pax_global_header00006660000000000000000000000064126555224050014520gustar00rootroot0000000000000052 comment=80f18448b510bcb1376c0b68bc70b98948e2b27a cakephp-2.8.0/000077500000000000000000000000001265552240500131425ustar00rootroot00000000000000cakephp-2.8.0/.editorconfig000066400000000000000000000004671265552240500156260ustar00rootroot00000000000000; This file is for unifying the coding style for different editors and IDEs. ; More information at http://editorconfig.org root = true [*] indent_style = tab end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true [*.bat] end_of_line = crlf [*.yml] indent_style = space indent_size = 2 cakephp-2.8.0/.gitattributes000066400000000000000000000014361265552240500160410ustar00rootroot00000000000000# Define the line ending behavior of the different file extensions # Set default behaviour, in case users don't have core.autocrlf set. * text=auto * text eol=lf # Explicitly declare text files we want to always be normalized and converted # to native line endings on checkout. *.php text *.default text *.ctp text *.sql text *.md text *.po text *.js text *.css text *.ini text *.properties text *.txt text *.xml text *.yml text .htaccess text # Declare files that will always have CRLF line endings on checkout. *.bat eol=crlf # Declare files that will always have LF line endings on checkout. *.pem eol=lf # Denote all files that are truly binary and should not be modified. *.png binary *.jpg binary *.gif binary *.ico binary *.mo binary *.pdf binary *.woff binary *.ttf binary *.eot binary cakephp-2.8.0/.gitignore000066400000000000000000000006511265552240500151340ustar00rootroot00000000000000# User specific & automatically generated files # ################################################# /app/Config/database.php /app/tmp /lib/Cake/Console/Templates/skel/tmp/ /plugins /vendors /build /dist /tags *.mo # IDE and editor specific files # ################################# /nbproject .idea # OS generated files # ###################### .DS_Store .DS_Store? ._* .Spotlight-V100 .Trashes Icon? ehthumbs.db Thumbs.db cakephp-2.8.0/.htaccess000066400000000000000000000001741265552240500147420ustar00rootroot00000000000000 RewriteEngine on RewriteRule ^$ app/webroot/ [L] RewriteRule (.*) app/webroot/$1 [L] cakephp-2.8.0/.travis.yml000066400000000000000000000076541265552240500152670ustar00rootroot00000000000000language: php php: - 5.3 - 5.4 - 5.5 - 5.6 - 7.0 env: - DB=mysql services: - memcached matrix: fast_finish: true include: - php: 5.4 env: DB=pgsql - php: 5.4 env: DB=sqlite - php: 5.4 env: PHPCS=1 before_script: - sh -c "composer global require 'phpunit/phpunit=3.7.33'" - sh -c "ln -s ~/.composer/vendor/phpunit/phpunit/PHPUnit ./vendors/PHPUnit" - sudo locale-gen de_DE - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'CREATE DATABASE cakephp_test;'; fi" - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'CREATE DATABASE cakephp_test2;'; fi" - sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'CREATE DATABASE cakephp_test3;'; fi" - sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'CREATE DATABASE cakephp_test;' -U postgres; fi" - sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'CREATE SCHEMA test2;' -U postgres -d cakephp_test; fi" - sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'CREATE SCHEMA test3;' -U postgres -d cakephp_test; fi" - chmod -R 777 ./app/tmp - if [[ ${TRAVIS_PHP_VERSION:0:3} == "5.3" ]] ; then pecl install timezonedb ; fi - sh -c "if [ '$PHPCS' = '1' ]; then composer global require 'cakephp/cakephp-codesniffer:1.*'; fi" - sh -c "if [ '$PHPCS' = '1' ]; then ~/.composer/vendor/bin/phpcs --config-set installed_paths ~/.composer/vendor/cakephp/cakephp-codesniffer; fi" - echo "extension = memcached.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini - phpenv rehash - set +H - echo " array( 'datasource' => 'Database/Mysql', 'host' => '0.0.0.0', 'login' => 'travis' ), 'pgsql' => array( 'datasource' => 'Database/Postgres', 'host' => '127.0.0.1', 'login' => 'postgres', 'database' => 'cakephp_test', 'schema' => array( 'default' => 'public', 'test' => 'public', 'test2' => 'test2', 'test_database_three' => 'test3' ) ), 'sqlite' => array( 'datasource' => 'Database/Sqlite', 'database' => array( 'default' => ':memory:', 'test' => ':memory:', 'test2' => '/tmp/cakephp_test2.db', 'test_database_three' => '/tmp/cakephp_test3.db' ), ) ); public \$default = array( 'persistent' => false, 'host' => '', 'login' => '', 'password' => '', 'database' => 'cakephp_test', 'prefix' => '' ); public \$test = array( 'persistent' => false, 'host' => '', 'login' => '', 'password' => '', 'database' => 'cakephp_test', 'prefix' => '' ); public \$test2 = array( 'persistent' => false, 'host' => '', 'login' => '', 'password' => '', 'database' => 'cakephp_test2', 'prefix' => '' ); public \$test_database_three = array( 'persistent' => false, 'host' => '', 'login' => '', 'password' => '', 'database' => 'cakephp_test3', 'prefix' => '' ); public function __construct() { \$db = 'mysql'; if (!empty(\$_SERVER['DB'])) { \$db = \$_SERVER['DB']; } foreach (array('default', 'test', 'test2', 'test_database_three') as \$source) { \$config = array_merge(\$this->{\$source}, \$this->identities[\$db]); if (is_array(\$config['database'])) { \$config['database'] = \$config['database'][\$source]; } if (!empty(\$config['schema']) && is_array(\$config['schema'])) { \$config['schema'] = \$config['schema'][\$source]; } \$this->{\$source} = \$config; } } }" > app/Config/database.php script: - sh -c "if [ '$PHPCS' != '1' ]; then ./lib/Cake/Console/cake test core AllTests --stderr; fi" - sh -c "if [ '$PHPCS' = '1' ]; then ~/.composer/vendor/bin/phpcs -p --extensions=php --standard=CakePHP ./lib/Cake; fi;" notifications: email: false cakephp-2.8.0/CONTRIBUTING.md000066400000000000000000000076031265552240500154010ustar00rootroot00000000000000# How to contribute CakePHP loves to welcome your contributions. There are several ways to help out: * Create an [issue](https://github.com/cakephp/cakephp/issues) on GitHub, if you have found a bug * Write test cases for open bug issues * Write patches for open bug/feature issues, preferably with test cases included * Contribute to the [documentation](https://github.com/cakephp/docs) There are a few guidelines that we need contributors to follow so that we have a chance of keeping on top of things. ## Code of Conduct Help us keep CakePHP open and inclusive. Please read and follow our [Code of Conduct](https://github.com/cakephp/code-of-conduct/blob/master/CODE_OF_CONDUCT.md). ## Getting Started * Make sure you have a [GitHub account](https://github.com/signup/free). * Submit an [issue](https://github.com/cakephp/cakephp/issues), assuming one does not already exist. * Clearly describe the issue including steps to reproduce when it is a bug. * Make sure you fill in the earliest version that you know has the issue. * Fork the repository on GitHub. ## Making Changes * Create a topic branch from where you want to base your work. * This is usually the master branch. * Only target release branches if you are certain your fix must be on that branch. * To quickly create a topic branch based on master; `git branch master/my_contribution master` then checkout the new branch with `git checkout master/my_contribution`. Better avoid working directly on the `master` branch, to avoid conflicts if you pull in updates from origin. * Make commits of logical units. * Check for unnecessary whitespace with `git diff --check` before committing. * Use descriptive commit messages and reference the #issue number. * Core test cases should continue to pass. You can run tests locally or enable [travis-ci](https://travis-ci.org/) for your fork, so all tests and codesniffs will be executed. * Your work should apply the [CakePHP coding standards](http://book.cakephp.org/2.0/en/contributing/cakephp-coding-conventions.html). ## Which branch to base the work * Bugfix branches will be based on master. * New features that are backwards compatible will be based on next minor release branch. * New features or other non backwards compatible changes will go in the next major release branch. ## Submitting Changes * Push your changes to a topic branch in your fork of the repository. * Submit a pull request to the repository in the cakephp organization, with the correct target branch. ## Test cases and codesniffer CakePHP tests requires [PHPUnit](http://www.phpunit.de/manual/current/en/installation.html) 3.7, version 4 is not compatible. To run the test cases locally use the following command: ./lib/Cake/Console/cake test core AllTests --stderr To run the sniffs for CakePHP coding standards: phpcs -p --extensions=php --standard=CakePHP ./lib/Cake Check the [cakephp-codesniffer](https://github.com/cakephp/cakephp-codesniffer) repository to setup the CakePHP standard. The [README](https://github.com/cakephp/cakephp-codesniffer/blob/master/README.md) contains installation info for the sniff and phpcs. ## Reporting a Security Issue If you've found a security related issue in CakePHP, please don't open an issue in GitHub. Instead contact us at security@cakephp.org. For more information on how we handle security issues, [see the CakePHP Security Issue Process](http://book.cakephp.org/2.0/en/contributing/tickets.html#reporting-security-issues). # Additional Resources * [CakePHP coding standards](http://book.cakephp.org/2.0/en/contributing/cakephp-coding-conventions.html) * [Existing issues](https://github.com/cakephp/cakephp/issues) * [Development Roadmaps](https://github.com/cakephp/cakephp/wiki#roadmaps) * [General GitHub documentation](https://help.github.com/) * [GitHub pull request documentation](https://help.github.com/send-pull-requests/) * #cakephp IRC channel on freenode.org cakephp-2.8.0/README.md000066400000000000000000000046351265552240500144310ustar00rootroot00000000000000# CakePHP [![Latest Stable Version](https://poser.pugx.org/cakephp/cakephp/v/stable.svg)](https://packagist.org/packages/cakephp/cakephp) [![License](https://poser.pugx.org/cakephp/cakephp/license.svg)](https://packagist.org/packages/cakephp/cakephp) [![Bake Status](https://secure.travis-ci.org/cakephp/cakephp.png?branch=master)](http://travis-ci.org/cakephp/cakephp) [![Code consistency](http://squizlabs.github.io/PHP_CodeSniffer/analysis/cakephp/cakephp/grade.svg)](http://squizlabs.github.io/PHP_CodeSniffer/analysis/cakephp/cakephp/) [![CakePHP](http://cakephp.org/img/cake-logo.png)](http://www.cakephp.org) CakePHP is a rapid development framework for PHP which uses commonly known design patterns like Active Record, Association Data Mapping, Front Controller and MVC. Our primary goal is to provide a structured framework that enables PHP users at all levels to rapidly develop robust web applications, without any loss to flexibility. ## Some Handy Links [CakePHP](http://www.cakephp.org) - The rapid development PHP framework [CookBook](http://book.cakephp.org) - THE CakePHP user documentation; start learning here! [API](http://api.cakephp.org) - A reference to CakePHP's classes [Plugins](http://plugins.cakephp.org/) - A repository of extensions to the framework [The Bakery](http://bakery.cakephp.org) - Tips, tutorials and articles [Community Center](http://community.cakephp.org) - A source for everything community related [Training](http://training.cakephp.org) - Join a live session and get skilled with the framework [CakeFest](http://cakefest.org) - Don't miss our annual CakePHP conference [Cake Software Foundation](http://cakefoundation.org) - Promoting development related to CakePHP ## Get Support! [#cakephp](http://webchat.freenode.net/?channels=#cakephp) on irc.freenode.net - Come chat with us, we have cake [Google Group](https://groups.google.com/group/cake-php) - Community mailing list and forum [GitHub Issues](https://github.com/cakephp/cakephp/issues) - Got issues? Please tell us! [Roadmaps](https://github.com/cakephp/cakephp/wiki#roadmaps) - Want to contribute? Get involved! ## Contributing [CONTRIBUTING.md](CONTRIBUTING.md) - Quick pointers for contributing to the CakePHP project [CookBook "Contributing" Section (2.x)](http://book.cakephp.org/2.0/en/contributing.html) [(3.0)](http://book.cakephp.org/3.0/en/contributing.html) - Version-specific details about contributing to the project cakephp-2.8.0/app/000077500000000000000000000000001265552240500137225ustar00rootroot00000000000000cakephp-2.8.0/app/.htaccess000066400000000000000000000001641265552240500155210ustar00rootroot00000000000000 RewriteEngine on RewriteRule ^$ webroot/ [L] RewriteRule (.*) webroot/$1 [L] cakephp-2.8.0/app/Config/000077500000000000000000000000001265552240500151275ustar00rootroot00000000000000cakephp-2.8.0/app/Config/Schema/000077500000000000000000000000001265552240500163275ustar00rootroot00000000000000cakephp-2.8.0/app/Config/Schema/db_acl.php000066400000000000000000000076241265552240500202550ustar00rootroot00000000000000 array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 'parent_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'model' => array('type' => 'string', 'null' => true), 'foreign_key' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'alias' => array('type' => 'string', 'null' => true), 'lft' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'rght' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'idx_acos_lft_rght' => array('column' => array('lft', 'rght'), 'unique' => 0), 'idx_acos_alias' => array('column' => 'alias', 'unique' => 0) ) ); /** * ARO - Access Request Object - Something that wants something */ public $aros = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 'parent_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'model' => array('type' => 'string', 'null' => true), 'foreign_key' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'alias' => array('type' => 'string', 'null' => true), 'lft' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'rght' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'idx_aros_lft_rght' => array('column' => array('lft', 'rght'), 'unique' => 0), 'idx_aros_alias' => array('column' => 'alias', 'unique' => 0) ) ); /** * Used by the Cake::Model:Permission class. * Checks if the given $aro has access to action $action in $aco. */ public $aros_acos = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 'aro_id' => array('type' => 'integer', 'null' => false, 'length' => 10, 'key' => 'index'), 'aco_id' => array('type' => 'integer', 'null' => false, 'length' => 10), '_create' => array('type' => 'string', 'null' => false, 'default' => '0', 'length' => 2), '_read' => array('type' => 'string', 'null' => false, 'default' => '0', 'length' => 2), '_update' => array('type' => 'string', 'null' => false, 'default' => '0', 'length' => 2), '_delete' => array('type' => 'string', 'null' => false, 'default' => '0', 'length' => 2), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'ARO_ACO_KEY' => array('column' => array('aro_id', 'aco_id'), 'unique' => 1), 'idx_aco_id' => array('column' => 'aco_id', 'unique' => 0) ) ); } cakephp-2.8.0/app/Config/Schema/db_acl.sql000066400000000000000000000030751265552240500202610ustar00rootroot00000000000000# $Id$ # # Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) # # Licensed under The MIT License # For full copyright and license information, please see the LICENSE.txt # Redistributions of files must retain the above copyright notice. # MIT License (http://www.opensource.org/licenses/mit-license.php) CREATE TABLE acos ( id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT, parent_id INTEGER(10) DEFAULT NULL, model VARCHAR(255) DEFAULT '', foreign_key INTEGER(10) UNSIGNED DEFAULT NULL, alias VARCHAR(255) DEFAULT '', lft INTEGER(10) DEFAULT NULL, rght INTEGER(10) DEFAULT NULL, PRIMARY KEY (id) ); CREATE TABLE aros_acos ( id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT, aro_id INTEGER(10) UNSIGNED NOT NULL, aco_id INTEGER(10) UNSIGNED NOT NULL, _create CHAR(2) NOT NULL DEFAULT 0, _read CHAR(2) NOT NULL DEFAULT 0, _update CHAR(2) NOT NULL DEFAULT 0, _delete CHAR(2) NOT NULL DEFAULT 0, PRIMARY KEY(id) ); CREATE TABLE aros ( id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT, parent_id INTEGER(10) DEFAULT NULL, model VARCHAR(255) DEFAULT '', foreign_key INTEGER(10) UNSIGNED DEFAULT NULL, alias VARCHAR(255) DEFAULT '', lft INTEGER(10) DEFAULT NULL, rght INTEGER(10) DEFAULT NULL, PRIMARY KEY (id) ); /* this indexes will improve acl perfomance */ CREATE INDEX idx_acos_lft_rght ON `acos` (`lft`, `rght`); CREATE INDEX idx_acos_alias ON `acos` (`alias`); CREATE INDEX idx_aros_lft_rght ON `aros` (`lft`, `rght`); CREATE INDEX idx_aros_alias ON `aros` (`alias`); CREATE INDEX idx_aco_id ON `aros_acos` (`aco_id`); cakephp-2.8.0/app/Config/Schema/i18n.php000066400000000000000000000042111265552240500176150ustar00rootroot00000000000000 array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 'locale' => array('type' => 'string', 'null' => false, 'length' => 6, 'key' => 'index'), 'model' => array('type' => 'string', 'null' => false, 'key' => 'index'), 'foreign_key' => array('type' => 'integer', 'null' => false, 'length' => 10, 'key' => 'index'), 'field' => array('type' => 'string', 'null' => false, 'key' => 'index'), 'content' => array('type' => 'text', 'null' => true, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), 'locale' => array('column' => 'locale', 'unique' => 0), 'model' => array('column' => 'model', 'unique' => 0), 'row_id' => array('column' => 'foreign_key', 'unique' => 0), 'field' => array('column' => 'field', 'unique' => 0)) ); } cakephp-2.8.0/app/Config/Schema/i18n.sql000066400000000000000000000015731265552240500176350ustar00rootroot00000000000000# $Id$ # # Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) # # Licensed under The MIT License # For full copyright and license information, please see the LICENSE.txt # Redistributions of files must retain the above copyright notice. # MIT License (http://www.opensource.org/licenses/mit-license.php) CREATE TABLE i18n ( id int(10) NOT NULL auto_increment, locale varchar(6) NOT NULL, model varchar(255) NOT NULL, foreign_key int(10) NOT NULL, field varchar(255) NOT NULL, content mediumtext, PRIMARY KEY (id), # UNIQUE INDEX I18N_LOCALE_FIELD(locale, model, foreign_key, field), # INDEX I18N_LOCALE_ROW(locale, model, foreign_key), # INDEX I18N_LOCALE_MODEL(locale, model), # INDEX I18N_FIELD(model, foreign_key, field), # INDEX I18N_ROW(model, foreign_key), INDEX locale (locale), INDEX model (model), INDEX row_id (foreign_key), INDEX field (field) );cakephp-2.8.0/app/Config/Schema/sessions.php000066400000000000000000000031571265552240500207140ustar00rootroot00000000000000 array('type' => 'string', 'null' => false, 'key' => 'primary'), 'data' => array('type' => 'text', 'null' => true, 'default' => null), 'expires' => array('type' => 'integer', 'null' => true, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)) ); } cakephp-2.8.0/app/Config/Schema/sessions.sql000066400000000000000000000010351265552240500207150ustar00rootroot00000000000000# $Id$ # # Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) # 1785 E. Sahara Avenue, Suite 490-204 # Las Vegas, Nevada 89104 # # Licensed under The MIT License # For full copyright and license information, please see the LICENSE.txt # Redistributions of files must retain the above copyright notice. # MIT License (http://www.opensource.org/licenses/mit-license.php) CREATE TABLE cake_sessions ( id varchar(255) NOT NULL default '', data text, expires int(11) default NULL, PRIMARY KEY (id) );cakephp-2.8.0/app/Config/acl.ini.php000066400000000000000000000037151265552240500171630ustar00rootroot00000000000000; ;/** ; * ACL Configuration ; * ; * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) ; * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) ; * ; * Licensed under The MIT License ; * Redistributions of files must retain the above copyright notice. ; * ; * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) ; * @link http://cakephp.org CakePHP(tm) Project ; * @package app.Config ; * @since CakePHP(tm) v 0.10.0.1076 ; * @license http://www.opensource.org/licenses/mit-license.php MIT License ; */ ; acl.ini.php - CakePHP ACL Configuration ; --------------------------------------------------------------------- ; Use this file to specify user permissions. ; aco = access control object (something in your application) ; aro = access request object (something requesting access) ; ; User records are added as follows: ; ; [uid] ; groups = group1, group2, group3 ; allow = aco1, aco2, aco3 ; deny = aco4, aco5, aco6 ; ; Group records are added in a similar manner: ; ; [gid] ; allow = aco1, aco2, aco3 ; deny = aco4, aco5, aco6 ; ; The allow, deny, and groups sections are all optional. ; NOTE: groups names *cannot* ever be the same as usernames! ; ; ACL permissions are checked in the following order: ; 1. Check for user denies (and DENY if specified) ; 2. Check for user allows (and ALLOW if specified) ; 3. Gather user's groups ; 4. Check group denies (and DENY if specified) ; 5. Check group allows (and ALLOW if specified) ; 6. If no aro, aco, or group information is found, DENY ; ; --------------------------------------------------------------------- ;------------------------------------- ;Users ;------------------------------------- [username-goes-here] groups = group1, group2 deny = aco1, aco2 allow = aco3, aco4 ;------------------------------------- ;Groups ;------------------------------------- [groupname-goes-here] deny = aco5, aco6 allow = aco7, aco8 cakephp-2.8.0/app/Config/acl.php000066400000000000000000000115051265552240500164010ustar00rootroot00000000000000Auth->authorize = array('Actions' => array('actionPath' => 'controllers/'),...) * * Now, when a user (i.e. jeff) authenticates successfully and requests a controller action (i.e. /invoices/delete) * that is not allowed by default (e.g. via $this->Auth->allow('edit') in the Invoices controller) then AuthComponent * will ask the configured ACL interface if access is granted. Under the assumptions 1. and 2. this will be * done via a call to Acl->check() with * * ``` * array('User' => array('username' => 'jeff', 'group_id' => 4, ...)) * ``` * * as ARO and * * ``` * '/controllers/invoices/delete' * ``` * * as ACO. * * If the configured map looks like * * ``` * $config['map'] = array( * 'User' => 'User/username', * 'Role' => 'User/group_id', * ); * ``` * * then PhpAcl will lookup if we defined a role like User/jeff. If that role is not found, PhpAcl will try to * find a definition for Role/4. If the definition isn't found then a default role (Role/default) will be used to * check rules for the given ACO. The search can be expanded by defining aliases in the alias configuration. * E.g. if you want to use a more readable name than Role/4 in your definitions you can define an alias like * * ``` * $config['alias'] = array( * 'Role/4' => 'Role/editor', * ); * ``` * * In the roles configuration you can define roles on the lhs and inherited roles on the rhs: * * ``` * $config['roles'] = array( * 'Role/admin' => null, * 'Role/accountant' => null, * 'Role/editor' => null, * 'Role/manager' => 'Role/editor, Role/accountant', * 'User/jeff' => 'Role/manager', * ); * ``` * * In this example manager inherits all rules from editor and accountant. Role/admin doesn't inherit from any role. * Lets define some rules: * * ``` * $config['rules'] = array( * 'allow' => array( * '*' => 'Role/admin', * 'controllers/users/(dashboard|profile)' => 'Role/default', * 'controllers/invoices/*' => 'Role/accountant', * 'controllers/articles/*' => 'Role/editor', * 'controllers/users/*' => 'Role/manager', * 'controllers/invoices/delete' => 'Role/manager', * ), * 'deny' => array( * 'controllers/invoices/delete' => 'Role/accountant, User/jeff', * 'controllers/articles/(delete|publish)' => 'Role/editor', * ), * ); * ``` * * Ok, so as jeff inherits from Role/manager he's matched every rule that references User/jeff, Role/manager, * Role/editor, and Role/accountant. However, for jeff, rules for User/jeff are more specific than * rules for Role/manager, rules for Role/manager are more specific than rules for Role/editor and so on. * This is important when allow and deny rules match for a role. E.g. Role/accountant is allowed * controllers/invoices/* but at the same time controllers/invoices/delete is denied. But there is a more * specific rule defined for Role/manager which is allowed controllers/invoices/delete. However, the most specific * rule denies access to the delete action explicitly for User/jeff, so he'll be denied access to the resource. * * If we would remove the role definition for User/jeff, then jeff would be granted access as he would be resolved * to Role/manager and Role/manager has an allow rule. */ /** * The role map defines how to resolve the user record from your application * to the roles you defined in the roles configuration. */ $config['map'] = array( 'User' => 'User/username', 'Role' => 'User/group_id', ); /** * define aliases to map your model information to * the roles defined in your role configuration. */ $config['alias'] = array( 'Role/4' => 'Role/editor', ); /** * role configuration */ $config['roles'] = array( 'Role/admin' => null, ); /** * rule configuration */ $config['rules'] = array( 'allow' => array( '*' => 'Role/admin', ), 'deny' => array(), ); cakephp-2.8.0/app/Config/bootstrap.php000066400000000000000000000124601265552240500176600ustar00rootroot00000000000000 'File')); /** * The settings below can be used to set additional paths to models, views and controllers. * * App::build(array( * 'Model' => array('/path/to/models/', '/next/path/to/models/'), * 'Model/Behavior' => array('/path/to/behaviors/', '/next/path/to/behaviors/'), * 'Model/Datasource' => array('/path/to/datasources/', '/next/path/to/datasources/'), * 'Model/Datasource/Database' => array('/path/to/databases/', '/next/path/to/database/'), * 'Model/Datasource/Session' => array('/path/to/sessions/', '/next/path/to/sessions/'), * 'Controller' => array('/path/to/controllers/', '/next/path/to/controllers/'), * 'Controller/Component' => array('/path/to/components/', '/next/path/to/components/'), * 'Controller/Component/Auth' => array('/path/to/auths/', '/next/path/to/auths/'), * 'Controller/Component/Acl' => array('/path/to/acls/', '/next/path/to/acls/'), * 'View' => array('/path/to/views/', '/next/path/to/views/'), * 'View/Helper' => array('/path/to/helpers/', '/next/path/to/helpers/'), * 'Console' => array('/path/to/consoles/', '/next/path/to/consoles/'), * 'Console/Command' => array('/path/to/commands/', '/next/path/to/commands/'), * 'Console/Command/Task' => array('/path/to/tasks/', '/next/path/to/tasks/'), * 'Lib' => array('/path/to/libs/', '/next/path/to/libs/'), * 'Locale' => array('/path/to/locales/', '/next/path/to/locales/'), * 'Vendor' => array('/path/to/vendors/', '/next/path/to/vendors/'), * 'Plugin' => array('/path/to/plugins/', '/next/path/to/plugins/'), * )); */ /** * Custom Inflector rules can be set to correctly pluralize or singularize table, model, controller names or whatever other * string is passed to the inflection functions * * Inflector::rules('singular', array('rules' => array(), 'irregular' => array(), 'uninflected' => array())); * Inflector::rules('plural', array('rules' => array(), 'irregular' => array(), 'uninflected' => array())); */ /** * Plugins need to be loaded manually, you can either load them one by one or all of them in a single call * Uncomment one of the lines below, as you need. Make sure you read the documentation on CakePlugin to use more * advanced ways of loading plugins * * CakePlugin::loadAll(); // Loads all plugins at once * CakePlugin::load('DebugKit'); // Loads a single plugin named DebugKit */ /** * To prefer app translation over plugin translation, you can set * * Configure::write('I18n.preferApp', true); */ /** * You can attach event listeners to the request lifecycle as Dispatcher Filter. By default CakePHP bundles two filters: * * - AssetDispatcher filter will serve your asset files (css, images, js, etc) from your themes and plugins * - CacheDispatcher filter will read the Cache.check configure variable and try to serve cached content generated from controllers * * Feel free to remove or add filters as you see fit for your application. A few examples: * * Configure::write('Dispatcher.filters', array( * 'MyCacheFilter', // will use MyCacheFilter class from the Routing/Filter package in your app. * 'MyCacheFilter' => array('prefix' => 'my_cache_'), // will use MyCacheFilter class from the Routing/Filter package in your app with settings array. * 'MyPlugin.MyFilter', // will use MyFilter class from the Routing/Filter package in MyPlugin plugin. * array('callable' => $aFunction, 'on' => 'before', 'priority' => 9), // A valid PHP callback type to be called on beforeDispatch * array('callable' => $anotherMethod, 'on' => 'after'), // A valid PHP callback type to be called on afterDispatch * * )); */ Configure::write('Dispatcher.filters', array( 'AssetDispatcher', 'CacheDispatcher' )); /** * Configures default file logging options */ App::uses('CakeLog', 'Log'); CakeLog::config('debug', array( 'engine' => 'File', 'types' => array('notice', 'info', 'debug'), 'file' => 'debug', )); CakeLog::config('error', array( 'engine' => 'File', 'types' => array('warning', 'error', 'critical', 'alert', 'emergency'), 'file' => 'error', )); cakephp-2.8.0/app/Config/core.php000066400000000000000000000350011265552240500165670ustar00rootroot00000000000000 0 * and log errors with CakeLog when debug = 0. * * Options: * * - `handler` - callback - The callback to handle errors. You can set this to any callable type, * including anonymous functions. * Make sure you add App::uses('MyHandler', 'Error'); when using a custom handler class * - `level` - integer - The level of errors you are interested in capturing. * - `trace` - boolean - Include stack traces for errors in log files. * * @see ErrorHandler for more information on error handling and configuration. */ Configure::write('Error', array( 'handler' => 'ErrorHandler::handleError', 'level' => E_ALL & ~E_DEPRECATED, 'trace' => true )); /** * Configure the Exception handler used for uncaught exceptions. By default, * ErrorHandler::handleException() is used. It will display a HTML page for the exception, and * while debug > 0, framework errors like Missing Controller will be displayed. When debug = 0, * framework errors will be coerced into generic HTTP errors. * * Options: * * - `handler` - callback - The callback to handle exceptions. You can set this to any callback type, * including anonymous functions. * Make sure you add App::uses('MyHandler', 'Error'); when using a custom handler class * - `renderer` - string - The class responsible for rendering uncaught exceptions. If you choose a custom class you * should place the file for that class in app/Lib/Error. This class needs to implement a render method. * - `log` - boolean - Should Exceptions be logged? * - `extraFatalErrorMemory` - integer - Increases memory limit at shutdown so fatal errors are logged. Specify * amount in megabytes or use 0 to disable (default: 4 MB) * - `skipLog` - array - list of exceptions to skip for logging. Exceptions that * extend one of the listed exceptions will also be skipped for logging. * Example: `'skipLog' => array('NotFoundException', 'UnauthorizedException')` * * @see ErrorHandler for more information on exception handling and configuration. */ Configure::write('Exception', array( 'handler' => 'ErrorHandler::handleException', 'renderer' => 'ExceptionRenderer', 'log' => true )); /** * Application wide charset encoding */ Configure::write('App.encoding', 'UTF-8'); /** * To configure CakePHP *not* to use mod_rewrite and to * use CakePHP pretty URLs, remove these .htaccess * files: * * /.htaccess * /app/.htaccess * /app/webroot/.htaccess * * And uncomment the App.baseUrl below. But keep in mind * that plugin assets such as images, CSS and JavaScript files * will not work without URL rewriting! * To work around this issue you should either symlink or copy * the plugin assets into you app's webroot directory. This is * recommended even when you are using mod_rewrite. Handling static * assets through the Dispatcher is incredibly inefficient and * included primarily as a development convenience - and * thus not recommended for production applications. */ //Configure::write('App.baseUrl', env('SCRIPT_NAME')); /** * To configure CakePHP to use a particular domain URL * for any URL generation inside the application, set the following * configuration variable to the http(s) address to your domain. This * will override the automatic detection of full base URL and can be * useful when generating links from the CLI (e.g. sending emails) */ //Configure::write('App.fullBaseUrl', 'http://example.com'); /** * Web path to the public images directory under webroot. * If not set defaults to 'img/' */ //Configure::write('App.imageBaseUrl', 'img/'); /** * Web path to the CSS files directory under webroot. * If not set defaults to 'css/' */ //Configure::write('App.cssBaseUrl', 'css/'); /** * Web path to the js files directory under webroot. * If not set defaults to 'js/' */ //Configure::write('App.jsBaseUrl', 'js/'); /** * Uncomment the define below to use CakePHP prefix routes. * * The value of the define determines the names of the routes * and their associated controller actions: * * Set to an array of prefixes you want to use in your application. Use for * admin or other prefixed routes. * * Routing.prefixes = array('admin', 'manager'); * * Enables: * `admin_index()` and `/admin/controller/index` * `manager_index()` and `/manager/controller/index` */ //Configure::write('Routing.prefixes', array('admin')); /** * Turn off all caching application-wide. */ //Configure::write('Cache.disable', true); /** * Enable cache checking. * * If set to true, for view caching you must still use the controller * public $cacheAction inside your controllers to define caching settings. * You can either set it controller-wide by setting public $cacheAction = true, * or in each action using $this->cacheAction = true. */ //Configure::write('Cache.check', true); /** * Enable cache view prefixes. * * If set it will be prepended to the cache name for view file caching. This is * helpful if you deploy the same application via multiple subdomains and languages, * for instance. Each version can then have its own view cache namespace. * Note: The final cache file name will then be `prefix_cachefilename`. */ //Configure::write('Cache.viewPrefix', 'prefix'); /** * Session configuration. * * Contains an array of settings to use for session configuration. The defaults key is * used to define a default preset to use for sessions, any settings declared here will override * the settings of the default config. * * ## Options * * - `Session.cookie` - The name of the cookie to use. Defaults to 'CAKEPHP' * - `Session.timeout` - The number of minutes you want sessions to live for. This timeout is handled by CakePHP * - `Session.cookieTimeout` - The number of minutes you want session cookies to live for. * - `Session.checkAgent` - Do you want the user agent to be checked when starting sessions? You might want to set the * value to false, when dealing with older versions of IE, Chrome Frame or certain web-browsing devices and AJAX * - `Session.defaults` - The default configuration set to use as a basis for your session. * There are four builtins: php, cake, cache, database. * - `Session.handler` - Can be used to enable a custom session handler. Expects an array of callables, * that can be used with `session_save_handler`. Using this option will automatically add `session.save_handler` * to the ini array. * - `Session.autoRegenerate` - Enabling this setting, turns on automatic renewal of sessions, and * sessionids that change frequently. See CakeSession::$requestCountdown. * - `Session.cacheLimiter` - Configure the cache control headers used for the session cookie. * See http://php.net/session_cache_limiter for accepted values. * - `Session.ini` - An associative array of additional ini values to set. * * The built in defaults are: * * - 'php' - Uses settings defined in your php.ini. * - 'cake' - Saves session files in CakePHP's /tmp directory. * - 'database' - Uses CakePHP's database sessions. * - 'cache' - Use the Cache class to save sessions. * * To define a custom session handler, save it at /app/Model/Datasource/Session/.php. * Make sure the class implements `CakeSessionHandlerInterface` and set Session.handler to * * To use database sessions, run the app/Config/Schema/sessions.php schema using * the cake shell command: cake schema create Sessions */ Configure::write('Session', array( 'defaults' => 'php' )); /** * A random string used in security hashing methods. */ Configure::write('Security.salt', 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi'); /** * A random numeric string (digits only) used to encrypt/decrypt strings. */ Configure::write('Security.cipherSeed', '76859309657453542496749683645'); /** * Apply timestamps with the last modified time to static assets (js, css, images). * Will append a query string parameter containing the time the file was modified. This is * useful for invalidating browser caches. * * Set to `true` to apply timestamps when debug > 0. Set to 'force' to always enable * timestamping regardless of debug value. */ //Configure::write('Asset.timestamp', true); /** * Compress CSS output by removing comments, whitespace, repeating tags, etc. * This requires a/var/cache directory to be writable by the web server for caching. * and /vendors/csspp/csspp.php * * To use, prefix the CSS link URL with '/ccss/' instead of '/css/' or use HtmlHelper::css(). */ //Configure::write('Asset.filter.css', 'css.php'); /** * Plug in your own custom JavaScript compressor by dropping a script in your webroot to handle the * output, and setting the config below to the name of the script. * * To use, prefix your JavaScript link URLs with '/cjs/' instead of '/js/' or use JsHelper::link(). */ //Configure::write('Asset.filter.js', 'custom_javascript_output_filter.php'); /** * The class name and database used in CakePHP's * access control lists. */ Configure::write('Acl.classname', 'DbAcl'); Configure::write('Acl.database', 'default'); /** * Uncomment this line and correct your server timezone to fix * any date & time related errors. */ //date_default_timezone_set('UTC'); /** * `Config.timezone` is available in which you can set users' timezone string. * If a method of CakeTime class is called with $timezone parameter as null and `Config.timezone` is set, * then the value of `Config.timezone` will be used. This feature allows you to set users' timezone just * once instead of passing it each time in function calls. */ //Configure::write('Config.timezone', 'Europe/Paris'); /** * 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' => 0664, //[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) * )); * * Memcached (http://www.danga.com/memcached/) * * Uses the memcached extension. See http://php.net/memcached * * Cache::config('default', array( * 'engine' => 'Memcached', //[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' => 'my_connection', // [optional] The name of the persistent connection. * 'compress' => false, // [optional] compress data in Memcached (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 * )); */ /** * Configure the cache handlers that CakePHP will use for internal * metadata like class maps, and model schema. * * By default File is used, but for improved performance you should use APC. * * Note: 'default' and other application caches should be configured in app/Config/bootstrap.php. * Please check the comments in bootstrap.php for more info on the cache engines available * and their settings. */ $engine = 'File'; // In development mode, caches should expire quickly. $duration = '+999 days'; if (Configure::read('debug') > 0) { $duration = '+10 seconds'; } // Prefix each application on the same server with a different string, to avoid Memcache and APC conflicts. $prefix = 'myapp_'; /** * Configure the cache used for general framework caching. Path information, * object listings, and translation cache files are stored with this configuration. */ Cache::config('_cake_core_', array( 'engine' => $engine, 'prefix' => $prefix . 'cake_core_', 'path' => CACHE . 'persistent' . DS, 'serialize' => ($engine === 'File'), 'duration' => $duration )); /** * Configure the cache for model and datasource caches. This cache configuration * is used to store schema descriptions, and table listings in connections. */ Cache::config('_cake_model_', array( 'engine' => $engine, 'prefix' => $prefix . 'cake_model_', 'path' => CACHE . 'models' . DS, 'serialize' => ($engine === 'File'), 'duration' => $duration )); cakephp-2.8.0/app/Config/database.php.default000066400000000000000000000062001265552240500210250ustar00rootroot00000000000000 The name of a supported datasource; valid options are as follows: * Database/Mysql - MySQL 4 & 5, * Database/Sqlite - SQLite (PHP5 only), * Database/Postgres - PostgreSQL 7 and higher, * Database/Sqlserver - Microsoft SQL Server 2005 and higher * * You can add custom database datasources (or override existing datasources) by adding the * appropriate file to app/Model/Datasource/Database. Datasources should be named 'MyDatasource.php', * * * persistent => true / false * Determines whether or not the database should use a persistent connection * * host => * the host you connect to the database. To add a socket or port number, use 'port' => # * * prefix => * Uses the given prefix for all the tables in this database. This setting can be overridden * on a per-table basis with the Model::$tablePrefix property. * * schema => * For Postgres/Sqlserver specifies which schema you would like to use the tables in. * Postgres defaults to 'public'. For Sqlserver, it defaults to empty and use * the connected user's default schema (typically 'dbo'). * * encoding => * For MySQL, Postgres specifies the character encoding to use when connecting to the * database. Uses database default not specified. * * sslmode => * For Postgres specifies whether to 'disable', 'allow', 'prefer', or 'require' SSL for the * connection. The default value is 'allow'. * * unix_socket => * For MySQL to connect via socket specify the `unix_socket` parameter instead of `host` and `port` * * settings => * Array of key/value pairs, on connection it executes SET statements for each pair * For MySQL : http://dev.mysql.com/doc/refman/5.6/en/set-statement.html * For Postgres : http://www.postgresql.org/docs/9.2/static/sql-set.html * For Sql Server : http://msdn.microsoft.com/en-us/library/ms190356.aspx * * flags => * A key/value array of driver specific connection options. */ class DATABASE_CONFIG { public $default = array( 'datasource' => 'Database/Mysql', 'persistent' => false, 'host' => 'localhost', 'login' => 'user', 'password' => 'password', 'database' => 'database_name', 'prefix' => '', //'encoding' => 'utf8', ); public $test = array( 'datasource' => 'Database/Mysql', 'persistent' => false, 'host' => 'localhost', 'login' => 'user', 'password' => 'password', 'database' => 'test_database_name', 'prefix' => '', //'encoding' => 'utf8', ); } cakephp-2.8.0/app/Config/email.php.default000066400000000000000000000046701265552240500203610ustar00rootroot00000000000000 The name of a supported transport; valid options are as follows: * Mail - Send using PHP mail function * Smtp - Send using SMTP * Debug - Do not send the email, just return the result * * You can add custom transports (or override existing transports) by adding the * appropriate file to app/Network/Email. Transports should be named 'YourTransport.php', * where 'Your' is the name of the transport. * * from => * The origin email. See CakeEmail::from() about the valid values */ class EmailConfig { public $default = array( 'transport' => 'Mail', 'from' => 'you@localhost', //'charset' => 'utf-8', //'headerCharset' => 'utf-8', ); public $smtp = array( 'transport' => 'Smtp', 'from' => array('site@localhost' => 'My Site'), 'host' => 'localhost', 'port' => 25, 'timeout' => 30, 'username' => 'user', 'password' => 'secret', 'client' => null, 'log' => false, //'charset' => 'utf-8', //'headerCharset' => 'utf-8', ); public $fast = array( 'from' => 'you@localhost', 'sender' => null, 'to' => null, 'cc' => null, 'bcc' => null, 'replyTo' => null, 'readReceipt' => null, 'returnPath' => null, 'messageId' => true, 'subject' => null, 'message' => null, 'headers' => null, 'viewRender' => null, 'template' => false, 'layout' => false, 'viewVars' => null, 'attachments' => null, 'emailFormat' => null, 'transport' => 'Smtp', 'host' => 'localhost', 'port' => 25, 'timeout' => 30, 'username' => 'user', 'password' => 'secret', 'client' => null, 'log' => true, //'charset' => 'utf-8', //'headerCharset' => 'utf-8', ); } cakephp-2.8.0/app/Config/routes.php000066400000000000000000000031521265552240500171620ustar00rootroot00000000000000 'pages', 'action' => 'display', 'home')); /** * ...and connect the rest of 'Pages' controller's URLs. */ Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display')); /** * Load all plugin routes. See the CakePlugin documentation on * how to customize the loading of plugin routes. */ CakePlugin::routes(); /** * Load the CakePHP default routes. Only remove this if you do not want to use * the built-in default routes. */ require CAKE . 'Config' . DS . 'routes.php'; cakephp-2.8.0/app/Console/000077500000000000000000000000001265552240500153245ustar00rootroot00000000000000cakephp-2.8.0/app/Console/Command/000077500000000000000000000000001265552240500167025ustar00rootroot00000000000000cakephp-2.8.0/app/Console/Command/AppShell.php000066400000000000000000000015261265552240500211270ustar00rootroot00000000000000redirect('/'); } $page = $subpage = $title_for_layout = null; if (!empty($path[0])) { $page = $path[0]; } if (!empty($path[1])) { $subpage = $path[1]; } if (!empty($path[$count - 1])) { $title_for_layout = Inflector::humanize($path[$count - 1]); } $this->set(compact('page', 'subpage', 'title_for_layout')); try { $this->render(implode('/', $path)); } catch (MissingViewException $e) { if (Configure::read('debug')) { throw $e; } throw new NotFoundException(); } } } cakephp-2.8.0/app/Lib/000077500000000000000000000000001265552240500144305ustar00rootroot00000000000000cakephp-2.8.0/app/Lib/empty000066400000000000000000000000001265552240500154770ustar00rootroot00000000000000cakephp-2.8.0/app/Locale/000077500000000000000000000000001265552240500151215ustar00rootroot00000000000000cakephp-2.8.0/app/Locale/eng/000077500000000000000000000000001265552240500156725ustar00rootroot00000000000000cakephp-2.8.0/app/Locale/eng/LC_MESSAGES/000077500000000000000000000000001265552240500174575ustar00rootroot00000000000000cakephp-2.8.0/app/Locale/eng/LC_MESSAGES/empty000066400000000000000000000000001265552240500205260ustar00rootroot00000000000000cakephp-2.8.0/app/Model/000077500000000000000000000000001265552240500147625ustar00rootroot00000000000000cakephp-2.8.0/app/Model/AppModel.php000066400000000000000000000017621265552240500172020ustar00rootroot00000000000000 ' . $line . "

\n"; endforeach; ?> cakephp-2.8.0/app/View/Emails/text/000077500000000000000000000000001265552240500170325ustar00rootroot00000000000000cakephp-2.8.0/app/View/Emails/text/default.ctp000066400000000000000000000012451265552240500211700ustar00rootroot00000000000000 cakephp-2.8.0/app/View/Errors/000077500000000000000000000000001265552240500161105ustar00rootroot00000000000000cakephp-2.8.0/app/View/Errors/error400.ctp000066400000000000000000000017271265552240500202040ustar00rootroot00000000000000

: '{$url}'" ); ?>

0): echo $this->element('exception_stack_trace'); endif; ?> cakephp-2.8.0/app/View/Errors/error500.ctp000066400000000000000000000016311265552240500201770ustar00rootroot00000000000000

:

0): echo $this->element('exception_stack_trace'); endif; ?> cakephp-2.8.0/app/View/Helper/000077500000000000000000000000001265552240500160535ustar00rootroot00000000000000cakephp-2.8.0/app/View/Helper/AppHelper.php000066400000000000000000000017711265552240500204520ustar00rootroot00000000000000 <?php echo $this->fetch('title'); ?> fetch('content'); ?>

This email was sent using the CakePHP Framework

cakephp-2.8.0/app/View/Layouts/Emails/text/000077500000000000000000000000001265552240500204725ustar00rootroot00000000000000cakephp-2.8.0/app/View/Layouts/Emails/text/default.ctp000066400000000000000000000014011265552240500226220ustar00rootroot00000000000000 fetch('content'); ?> This email was sent using the CakePHP Framework, http://cakephp.org. cakephp-2.8.0/app/View/Layouts/ajax.ctp000066400000000000000000000012601265552240500177260ustar00rootroot00000000000000 fetch('content'); ?> cakephp-2.8.0/app/View/Layouts/default.ctp000066400000000000000000000034031265552240500204300ustar00rootroot00000000000000 Html->charset(); ?> <?php echo $cakeDescription ?>: <?php echo $this->fetch('title'); ?> Html->meta('icon'); echo $this->Html->css('cake.generic'); echo $this->fetch('meta'); echo $this->fetch('css'); echo $this->fetch('script'); ?>
Flash->render(); ?> fetch('content'); ?>
element('sql_dump'); ?> cakephp-2.8.0/app/View/Layouts/error.ctp000066400000000000000000000031721265552240500201400ustar00rootroot00000000000000 Html->charset(); ?> <?php echo $cakeDescription ?>: <?php echo $this->fetch('title'); ?> Html->meta('icon'); echo $this->Html->css('cake.generic'); echo $this->fetch('meta'); echo $this->fetch('css'); echo $this->fetch('script'); ?>
Session->flash(); ?> fetch('content'); ?>
element('sql_dump'); ?> cakephp-2.8.0/app/View/Layouts/flash.ctp000066400000000000000000000021751265552240500201060ustar00rootroot00000000000000 Html->charset(); ?> <?php echo $pageTitle; ?> ', $pause, $url); endif; ?>

Html->link($message, $url); ?>

cakephp-2.8.0/app/View/Layouts/js/000077500000000000000000000000001265552240500167105ustar00rootroot00000000000000cakephp-2.8.0/app/View/Layouts/js/default.ctp000066400000000000000000000001651265552240500210460ustar00rootroot00000000000000fetch('script'); ?> cakephp-2.8.0/app/View/Layouts/rss/000077500000000000000000000000001265552240500171035ustar00rootroot00000000000000cakephp-2.8.0/app/View/Layouts/rss/default.ctp000066400000000000000000000003611265552240500212370ustar00rootroot00000000000000fetch('title'); endif; echo $this->Rss->document( $this->Rss->channel( array(), $channel, $this->fetch('content') ) ); cakephp-2.8.0/app/View/Layouts/xml/000077500000000000000000000000001265552240500170745ustar00rootroot00000000000000cakephp-2.8.0/app/View/Layouts/xml/default.ctp000066400000000000000000000000471265552240500212310ustar00rootroot00000000000000fetch('content'); ?> cakephp-2.8.0/app/View/Pages/000077500000000000000000000000001265552240500156735ustar00rootroot00000000000000cakephp-2.8.0/app/View/Pages/home.ctp000066400000000000000000000216001265552240500173320ustar00rootroot00000000000000

Html->link(__d('cake_dev', 'Read the changelog'), 'http://cakephp.org/changelogs/' . Configure::version()); ?>

0): Debugger::checkSecurityKeys(); endif; ?>

1) Help me configure it 2) I don't / can't use URL rewriting

=')): echo ''; echo __d('cake_dev', 'Your version of PHP is 5.2.8 or higher.'); echo ''; else: echo ''; echo __d('cake_dev', 'Your version of PHP is too low. You need PHP 5.2.8 or higher to use CakePHP.'); echo ''; endif; ?>

'; echo __d('cake_dev', 'Your tmp directory is writable.'); echo ''; else: echo ''; echo __d('cake_dev', 'Your tmp directory is NOT writable.'); echo ''; endif; ?>

'; echo __d('cake_dev', 'The %s is being used for core caching. To change the config edit %s', '' . $settings['engine'] . 'Engine', 'APP/Config/core.php'); echo ''; else: echo ''; echo __d('cake_dev', 'Your cache is NOT working. Please check the settings in %s', 'APP/Config/core.php'); echo ''; endif; ?>

'; echo __d('cake_dev', 'Your database configuration file is present.'); $filePresent = true; echo ''; else: echo ''; echo __d('cake_dev', 'Your database configuration file is NOT present.'); echo '
'; echo __d('cake_dev', 'Rename %s to %s', 'APP/Config/database.php.default', 'APP/Config/database.php'); echo '
'; endif; ?>

getMessage(); if (method_exists($connectionError, 'getAttributes')): $attributes = $connectionError->getAttributes(); if (isset($errorMsg['message'])): $errorMsg .= '
' . $attributes['message']; endif; endif; } ?>

isConnected()): echo ''; echo __d('cake_dev', 'CakePHP is able to connect to the database.'); echo ''; else: echo ''; echo __d('cake_dev', 'CakePHP is NOT able to connect to the database.'); echo '

'; echo $errorMsg; echo '
'; endif; ?>

'; echo __d('cake_dev', 'PCRE has not been compiled with Unicode support.'); echo '
'; echo __d('cake_dev', 'Recompile PCRE with Unicode support by adding --enable-unicode-properties when configuring'); echo '

'; endif; ?>

'; echo __d('cake_dev', 'DebugKit plugin is present'); echo ''; else: echo ''; echo __d('cake_dev', 'DebugKit is not installed. It will help you inspect and debug different aspects of your application.'); echo '
'; echo __d('cake_dev', 'You can install it from %s', $this->Html->link('GitHub', 'https://github.com/cakephp/debug_kit/tree/2.2')); echo '
'; endif; ?>

To change its layout, edit: %s.
You can also add some CSS styles for your pages at: %s.', 'APP/View/Pages/home.ctp', 'APP/View/Layouts/default.ctp', 'APP/webroot/css'); ?>

Html->link( sprintf('%s %s', __d('cake_dev', 'New'), __d('cake_dev', 'CakePHP 2.0 Docs')), 'http://book.cakephp.org/2.0/en/', array('target' => '_blank', 'escape' => false) ); ?>

Html->link( __d('cake_dev', 'The 15 min Blog Tutorial'), 'http://book.cakephp.org/2.0/en/tutorials-and-examples/blog/blog.html', array('target' => '_blank', 'escape' => false) ); ?>

cakephp-2.8.0/app/View/Scaffolds/000077500000000000000000000000001265552240500165405ustar00rootroot00000000000000cakephp-2.8.0/app/View/Scaffolds/empty000066400000000000000000000000001265552240500176070ustar00rootroot00000000000000cakephp-2.8.0/app/index.php000066400000000000000000000012611265552240500155420ustar00rootroot00000000000000 RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] cakephp-2.8.0/app/webroot/css/000077500000000000000000000000001265552240500161735ustar00rootroot00000000000000cakephp-2.8.0/app/webroot/css/cake.generic.css000066400000000000000000000361451265552240500212340ustar00rootroot00000000000000@charset "utf-8"; /** * Generic CSS for CakePHP * * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://cakephp.org CakePHP(tm) Project * @package app.webroot.css * @license http://www.opensource.org/licenses/mit-license.php MIT License */ * { margin:0; padding:0; } /** General Style Info **/ body { background: #003d4c; color: #fff; font-family:'lucida grande',verdana,helvetica,arial,sans-serif; font-size:90%; margin: 0; } a { color: #003d4c; text-decoration: underline; font-weight: bold; } a:hover { color: #367889; text-decoration:none; } a img { border:none; } h1, h2, h3, h4 { font-weight: normal; margin-bottom:0.5em; } h1 { background:#fff; color: #003d4c; font-size: 100%; } h2 { background:#fff; color: #e32; font-family:'Gill Sans','lucida grande', helvetica, arial, sans-serif; font-size: 190%; } h3 { color: #2c6877; font-family:'Gill Sans','lucida grande', helvetica, arial, sans-serif; font-size: 165%; } h4 { color: #993; font-weight: normal; } ul, li { margin: 0 12px; } p { margin: 0 0 1em 0; } /** Layout **/ #container { text-align: left; } #header{ padding: 10px 20px; } #header h1 { line-height:20px; background: #003d4c url('../img/cake.icon.png') no-repeat left; color: #fff; padding: 0 30px; } #header h1 a { color: #fff; background: #003d4c; font-weight: normal; text-decoration: none; } #header h1 a:hover { color: #fff; background: #003d4c; text-decoration: underline; } #content{ background: #fff; clear: both; color: #333; padding: 10px 20px 40px 20px; overflow: auto; } #footer { clear: both; padding: 6px 10px; } #header a, #footer a { color: #fff; } #cake-powered { float: right; } /** containers **/ div.form, div.index, div.view { float:right; width:76%; border-left:1px solid #666; padding:10px 2%; } div.actions { float:left; width:16%; padding:10px 1.5%; } div.actions h3 { padding-top:0; color:#777; } /** Tables **/ table { border-right:0; clear: both; color: #333; margin-bottom: 10px; width: 100%; } th { border:0; border-bottom:2px solid #555; text-align: left; padding:4px; } th a { display: block; padding: 2px 4px; text-decoration: none; } th a.asc:after { content: ' โ‡ฃ'; } th a.desc:after { content: ' โ‡ก'; } table tr td { padding: 6px; text-align: left; vertical-align: top; border-bottom:1px solid #ddd; } table tr:nth-child(even) { background: #f9f9f9; } td.actions { text-align: center; white-space: nowrap; } table td.actions a { margin: 0 6px; padding:2px 5px; } /* SQL log */ .cake-sql-log { background: #fff; } .cake-sql-log td { padding: 4px 8px; text-align: left; font-family: Monaco, Consolas, "Courier New", monospaced; } .cake-sql-log caption { color:#fff; } /** Paging **/ .paging { background:#fff; color: #ccc; margin-top: 1em; clear:both; } .paging .current, .paging .disabled, .paging a { text-decoration: none; padding: 5px 8px; display: inline-block } .paging > span { display: inline-block; border: 1px solid #ccc; border-left: 0; } .paging > span:hover { background: #efefef; } .paging .prev { border-left: 1px solid #ccc; -moz-border-radius: 4px 0 0 4px; -webkit-border-radius: 4px 0 0 4px; border-radius: 4px 0 0 4px; } .paging .next { -moz-border-radius: 0 4px 4px 0; -webkit-border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0; } .paging .disabled { color: #ddd; } .paging .disabled:hover { background: transparent; } .paging .current { background: #efefef; color: #c73e14; } /** Scaffold View **/ dl { line-height: 2em; margin: 0em 0em; width: 60%; } dl dd:nth-child(4n+2), dl dt:nth-child(4n+1) { background: #f4f4f4; } dt { font-weight: bold; padding-left: 4px; vertical-align: top; width: 10em; } dd { margin-left: 10em; margin-top: -2em; vertical-align: top; } /** Forms **/ form { clear: both; margin-right: 20px; padding: 0; width: 95%; } fieldset { border: none; margin-bottom: 1em; padding: 16px 10px; } fieldset legend { color: #e32; font-size: 160%; font-weight: bold; } fieldset fieldset { margin-top: 0; padding: 10px 0 0; } fieldset fieldset legend { font-size: 120%; font-weight: normal; } fieldset fieldset div { clear: left; margin: 0 20px; } form div { clear: both; margin-bottom: 1em; padding: .5em; vertical-align: text-top; } form .input { color: #444; } form .required { font-weight: bold; } form .required label:after { color: #e32; content: '*'; display:inline; } form div.submit { border: 0; clear: both; margin-top: 10px; } label { display: block; font-size: 110%; margin-bottom:3px; } input, textarea { clear: both; font-size: 140%; font-family: "frutiger linotype", "lucida grande", "verdana", sans-serif; padding: 1%; width:98%; } select { clear: both; font-size: 120%; vertical-align: text-bottom; } select[multiple=multiple] { width: 100%; } option { font-size: 120%; padding: 0 3px; } input[type=checkbox] { clear: left; float: left; margin: 0 6px 7px 2px; width: auto; } div.checkbox label { display: inline; } input[type=radio] { float:left; width:auto; margin: 6px 0; padding: 0; line-height: 26px; } .radio label { margin: 0 0 6px 20px; line-height: 26px; } input[type=submit] { display: inline; font-size: 110%; width: auto; } form .submit input[type=submit] { background:#62af56; background-image: -webkit-gradient(linear, left top, left bottom, from(#76BF6B), to(#3B8230)); background-image: -webkit-linear-gradient(top, #76BF6B, #3B8230); background-image: -moz-linear-gradient(top, #76BF6B, #3B8230); border-color: #2d6324; color: #fff; text-shadow: rgba(0, 0, 0, 0.5) 0 -1px 0; padding: 8px 10px; } form .submit input[type=submit]:hover { background: #5BA150; } /* Form errors */ form .error { background: #FFDACC; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; font-weight: normal; } form .error-message { -moz-border-radius: none; -webkit-border-radius: none; border-radius: none; border: none; background: none; margin: 0; padding-left: 4px; padding-right: 0; } form .error, form .error-message { color: #9E2424; -webkit-box-shadow: none; -moz-box-shadow: none; -ms-box-shadow: none; -o-box-shadow: none; box-shadow: none; text-shadow: none; } /** Notices and Errors **/ .message { clear: both; color: #fff; font-size: 140%; font-weight: bold; margin: 0 0 1em 0; padding: 5px; } .success, .message, .cake-error, .cake-debug, .notice, p.error, .error-message { background: #ffcc00; background-repeat: repeat-x; background-image: -moz-linear-gradient(top, #ffcc00, #E6B800); background-image: -ms-linear-gradient(top, #ffcc00, #E6B800); background-image: -webkit-gradient(linear, left top, left bottom, from(#ffcc00), to(#E6B800)); background-image: -webkit-linear-gradient(top, #ffcc00, #E6B800); background-image: -o-linear-gradient(top, #ffcc00, #E6B800); background-image: linear-gradient(top, #ffcc00, #E6B800); text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); border: 1px solid rgba(0, 0, 0, 0.2); margin-bottom: 18px; padding: 7px 14px; color: #404040; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); } .success, .message, .cake-error, p.error, .error-message { clear: both; color: #fff; background: #c43c35; border: 1px solid rgba(0, 0, 0, 0.5); background-repeat: repeat-x; background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); background-image: -webkit-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35)); background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); background-image: linear-gradient(top, #ee5f5b, #c43c35); text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3); } .success { clear: both; color: #fff; border: 1px solid rgba(0, 0, 0, 0.5); background: #3B8230; background-repeat: repeat-x; background-image: -webkit-gradient(linear, left top, left bottom, from(#76BF6B), to(#3B8230)); background-image: -webkit-linear-gradient(top, #76BF6B, #3B8230); background-image: -moz-linear-gradient(top, #76BF6B, #3B8230); background-image: -ms-linear-gradient(top, #76BF6B, #3B8230); background-image: -o-linear-gradient(top, #76BF6B, #3B8230); background-image: linear-gradient(top, #76BF6B, #3B8230); text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3); } p.error { font-family: Monaco, Consolas, Courier, monospace; font-size: 120%; padding: 0.8em; margin: 1em 0; } p.error em { font-weight: normal; line-height: 140%; } .notice { color: #000; display: block; font-size: 120%; padding: 0.8em; margin: 1em 0; } .success { color: #fff; } /** Actions **/ .actions ul { margin: 0; padding: 0; } .actions li { margin:0 0 0.5em 0; list-style-type: none; white-space: nowrap; padding: 0; } .actions ul li a { font-weight: normal; display: block; clear: both; } /* Buttons and button links */ input[type=submit], .actions ul li a, .actions a { font-weight:normal; padding: 4px 8px; background: #dcdcdc; background-image: -webkit-gradient(linear, left top, left bottom, from(#fefefe), to(#dcdcdc)); background-image: -webkit-linear-gradient(top, #fefefe, #dcdcdc); background-image: -moz-linear-gradient(top, #fefefe, #dcdcdc); background-image: -ms-linear-gradient(top, #fefefe, #dcdcdc); background-image: -o-linear-gradient(top, #fefefe, #dcdcdc); background-image: linear-gradient(top, #fefefe, #dcdcdc); color:#333; border:1px solid #bbb; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; text-decoration: none; text-shadow: #fff 0 1px 0; min-width: 0; -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 1px 1px rgba(0, 0, 0, 0.2); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 1px 1px rgba(0, 0, 0, 0.2); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 1px 1px rgba(0, 0, 0, 0.2); -webkit-user-select: none; user-select: none; } .actions ul li a:hover, .actions a:hover { background: #ededed; border-color: #acacac; text-decoration: none; } input[type=submit]:active, .actions ul li a:active, .actions a:active { background: #eee; background-image: -webkit-gradient(linear, left top, left bottom, from(#dfdfdf), to(#eee)); background-image: -webkit-linear-gradient(top, #dfdfdf, #eee); background-image: -moz-linear-gradient(top, #dfdfdf, #eee); background-image: -ms-linear-gradient(top, #dfdfdf, #eee); background-image: -o-linear-gradient(top, #dfdfdf, #eee); background-image: linear-gradient(top, #dfdfdf, #eee); text-shadow: #eee 0 1px 0; -moz-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.3); -webkit-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.3); box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.3); border-color: #aaa; text-decoration: none; } /** Related **/ .related { clear: both; display: block; } /** Debugging **/ pre { color: #000; background: #f0f0f0; padding: 15px; -moz-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3); box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3); } .cake-debug-output { padding: 0; position: relative; } .cake-debug-output > span { position: absolute; top: 5px; right: 5px; background: rgba(255, 255, 255, 0.3); -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; padding: 5px 6px; color: #000; display: block; float: left; -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.25), 0 1px 0 rgba(255, 255, 255, 0.5); -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.25), 0 1px 0 rgba(255, 255, 255, 0.5); box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.25), 0 1px 0 rgba(255, 255, 255, 0.5); text-shadow: 0 1px 1px rgba(255, 255, 255, 0.8); } .cake-debug, .cake-error { font-size: 16px; line-height: 20px; clear: both; } .cake-error > a { text-shadow: none; } .cake-error { white-space: normal; } .cake-stack-trace { background: rgba(255, 255, 255, 0.7); color: #333; margin: 10px 0 5px 0; padding: 10px 10px 0 10px; font-size: 120%; line-height: 140%; overflow: auto; position: relative; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } .cake-stack-trace a { text-shadow: none; background: rgba(255, 255, 255, 0.7); padding: 5px; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; margin: 0 4px 10px 2px; font-family: sans-serif; font-size: 14px; line-height: 14px; display: inline-block; text-decoration: none; -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.3); -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.3); box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.3); } .cake-code-dump pre { position: relative; overflow: auto; } .cake-context { margin-bottom: 10px; } .cake-stack-trace pre { color: #000; background-color: #F0F0F0; margin: 0 0 10px 0; padding: 1em; overflow: auto; text-shadow: none; } .cake-stack-trace li { padding: 10px 5px 0; margin: 0 0 4px 0; font-family: monospace; border: 1px solid #bbb; -moz-border-radius: 4px; -wekbkit-border-radius: 4px; border-radius: 4px; background: #dcdcdc; background-image: -webkit-gradient(linear, left top, left bottom, from(#fefefe), to(#dcdcdc)); background-image: -webkit-linear-gradient(top, #fefefe, #dcdcdc); background-image: -moz-linear-gradient(top, #fefefe, #dcdcdc); background-image: -ms-linear-gradient(top, #fefefe, #dcdcdc); background-image: -o-linear-gradient(top, #fefefe, #dcdcdc); background-image: linear-gradient(top, #fefefe, #dcdcdc); } /* excerpt */ .cake-code-dump pre, .cake-code-dump pre code { clear: both; font-size: 12px; line-height: 15px; margin: 4px 2px; padding: 4px; overflow: auto; } .cake-code-dump .code-highlight { display: block; background-color: rgba(255, 255, 0, 0.5); } .code-coverage-results div.code-line { padding-left:5px; display:block; margin-left:10px; } .code-coverage-results div.uncovered span.content { background:#ecc; } .code-coverage-results div.covered span.content { background:#cec; } .code-coverage-results div.ignored span.content { color:#aaa; } .code-coverage-results span.line-num { color:#666; display:block; float:left; width:20px; text-align:right; margin-right:5px; } .code-coverage-results span.line-num strong { color:#666; } .code-coverage-results div.start { border:1px solid #aaa; border-width:1px 1px 0 1px; margin-top:30px; padding-top:5px; } .code-coverage-results div.end { border:1px solid #aaa; border-width:0px 1px 1px 1px; margin-bottom:30px; padding-bottom:5px; } .code-coverage-results div.realstart { margin-top:0px; } .code-coverage-results p.note { color:#bbb; padding:5px; margin:5px 0 10px; font-size:10px; } .code-coverage-results span.result-bad { color: #a00; } .code-coverage-results span.result-ok { color: #fa0; } .code-coverage-results span.result-good { color: #0a0; } /** Elements **/ #url-rewriting-warning { display:none; } cakephp-2.8.0/app/webroot/favicon.ico000066400000000000000000000005641265552240500175310ustar00rootroot00000000000000‰PNG  IHDR DคŠฦPLTEู฿ๆaz•j€—Fa~ฅญ๑๏์โโใฺrstRNS6์ฺึ๛๘IDATxฺญ“ัย0C%!๋ฑ,t8={4๘ฒr )_U@YƒฟL$ดJ‡ต$@๗nส๑๐D`หภ฿๔™ ”^\ื“IENDฎB`‚cakephp-2.8.0/app/webroot/files/000077500000000000000000000000001265552240500165055ustar00rootroot00000000000000cakephp-2.8.0/app/webroot/files/empty000066400000000000000000000000001265552240500175540ustar00rootroot00000000000000cakephp-2.8.0/app/webroot/img/000077500000000000000000000000001265552240500161575ustar00rootroot00000000000000cakephp-2.8.0/app/webroot/img/cake.icon.png000066400000000000000000000016571265552240500205300ustar00rootroot00000000000000‰PNG  IHDR‰ tEXtSoftwareAdobe ImageReadyqษe<QIDATxฺฌT]HSa~ถ…ๅOyิ08?๙3›‘™ป( %กAฤส!† ั)*จhBˆK&ฎะœ"^ค˜C']„n„ถะM\q๚พwุPป๒น๘็{฿๓œ็๑<ฃฤ1zˆD"แขดดิ@ืT*•.::Z'—หกP(˜maa[[[pน\ถตตตr๕bpppฦ-'b!คDฑฑฑmeee๊|ไ0P๒กก!ŒŒŒP๒‡”˜EKBึ`ฑX๘ƒ011มทดดฐ็ๆๆๆ>;ฝkjjโ G ฐถถ–onn>TMMM Qผ็/คา คฅiAฃHJJbvš“ษ4ำืื—รrH๓๔?TUUกซ๋Šฏ„’ทE,/;ั๛?–ล+4Œ<""‚ŠBsQ\\ ญV{ !ฝฯศธJ~„R)J†ิยยd!฿พูแvปYqฤ{฿ุฬๆFดถถ’ฟ/Hj415)มจm.็H$!ˆCจ2Hc˜8ป เืํ๑$!่๎๎ฤ๎ฎ‰‰Iˆ‹SAญVƒใ"ฑฒฒŠฌฌ<ฬฯโ๋ื฿ถ#=]‰ำi‰X_๗QŽ™@Bปลโ1TVๆ บบกก*ๆดธ่„รแ€ื๋eNว‘ร`H€Xฤ๛.ๆ฿Iศn&*ะนบบ‹ว฿ฃผœGIIHS#&F๖ุุฝ๓มf๓"๗)œฯMลฅ‹R<ํ์G{วs[กFlXญŸ๑ๆอ'R9=๔z=k๐๐pๆไ๓๙œ|QQax;OR3‡3ูฉXr{AฃGใIWP_ว15ๅภภภ+ ?๔z9๒๒โQXp;;'0=ํ"น฿…ั3™ฎ๓๑๑1Œฬhผ.ๅ+Vซ6ญVกฮฟฉฮสฬ y๔ขญU#ฝสๅWH๚h\Qq๙ฮ๖v$ฺŸ‘v่EQQ4 ม่“'ๆB:๛Jฅ\UเฏpBโภ%$ศ๋๊๎s2Y &'็Y•ggg…dni๘w‰sภvR“wง pฃ๎ๆอ_zzบxวฝo๔๗๗ณ%pุˆ…Lฑทr66ถ /_พvข฿~ุBtิ[Œ#ฦ?า6งRคXพyIENDฎB`‚cakephp-2.8.0/app/webroot/img/cake.power.gif000066400000000000000000000003111265552240500206770ustar00rootroot00000000000000GIF87ab ๑4Aภภภ,b ข”ฉหํ#ดฺ‹ณ:๘†โHއฆjVถ๎œ๋Lณ๐ห—่๕๋ษ>•ล vFE%๑‰LFI< ตwฑลฃ7๙^Hาฒว >ƒฬข*ท‚n…Aฅ๔|฿jฃ:=ุ6—Uˆต5'ถจˆAย–ฦ๖GE(gt๐ีลˆ๒y็—ว7 โV“š‚ร๚‚ช kำ:;kหA›{*ม๋๛๛[;cakephp-2.8.0/app/webroot/img/test-error-icon.png000066400000000000000000000064361265552240500217320ustar00rootroot00000000000000‰PNG  IHDR๓a pHYs  šœ OiCCPPhotoshop ICC profilexฺSgTS้=๗๔BKˆ€”KoR RB‹€‘&*! Jˆ!กูQมEEศ ˆŽŽ€ŒQ, Š ุไ!ขŽƒฃˆŠส๛แ{ฃkึผ๗ๆอตื>็ฌ๓ณฯภ –H3Q5€ ฉBเƒวฤฦแไ.@ $pณd!s#๘~<<+"ภพxำ ภM›ภ0‡๊B™\€„ภt‘8K€@zŽBฆ@F€˜&S `หcbใP-`'ๆำ€๘™{[”! ‘ eˆDh;ฌฯVŠEX0fKฤ9ุ-0IWfHฐทภฮ ฒ 0Qˆ…){`ศ##x„™F๒W<๑+ฎ็*x™ฒ<น$9E[-qWW.(ฮI+6aaš@.ยy™24เ๓ฬ ‘เƒ๓xฮฎฮฮ6Žถ_-๊ฟ"bbใๅฯซp@แt~ั,/ณ€;€mข%๎h^  u๗‹fฒ@ต ฺ้W๓p๘~<฿5ฐj>{‘-จ]c๖K'Xtภโ๗๒ปoมิ(€hƒแฯw๏?G %€fI’q^D$.Tสณ?วD *ฐA๔ม,ภมม `6„B$ฤยBB d€r`)ฌ‚B(†อฐ*`/ิ@4ภQh†“p.ยUธ=p๚ažม(ผ Aศa!ฺˆbŠX#Ž™…๘!มH‹$ ษˆQ"K‘5H1RŠT UH๒=r9‡\Fบ‘;ศ2‚†ผG1”ฒQ=ิ ตCนจ7„Fข ะdt1š ›ะrด=Œ6ก็ะซhฺ>Cว0ภ่3ฤl0.ฦรBฑ8, “cหฑ"ฌ ซฦฐVฌป‰๕cฯฑwEภ 6wB aAHXLXNุHจ $4ฺ 7 „Qย'"“จKด&บ๙ฤb21‡XH,#ึ/{ˆCฤ7$‰C2'นIฑคTาาFาnR#้,ฉ›4H#“ษฺdkฒ9”, +ศ…ไไรไ3ไไ!๒[ b@qค๘Sโ(RสjJๅๅ4ๅe˜2AUฃšRจกT5ZBญกถRฏQ‡จ4uš9อƒIKฅญข•ำhh๗iฏ่tบ•N—ะWาห้G่—่๔w †ƒวˆg(›gwฏ˜Lฆำ‹วT071๋˜็™™oUX*ถ*|‘ส •J•&•*/Tฉชฆชช U๓UหTฉ^S}ฎFU3Sใฉ ิ–ซUชP๋SSgฉ;จ‡ชgจoT?ค~Y‰YรLรOCคQ ฑ_ใผฦ cณx,!k ซ†u5ฤ&ฑอู|v*ป˜ป‹=ชฉก9C3J3WณR๓”f?ใ˜q๘œtN ็(ง—๓~Š๏)โ)ฆ4Lน1e\kช–—–XซHซQซG๋ฝ6ฎํงฆฝEปY๛AวJ'\'Ggฮ็SูSง งM=:๕ฎ.ชkฅกปDwฟnง๎˜žพ^€žLoงyฝ็๚}/Tm๚ง๕G Xณ $ ฮ<ล5qo</ว๑QC]ร@Cฅa•a—แ„‘นั<ฃีFFŒiฦ\ใ$ใmฦmฦฃ&&!&KM๊M๎šRMนฆ)ฆ;L;Lวอฬอขอึ™5›=1ื2็›็›ื›฿ท`ZxZ,ถจถธeIฒไZฆY๎ถผn…Z9YฅXUZ]ณFญญ%ึปญปงงนN“Nซžึgรฐ๑ถษถฉทฐๅุฎถmถ}agbgทลฎร๎“ฝ“}บ}= ‡ูซZ~sดr:V:šฮœ๎?}ล๔–้/gXฯฯุ3ใถห)ฤiS›ำGggนsƒ๓ˆ‹‰K‚ห.—>.›ฦศฝไJt๕q]แzา๕›ณ›ยํจฏ๎6๎i๎‡Ÿฬ4Ÿ)žY3sะรศCเQๅั? Ÿ•0k฿ฌ~OCOgต็#/c/‘Wญืฐทฅwช๗a๏>๖>rŸใ>ใ<72Y_ฬ7ภทศทหOรož_…฿C#dzัง€%g‰A[๛๘z|!ฟŽ?:e๖ฒูํAŒ นAA‚ญ‚ๅมญ!hศ์ญ!๗็˜ฮ‘ฮi…P~่ึะaๆa‹ร~ '…‡…W†?ŽpˆXั1—5wัCs฿D๚D–D›g1O9ฏ-J5*>ช.j<ฺ7บ4บ?ฦ.fYฬีXXIlK9.*ฎ6nlพ฿ํ๓‡โโ ใ{˜/ศ]pyกฮย๔…งฉ.,:–@LˆN8”๐A*จŒ%๒w%Ž yยยg"/ั6ัˆุC\*N๒H*Mz’์‘ผ5y$ล3ฅ,ๅน„'ฉผL L›:žšv m2=:ฝ1ƒ’‘qBช!M“ถg๊gๆfvหฌe…ฒลn‹ท/•ษkณฌY- ถBฆ่TZ(ื*ฒgeWfฟอ‰ส9–ซž+อํฬณส7œ๏Ÿํยแ’ถฅ†KW-Xๆฝฌj9ฒ‰Šฎ—ุ(xๅ‡oสฟ™”ดฉซฤนdฯfาf้ๆ-ž[–ช—ๆ—n ฺูด ฿Vดํ๕๖E/—อ(ปƒถCนฃฟ<ธผeงษฮอ;?TคT๔T๚T6๎าตaื๘nั๎{ผ๖4์ี[ผ๗>ษพUUMีfีe๛I๛ณ๗?ฎ‰ช้๘–๛m]ญNmqํวา#ถืนิีา=TRึ+๋Gวพ๏w- 6 Uœฦโ#pDyไ้๗ ฿๗ :ฺvŒ{ฌแำvg/jBš๒šF›Sš๛[b[บOฬ>ัึ๊zGœ499โ?r้งCฯdฯ&žขหฎ/~๘ี๋ืฮั˜ัก—๒—“ฟm|ฅ๊ภ๋ฏฦยฦพษx31^๔V๛ํมww๏ฃ฿Oไ| (h๙ฑ๕Sะง๛“““˜๓c3- cHRMz%€ƒ๙€้u0๊`:˜o’_ลFIIDATxฺŒ“AkAล;ณูธm–B›CึMlดุ^ฤR๑dฟ@=V๔ ๛z๒ึc/ฝˆwฤxRฐH % )ถ ฅMุ์ฬฮŽ7hkลsyy๏?๓f€ต๖๗ํ๕?N๕ส๛ๆ้ึตคปๅ๒Ÿ‚@|zy๛CฝqผโV๏XูwK฿ล๛็%วqๆwwweน\ถkOึLฝqผ<๗Š }ว>ผ•8oœ ยM`#ŸฯW…c(‹,?Xๆฎ๗s๓{{{Fฃq=๑ขๆ™ฬเฐQ,ืซี*“““c888`๕๑*aR[ง\.ำnท้๕zาqyvvฆณ 6*•ส๚พ๏#ฅฤC†„aH<ŠวโJฅา=<รแ๐ฏโแp˜งฟ‹/bุBX฿๗ํฤฤ„๕}฿ !,ฐ๓ซ~ ?๒L%X€“;:IENDฎB`‚cakephp-2.8.0/app/webroot/img/test-fail-icon.png000066400000000000000000000007601265552240500215060ustar00rootroot00000000000000‰PNG  IHDR(-StEXtSoftwareAdobe ImageReadyqษe<ฅPLTEำฟลษ๘„นืฯจไชXเฒฺ์์33โญฃํํ๐๐ั๒rึU,66โˆF๎ฬjเณ ฬW-เ ๅใชXร)าิฝ แใไะอุ 00ฬย๓๎{หใีแึ –D•7tRNSY‹žIDATxฺLฯว‚0ะQ‚5ค7ฑ๗^๒Ÿfvแเปฬ์ฦ๕šฒฒ์ฝu>ŠUA0bnฃT๊6ฑr!rสงยw@ค’ห -ธผ \ึ8:$M’”KŒGŸE›4ืฟ=—lไbษศ0ถ๊ปจ)3" ฿๗+)+ยุล๋8:ค็B๑V:โoia™ฝอO€Š ๋๑ใIENDฎB`‚cakephp-2.8.0/app/webroot/img/test-pass-icon.png000066400000000000000000000014171265552240500215410ustar00rootroot00000000000000‰PNG  IHDR(-StEXtSoftwareAdobe ImageReadyqษe<>PLTE€฿๏฿Pนน8œ8‡OrนrsนsN † ˆ]Mt…„qธq’a๙๙|\ฎ\vnทn … XolŽQ † ~`p^VqkYทท<š<ƒZฉZsฑัฑQคQุ็ุ ` ‘klT … Œี่ีฬไฬrรรІุุ่Uฦเฦ5š5W$n$_ธธtS\ทัทRœผœ‚s „ 3t3“K›K™ม™{f˜fzZญZE•ETฆT๙๛๙u88oทo–น– o a W‰ณl…ณjtRNSผไใ๑IDATxฺ$ฯUnAะุeF3s˜ั;ฬฬLs ฤ^๗Wฉฅ’๊œ ‹•สง0ฬภ9QฎaฺuฝZ† $เm—J๋nž ‡‰ ~บ› ฃภ็0žm=ใ6จ้xjลษ_mภXช้0cฯ`>fอฮƒn่๐jฃrZfถยF ๑|„บW๛!vJ^wฺxožิˆŽt์๛ํื[tP‘ฑบ๚…ฺ๚>ฬ—)–Aะ:}|;[ฬ๏PkS€+xLฅ7ฟ็eษ AIฆใข%ITU"#œVuL35%ม๘Œ‰rย`h’(?ัbำIENDฎB`‚cakephp-2.8.0/app/webroot/img/test-skip-icon.png000066400000000000000000000022671265552240500215450ustar00rootroot00000000000000‰PNG  IHDR(-StEXtSoftwareAdobe ImageReadyqษe<PLTEiz”(P๖๗๙5XGo ?eุใQ|Mx,U'n +xช'P+S฿ๅl}– >d`อุแZ‡)rฃ#f˜Z‰1bˆU‚/V+QHlyนJnFnAhOz6zจ#hš1r AlŒ๙๚๛$j›T~๓๔๖+T2X\‹Bƒฏพีๅ+g”Is\‰[”นลึโP|Qx•Yˆ'O*S&O,xช#h™,xซ+vฉƒฐอ'Q/U<|งX†*Q0W‰ฃท"Z„ b“+wฉ%kœ&\†ถฬ6k“3vฅ(qฃ"`ŽZ†_Žt“ซ}จล^Žๆ๏๔|คภFog/f ๓ุฑ4ฤ–๙„ี;ŸOงƒ‹3?euสpง~ปฎKงzยƒt๕v?็z‰๒xเหว๋๓kฺToด0เDfฟ(q5 ‹VOรn,่ jwจ4็[8ƒ8l๚ณ ขย+%kวwkŽQ‘*+๔่x& ผr~:๓Lซสค‘:ห๒‘”กn^ฬ›"ๅบMmฎnŠbตuหธ-`ท'ภ+|<'ป]฿ฎIENDฎB`‚cakephp-2.8.0/app/webroot/index.php000066400000000000000000000070271265552240500172310ustar00rootroot00000000000000dispatch( new CakeRequest(), new CakeResponse() ); cakephp-2.8.0/app/webroot/js/000077500000000000000000000000001265552240500160175ustar00rootroot00000000000000cakephp-2.8.0/app/webroot/js/empty000066400000000000000000000000001265552240500170660ustar00rootroot00000000000000cakephp-2.8.0/app/webroot/test.php000066400000000000000000000066111265552240500170770ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html * @package app.webroot * @since CakePHP(tm) v 1.2.0.4433 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ set_time_limit(0); ini_set('display_errors', 1); /** * Use the DS to separate the directories in other defines */ if (!defined('DS')) { define('DS', DIRECTORY_SEPARATOR); } /** * These defines should only be edited if you have CakePHP installed in * a directory layout other than the way it is distributed. * When using custom settings be sure to use the DS and do not add a trailing DS. */ /** * The full path to the directory which holds "app", WITHOUT a trailing DS. */ if (!defined('ROOT')) { define('ROOT', dirname(dirname(dirname(__FILE__)))); } /** * The actual directory name for the "app". */ if (!defined('APP_DIR')) { define('APP_DIR', basename(dirname(dirname(__FILE__)))); } /** * The absolute path to the "Cake" directory, WITHOUT a trailing DS. * * For ease of development CakePHP uses PHP's include_path. If you * need to cannot modify your include_path, you can set this path. * * Leaving this constant undefined will result in it being defined in Cake/bootstrap.php * * The following line differs from its sibling * /lib/Cake/Console/Templates/skel/webroot/test.php */ //define('CAKE_CORE_INCLUDE_PATH', ROOT . DS . 'lib'); /** * This auto-detects CakePHP as a composer installed library. * You may remove this if you are not planning to use composer (not recommended, though). */ $vendorPath = ROOT . DS . APP_DIR . DS . 'Vendor' . DS . 'cakephp' . DS . 'cakephp' . DS . 'lib'; $dispatcher = 'Cake' . DS . 'Console' . DS . 'ShellDispatcher.php'; if (!defined('CAKE_CORE_INCLUDE_PATH') && file_exists($vendorPath . DS . $dispatcher)) { define('CAKE_CORE_INCLUDE_PATH', $vendorPath); } /** * Editing below this line should not be necessary. * Change at your own risk. */ if (!defined('WEBROOT_DIR')) { define('WEBROOT_DIR', basename(dirname(__FILE__))); } if (!defined('WWW_ROOT')) { define('WWW_ROOT', dirname(__FILE__) . DS); } if (!defined('CAKE_CORE_INCLUDE_PATH')) { if (function_exists('ini_set')) { ini_set('include_path', ROOT . DS . 'lib' . PATH_SEPARATOR . ini_get('include_path')); } if (!include 'Cake' . DS . 'bootstrap.php') { $failed = true; } } else { if (!include CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'bootstrap.php') { $failed = true; } } if (!empty($failed)) { trigger_error("CakePHP core could not be found. Check the value of CAKE_CORE_INCLUDE_PATH in APP/webroot/test.php. It should point to the directory containing your " . DS . "cake core directory and your " . DS . "vendors root directory.", E_USER_ERROR); } if (Configure::read('debug') < 1) { throw new NotFoundException(__d('cake_dev', 'Debug setting does not allow access to this URL.')); } require_once CAKE . 'TestSuite' . DS . 'CakeTestSuiteDispatcher.php'; CakeTestSuiteDispatcher::run(); cakephp-2.8.0/build.properties000066400000000000000000000002561265552240500163620ustar00rootroot00000000000000# Name project.name = CakePHP # Git stuff git.remote = origin # Directories build.dir = build dist.dir = dist # Server pirum.dir = /home/cakephp/www-live/pear.cakephp.org cakephp-2.8.0/build.xml000066400000000000000000000237521265552240500147740ustar00rootroot00000000000000 CakePHP CakePHP Rapid Development Framework pear.cakephp.org CakePHP is an application development framework for PHP 5.2+ MIT License https://github.com/cakephp/cakephp/blob/master/README script php php php php php php php php cakephp-2.8.0/composer.json000066400000000000000000000013551265552240500156700ustar00rootroot00000000000000{ "name": "cakephp/cakephp", "description": "The CakePHP framework", "type": "library", "keywords": ["framework"], "homepage": "http://cakephp.org", "license": "MIT", "authors": [ { "name": "CakePHP Community", "homepage": "https://github.com/cakephp/cakephp/graphs/contributors" } ], "support": { "issues": "https://github.com/cakephp/cakephp/issues", "forum": "http://stackoverflow.com/tags/cakephp", "irc": "irc://irc.freenode.org/cakephp", "source": "https://github.com/cakephp/cakephp" }, "require": { "php": ">=5.3.0", "ext-mcrypt": "*" }, "require-dev": { "phpunit/phpunit": "3.7.*", "cakephp/debug_kit" : "^2.2.0", "cakephp/cakephp-codesniffer": "^1.0.0" }, "bin": [ "lib/Cake/Console/cake" ] } cakephp-2.8.0/index.php000066400000000000000000000026561265552240500147730ustar00rootroot00000000000000 'Apc', * 'prefix' => 'my_app_' * )); * ``` * * This would configure an APC cache engine to the 'shared' alias. You could then read and write * to that cache alias by using it for the `$config` parameter in the various Cache methods. In * general all Cache operations are supported by all cache engines. However, Cache::increment() and * Cache::decrement() are not supported by File caching. * * @package Cake.Cache */ class Cache { /** * Cache configuration stack * Keeps the permanent/default settings for each cache engine. * These settings are used to reset the engines after temporary modification. * * @var array */ protected static $_config = array(); /** * Group to Config mapping * * @var array */ protected static $_groups = array(); /** * Whether to reset the settings with the next call to Cache::set(); * * @var array */ protected static $_reset = false; /** * Engine instances keyed by configuration name. * * @var array */ protected static $_engines = array(); /** * Set the cache configuration to use. config() can * both create new configurations, return the settings for already configured * configurations. * * To create a new configuration, or to modify an existing configuration permanently: * * `Cache::config('my_config', array('engine' => 'File', 'path' => TMP));` * * If you need to modify a configuration temporarily, use Cache::set(). * To get the settings for a configuration: * * `Cache::config('default');` * * There are 5 built-in caching engines: * * - `FileEngine` - Uses simple files to store content. Poor performance, but good for * storing large objects, or things that are not IO sensitive. * - `ApcEngine` - Uses the APC object cache, one of the fastest caching engines. * - `MemcacheEngine` - Uses the PECL::Memcache extension and Memcached for storage. * Fast reads/writes, and benefits from memcache being distributed. * - `XcacheEngine` - Uses the Xcache extension, an alternative to APC. * - `WincacheEngine` - Uses Windows Cache Extension for PHP. Supports wincache 1.1.0 and higher. * * The following keys are used in core cache engines: * * - `duration` Specify how long items in this cache configuration last. * - `groups` List of groups or 'tags' associated to every key stored in this config. * handy for deleting a complete group from cache. * - `prefix` Prefix appended to all entries. Good for when you need to share a keyspace * with either another cache config or another application. * - `probability` Probability of hitting a cache gc cleanup. Setting to 0 will disable * cache::gc from ever being called automatically. * - `servers' Used by memcache. Give the address of the memcached servers to use. * - `compress` Used by memcache. Enables memcache's compressed format. * - `serialize` Used by FileCache. Should cache objects be serialized first. * - `path` Used by FileCache. Path to where cachefiles should be saved. * - `lock` Used by FileCache. Should files be locked before writing to them? * - `user` Used by Xcache. Username for XCache * - `password` Used by Xcache/Redis. Password for XCache/Redis * * @param string $name Name of the configuration * @param array $settings Optional associative array of settings passed to the engine * @return array array(engine, settings) on success, false on failure * @throws CacheException * @see app/Config/core.php for configuration settings */ public static function config($name = null, $settings = array()) { if (is_array($name)) { $settings = $name; } $current = array(); if (isset(static::$_config[$name])) { $current = static::$_config[$name]; } if (!empty($settings)) { static::$_config[$name] = $settings + $current; } if (empty(static::$_config[$name]['engine'])) { return false; } if (!empty(static::$_config[$name]['groups'])) { foreach (static::$_config[$name]['groups'] as $group) { static::$_groups[$group][] = $name; sort(static::$_groups[$group]); static::$_groups[$group] = array_unique(static::$_groups[$group]); } } $engine = static::$_config[$name]['engine']; if (!isset(static::$_engines[$name])) { static::_buildEngine($name); $settings = static::$_config[$name] = static::settings($name); } elseif ($settings = static::set(static::$_config[$name], null, $name)) { static::$_config[$name] = $settings; } return compact('engine', 'settings'); } /** * Finds and builds the instance of the required engine class. * * @param string $name Name of the config array that needs an engine instance built * @return bool * @throws CacheException */ protected static function _buildEngine($name) { $config = static::$_config[$name]; list($plugin, $class) = pluginSplit($config['engine'], true); $cacheClass = $class . 'Engine'; App::uses($cacheClass, $plugin . 'Cache/Engine'); if (!class_exists($cacheClass)) { throw new CacheException(__d('cake_dev', 'Cache engine %s is not available.', $name)); } $cacheClass = $class . 'Engine'; if (!is_subclass_of($cacheClass, 'CacheEngine')) { throw new CacheException(__d('cake_dev', 'Cache engines must use %s as a base class.', 'CacheEngine')); } static::$_engines[$name] = new $cacheClass(); if (!static::$_engines[$name]->init($config)) { $msg = __d( 'cake_dev', 'Cache engine "%s" is not properly configured. Ensure required extensions are installed, and credentials/permissions are correct', $name ); throw new CacheException($msg); } if (static::$_engines[$name]->settings['probability'] && time() % static::$_engines[$name]->settings['probability'] === 0) { static::$_engines[$name]->gc(); } return true; } /** * Returns an array containing the currently configured Cache settings. * * @return array Array of configured Cache config names. */ public static function configured() { return array_keys(static::$_config); } /** * Drops a cache engine. Deletes the cache configuration information * If the deleted configuration is the last configuration using a certain engine, * the Engine instance is also unset. * * @param string $name A currently configured cache config you wish to remove. * @return bool success of the removal, returns false when the config does not exist. */ public static function drop($name) { if (!isset(static::$_config[$name])) { return false; } unset(static::$_config[$name], static::$_engines[$name]); return true; } /** * Temporarily change the settings on a cache config. The settings will persist for the next write * operation (write, decrement, increment, clear). Any reads that are done before the write, will * use the modified settings. If `$settings` is empty, the settings will be reset to the * original configuration. * * Can be called with 2 or 3 parameters. To set multiple values at once. * * `Cache::set(array('duration' => '+30 minutes'), 'my_config');` * * Or to set one value. * * `Cache::set('duration', '+30 minutes', 'my_config');` * * To reset a config back to the originally configured values. * * `Cache::set(null, 'my_config');` * * @param string|array $settings Optional string for simple name-value pair or array * @param string $value Optional for a simple name-value pair * @param string $config The configuration name you are changing. Defaults to 'default' * @return array Array of settings. */ public static function set($settings = array(), $value = null, $config = 'default') { if (is_array($settings) && $value !== null) { $config = $value; } if (!isset(static::$_config[$config]) || !isset(static::$_engines[$config])) { return false; } if (!empty($settings)) { static::$_reset = true; } if (static::$_reset === true) { if (empty($settings)) { static::$_reset = false; $settings = static::$_config[$config]; } else { if (is_string($settings) && $value !== null) { $settings = array($settings => $value); } $settings += static::$_config[$config]; if (isset($settings['duration']) && !is_numeric($settings['duration'])) { $settings['duration'] = strtotime($settings['duration']) - time(); } } static::$_engines[$config]->settings = $settings; } return static::settings($config); } /** * Garbage collection * * Permanently remove all expired and deleted data * * @param string $config [optional] The config name you wish to have garbage collected. Defaults to 'default' * @param int $expires [optional] An expires timestamp. Defaults to NULL * @return bool */ public static function gc($config = 'default', $expires = null) { return static::$_engines[$config]->gc($expires); } /** * Write data for key into a cache engine. * * ### Usage: * * Writing to the active cache config: * * `Cache::write('cached_data', $data);` * * Writing to a specific cache config: * * `Cache::write('cached_data', $data, 'long_term');` * * @param string $key Identifier for the data * @param mixed $value Data to be cached - anything except a resource * @param string $config Optional string configuration name to write to. Defaults to 'default' * @return bool True if the data was successfully cached, false on failure */ public static function write($key, $value, $config = 'default') { $settings = static::settings($config); if (empty($settings)) { return false; } if (!static::isInitialized($config)) { return false; } $key = static::$_engines[$config]->key($key); if (!$key || is_resource($value)) { return false; } $success = static::$_engines[$config]->write($settings['prefix'] . $key, $value, $settings['duration']); static::set(null, $config); if ($success === false && $value !== '') { trigger_error( __d('cake_dev', "%s cache was unable to write '%s' to %s cache", $config, $key, static::$_engines[$config]->settings['engine'] ), E_USER_WARNING ); } return $success; } /** * Read a key from a cache config. * * ### Usage: * * Reading from the active cache configuration. * * `Cache::read('my_data');` * * Reading from a specific cache configuration. * * `Cache::read('my_data', 'long_term');` * * @param string $key Identifier for the data * @param string $config optional name of the configuration to use. Defaults to 'default' * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it */ public static function read($key, $config = 'default') { $settings = static::settings($config); if (empty($settings)) { return false; } if (!static::isInitialized($config)) { return false; } $key = static::$_engines[$config]->key($key); if (!$key) { return false; } return static::$_engines[$config]->read($settings['prefix'] . $key); } /** * Increment a number under the key and return incremented value. * * @param string $key Identifier for the data * @param int $offset How much to add * @param string $config Optional string configuration name. Defaults to 'default' * @return mixed new value, or false if the data doesn't exist, is not integer, * or if there was an error fetching it. */ public static function increment($key, $offset = 1, $config = 'default') { $settings = static::settings($config); if (empty($settings)) { return false; } if (!static::isInitialized($config)) { return false; } $key = static::$_engines[$config]->key($key); if (!$key || !is_int($offset) || $offset < 0) { return false; } $success = static::$_engines[$config]->increment($settings['prefix'] . $key, $offset); static::set(null, $config); return $success; } /** * Decrement a number under the key and return decremented value. * * @param string $key Identifier for the data * @param int $offset How much to subtract * @param string $config Optional string configuration name. Defaults to 'default' * @return mixed new value, or false if the data doesn't exist, is not integer, * or if there was an error fetching it */ public static function decrement($key, $offset = 1, $config = 'default') { $settings = static::settings($config); if (empty($settings)) { return false; } if (!static::isInitialized($config)) { return false; } $key = static::$_engines[$config]->key($key); if (!$key || !is_int($offset) || $offset < 0) { return false; } $success = static::$_engines[$config]->decrement($settings['prefix'] . $key, $offset); static::set(null, $config); return $success; } /** * Delete a key from the cache. * * ### Usage: * * Deleting from the active cache configuration. * * `Cache::delete('my_data');` * * Deleting from a specific cache configuration. * * `Cache::delete('my_data', 'long_term');` * * @param string $key Identifier for the data * @param string $config name of the configuration to use. Defaults to 'default' * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ public static function delete($key, $config = 'default') { $settings = static::settings($config); if (empty($settings)) { return false; } if (!static::isInitialized($config)) { return false; } $key = static::$_engines[$config]->key($key); if (!$key) { return false; } $success = static::$_engines[$config]->delete($settings['prefix'] . $key); static::set(null, $config); return $success; } /** * Delete all keys from the cache. * * @param bool $check if true will check expiration, otherwise delete all * @param string $config name of the configuration to use. Defaults to 'default' * @return bool True if the cache was successfully cleared, false otherwise */ public static function clear($check = false, $config = 'default') { if (!static::isInitialized($config)) { return false; } $success = static::$_engines[$config]->clear($check); static::set(null, $config); return $success; } /** * Delete all keys from the cache belonging to the same group. * * @param string $group name of the group to be cleared * @param string $config name of the configuration to use. Defaults to 'default' * @return bool True if the cache group was successfully cleared, false otherwise */ public static function clearGroup($group, $config = 'default') { if (!static::isInitialized($config)) { return false; } $success = static::$_engines[$config]->clearGroup($group); static::set(null, $config); return $success; } /** * Check if Cache has initialized a working config for the given name. * * @param string $config name of the configuration to use. Defaults to 'default' * @return bool Whether or not the config name has been initialized. */ public static function isInitialized($config = 'default') { if (Configure::read('Cache.disable')) { return false; } return isset(static::$_engines[$config]); } /** * Return the settings for the named cache engine. * * @param string $name Name of the configuration to get settings for. Defaults to 'default' * @return array list of settings for this engine * @see Cache::config() */ public static function settings($name = 'default') { if (!empty(static::$_engines[$name])) { return static::$_engines[$name]->settings(); } return array(); } /** * Retrieve group names to config mapping. * * ``` * Cache::config('daily', array( * 'duration' => '1 day', 'groups' => array('posts') * )); * Cache::config('weekly', array( * 'duration' => '1 week', 'groups' => array('posts', 'archive') * )); * $configs = Cache::groupConfigs('posts'); * ``` * * $config will equal to `array('posts' => array('daily', 'weekly'))` * * @param string $group group name or null to retrieve all group mappings * @return array map of group and all configuration that has the same group * @throws CacheException */ public static function groupConfigs($group = null) { if ($group === null) { return static::$_groups; } if (isset(static::$_groups[$group])) { return array($group => static::$_groups[$group]); } throw new CacheException(__d('cake_dev', 'Invalid cache group %s', $group)); } /** * Provides the ability to easily do read-through caching. * * When called if the $key is not set in $config, the $callable function * will be invoked. The results will then be stored into the cache config * at key. * * Examples: * * Using a Closure to provide data, assume $this is a Model: * * ``` * $model = $this; * $results = Cache::remember('all_articles', function() use ($model) { * return $model->find('all'); * }); * ``` * * @param string $key The cache key to read/store data at. * @param callable $callable The callable that provides data in the case when * the cache key is empty. Can be any callable type supported by your PHP. * @param string $config The cache configuration to use for this operation. * Defaults to default. * @return mixed The results of the callable or unserialized results. */ public static function remember($key, $callable, $config = 'default') { $existing = static::read($key, $config); if ($existing !== false) { return $existing; } $results = call_user_func($callable); static::write($key, $results, $config); return $results; } /** * Write data for key into a cache engine if it doesn't exist already. * * ### Usage: * * Writing to the active cache config: * * `Cache::add('cached_data', $data);` * * Writing to a specific cache config: * * `Cache::add('cached_data', $data, 'long_term');` * * @param string $key Identifier for the data. * @param mixed $value Data to be cached - anything except a resource. * @param string $config Optional string configuration name to write to. Defaults to 'default'. * @return bool True if the data was successfully cached, false on failure. * Or if the key existed already. */ public static function add($key, $value, $config = 'default') { $settings = self::settings($config); if (empty($settings)) { return false; } if (!self::isInitialized($config)) { return false; } $key = self::$_engines[$config]->key($key); if (!$key || is_resource($value)) { return false; } $success = self::$_engines[$config]->add($settings['prefix'] . $key, $value, $settings['duration']); self::set(null, $config); return $success; } } cakephp-2.8.0/lib/Cake/Cache/CacheEngine.php000066400000000000000000000120051265552240500204160ustar00rootroot00000000000000settings + array( 'prefix' => 'cake_', 'duration' => 3600, 'probability' => 100, 'groups' => array() ); $this->settings = $settings; if (!empty($this->settings['groups'])) { sort($this->settings['groups']); $this->_groupPrefix = str_repeat('%s_', count($this->settings['groups'])); } if (!is_numeric($this->settings['duration'])) { $this->settings['duration'] = strtotime($this->settings['duration']) - time(); } return true; } /** * Garbage collection * * Permanently remove all expired and deleted data * * @param int $expires [optional] An expires timestamp, invalidating all data before. * @return void */ public function gc($expires = null) { } /** * Write value for a key into cache * * @param string $key Identifier for the data * @param mixed $value Data to be cached * @param int $duration How long to cache for. * @return bool True if the data was successfully cached, false on failure */ abstract public function write($key, $value, $duration); /** * Write value for a key into cache if it doesn't already exist * * @param string $key Identifier for the data * @param mixed $value Data to be cached * @param int $duration How long to cache for. * @return bool True if the data was successfully cached, false on failure */ public function add($key, $value, $duration) { } /** * Read a key from the cache * * @param string $key Identifier for the data * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it */ abstract public function read($key); /** * Increment a number under the key and return incremented value * * @param string $key Identifier for the data * @param int $offset How much to add * @return New incremented value, false otherwise */ abstract public function increment($key, $offset = 1); /** * Decrement a number under the key and return decremented value * * @param string $key Identifier for the data * @param int $offset How much to subtract * @return New incremented value, false otherwise */ abstract public function decrement($key, $offset = 1); /** * Delete a key from the cache * * @param string $key Identifier for the data * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ abstract public function delete($key); /** * Delete all keys from the cache * * @param bool $check if true will check expiration, otherwise delete all * @return bool True if the cache was successfully cleared, false otherwise */ abstract public function clear($check); /** * Clears all values belonging to a group. Is up to the implementing engine * to decide whether actually delete the keys or just simulate it to achieve * the same result. * * @param string $group name of the group to be cleared * @return bool */ public function clearGroup($group) { return false; } /** * Does whatever initialization for each group is required * and returns the `group value` for each of them, this is * the token representing each group in the cache key * * @return array */ public function groups() { return $this->settings['groups']; } /** * Cache Engine settings * * @return array settings */ public function settings() { return $this->settings; } /** * Generates a safe key for use with cache engine storage engines. * * @param string $key the key passed over * @return mixed string $key or false */ public function key($key) { if (empty($key)) { return false; } $prefix = ''; if (!empty($this->_groupPrefix)) { $prefix = vsprintf($this->_groupPrefix, $this->groups()); } $key = preg_replace('/[\s]+/', '_', strtolower(trim(str_replace(array(DS, '/', '.'), '_', strval($key))))); return $prefix . $key; } } cakephp-2.8.0/lib/Cake/Cache/Engine/000077500000000000000000000000001265552240500167635ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Cache/Engine/ApcEngine.php000066400000000000000000000134561265552240500213360ustar00rootroot00000000000000 'Apc'); parent::init($settings); return function_exists('apc_dec'); } /** * Write data for key into cache * * @param string $key Identifier for the data * @param mixed $value Data to be cached * @param int $duration How long to cache the data, in seconds * @return bool True if the data was successfully cached, false on failure */ public function write($key, $value, $duration) { $expires = 0; if ($duration) { $expires = time() + $duration; } apc_store($key . '_expires', $expires, $duration); return apc_store($key, $value, $duration); } /** * Read a key from the cache * * @param string $key Identifier for the data * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it */ public function read($key) { $time = time(); $cachetime = (int)apc_fetch($key . '_expires'); if ($cachetime !== 0 && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) { return false; } return apc_fetch($key); } /** * Increments the value of an integer cached key * * @param string $key Identifier for the data * @param int $offset How much to increment * @return New incremented value, false otherwise */ public function increment($key, $offset = 1) { return apc_inc($key, $offset); } /** * Decrements the value of an integer cached key * * @param string $key Identifier for the data * @param int $offset How much to subtract * @return New decremented value, false otherwise */ public function decrement($key, $offset = 1) { return apc_dec($key, $offset); } /** * Delete a key from the cache * * @param string $key Identifier for the data * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ public function delete($key) { return apc_delete($key); } /** * Delete all keys from the cache. This will clear every cache config using APC. * * @param bool $check If true, nothing will be cleared, as entries are removed * from APC as they expired. This flag is really only used by FileEngine. * @return bool True Returns true. */ public function clear($check) { if ($check) { return true; } if (class_exists('APCIterator', false)) { $iterator = new APCIterator( 'user', '/^' . preg_quote($this->settings['prefix'], '/') . '/', APC_ITER_NONE ); apc_delete($iterator); return true; } $cache = apc_cache_info('user'); foreach ($cache['cache_list'] as $key) { if (strpos($key['info'], $this->settings['prefix']) === 0) { apc_delete($key['info']); } } return true; } /** * Returns the `group value` for each of the configured groups * If the group initial value was not found, then it initializes * the group accordingly. * * @return array */ public function groups() { if (empty($this->_compiledGroupNames)) { foreach ($this->settings['groups'] as $group) { $this->_compiledGroupNames[] = $this->settings['prefix'] . $group; } } $groups = apc_fetch($this->_compiledGroupNames); if (count($groups) !== count($this->settings['groups'])) { foreach ($this->_compiledGroupNames as $group) { if (!isset($groups[$group])) { apc_store($group, 1); $groups[$group] = 1; } } ksort($groups); } $result = array(); $groups = array_values($groups); foreach ($this->settings['groups'] as $i => $group) { $result[] = $group . $groups[$i]; } return $result; } /** * Increments the group value to simulate deletion of all keys under a group * old values will remain in storage until they expire. * * @param string $group The group to clear. * @return bool success */ public function clearGroup($group) { apc_inc($this->settings['prefix'] . $group, 1, $success); return $success; } /** * Write data for key into cache if it doesn't exist already. * If it already exists, it fails and returns false. * * @param string $key Identifier for the data. * @param mixed $value Data to be cached. * @param int $duration How long to cache the data, in seconds. * @return bool True if the data was successfully cached, false on failure. * @link http://php.net/manual/en/function.apc-add.php */ public function add($key, $value, $duration) { $expires = 0; if ($duration) { $expires = time() + $duration; } apc_add($key . '_expires', $expires, $duration); return apc_add($key, $value, $duration); } } cakephp-2.8.0/lib/Cake/Cache/Engine/FileEngine.php000066400000000000000000000271771265552240500215170ustar00rootroot00000000000000 CACHE * - prefix = string prefix for filename, default => cake_ * - lock = enable file locking on write, default => true * - serialize = serialize the data, default => true * * @var array * @see CacheEngine::__defaults */ public $settings = array(); /** * True unless FileEngine::__active(); fails * * @var bool */ protected $_init = true; /** * Initialize the Cache Engine * * Called automatically by the cache frontend * To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array()); * * @param array $settings array of setting for the engine * @return bool True if the engine has been successfully initialized, false if not */ public function init($settings = array()) { $settings += array( 'engine' => 'File', 'path' => CACHE, 'prefix' => 'cake_', 'lock' => true, 'serialize' => true, 'isWindows' => false, 'mask' => 0664 ); parent::init($settings); if (DS === '\\') { $this->settings['isWindows'] = true; } if (substr($this->settings['path'], -1) !== DS) { $this->settings['path'] .= DS; } if (!empty($this->_groupPrefix)) { $this->_groupPrefix = str_replace('_', DS, $this->_groupPrefix); } return $this->_active(); } /** * Garbage collection. Permanently remove all expired and deleted data * * @param int $expires [optional] An expires timestamp, invalidating all data before. * @return bool True if garbage collection was successful, false on failure */ public function gc($expires = null) { return $this->clear(true); } /** * Write data for key into cache * * @param string $key Identifier for the data * @param mixed $data Data to be cached * @param int $duration How long to cache the data, in seconds * @return bool True if the data was successfully cached, false on failure */ public function write($key, $data, $duration) { if (!$this->_init) { return false; } if ($this->_setKey($key, true) === false) { return false; } $lineBreak = "\n"; if ($this->settings['isWindows']) { $lineBreak = "\r\n"; } if (!empty($this->settings['serialize'])) { if ($this->settings['isWindows']) { $data = str_replace('\\', '\\\\\\\\', serialize($data)); } else { $data = serialize($data); } } $expires = time() + $duration; $contents = $expires . $lineBreak . $data . $lineBreak; if ($this->settings['lock']) { $this->_File->flock(LOCK_EX); } $this->_File->rewind(); $success = $this->_File->ftruncate(0) && $this->_File->fwrite($contents) && $this->_File->fflush(); if ($this->settings['lock']) { $this->_File->flock(LOCK_UN); } return $success; } /** * Read a key from the cache * * @param string $key Identifier for the data * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it */ public function read($key) { if (!$this->_init || $this->_setKey($key) === false) { return false; } if ($this->settings['lock']) { $this->_File->flock(LOCK_SH); } $this->_File->rewind(); $time = time(); $cachetime = (int)$this->_File->current(); if ($cachetime !== false && ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime)) { if ($this->settings['lock']) { $this->_File->flock(LOCK_UN); } return false; } $data = ''; $this->_File->next(); while ($this->_File->valid()) { $data .= $this->_File->current(); $this->_File->next(); } if ($this->settings['lock']) { $this->_File->flock(LOCK_UN); } $data = trim($data); if ($data !== '' && !empty($this->settings['serialize'])) { if ($this->settings['isWindows']) { $data = str_replace('\\\\\\\\', '\\', $data); } $data = unserialize((string)$data); } return $data; } /** * Delete a key from the cache * * @param string $key Identifier for the data * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ public function delete($key) { if ($this->_setKey($key) === false || !$this->_init) { return false; } $path = $this->_File->getRealPath(); $this->_File = null; //@codingStandardsIgnoreStart return @unlink($path); //@codingStandardsIgnoreEnd } /** * Delete all values from the cache * * @param bool $check Optional - only delete expired cache items * @return bool True if the cache was successfully cleared, false otherwise */ public function clear($check) { if (!$this->_init) { return false; } $this->_File = null; $threshold = $now = false; if ($check) { $now = time(); $threshold = $now - $this->settings['duration']; } $this->_clearDirectory($this->settings['path'], $now, $threshold); $directory = new RecursiveDirectoryIterator($this->settings['path']); $contents = new RecursiveIteratorIterator($directory, RecursiveIteratorIterator::SELF_FIRST); $cleared = array(); foreach ($contents as $path) { if ($path->isFile()) { continue; } $path = $path->getRealPath() . DS; if (!in_array($path, $cleared)) { $this->_clearDirectory($path, $now, $threshold); $cleared[] = $path; } } return true; } /** * Used to clear a directory of matching files. * * @param string $path The path to search. * @param int $now The current timestamp * @param int $threshold Any file not modified after this value will be deleted. * @return void */ protected function _clearDirectory($path, $now, $threshold) { $prefixLength = strlen($this->settings['prefix']); if (!is_dir($path)) { return; } $dir = dir($path); while (($entry = $dir->read()) !== false) { if (substr($entry, 0, $prefixLength) !== $this->settings['prefix']) { continue; } try { $file = new SplFileObject($path . $entry, 'r'); } catch (Exception $e) { continue; } if ($threshold) { $mtime = $file->getMTime(); if ($mtime > $threshold) { continue; } $expires = (int)$file->current(); if ($expires > $now) { continue; } } if ($file->isFile()) { $filePath = $file->getRealPath(); $file = null; //@codingStandardsIgnoreStart @unlink($filePath); //@codingStandardsIgnoreEnd } } } /** * Not implemented * * @param string $key The key to decrement * @param int $offset The number to offset * @return void * @throws CacheException */ public function decrement($key, $offset = 1) { throw new CacheException(__d('cake_dev', 'Files cannot be atomically decremented.')); } /** * Not implemented * * @param string $key The key to decrement * @param int $offset The number to offset * @return void * @throws CacheException */ public function increment($key, $offset = 1) { throw new CacheException(__d('cake_dev', 'Files cannot be atomically incremented.')); } /** * Sets the current cache key this class is managing, and creates a writable SplFileObject * for the cache file the key is referring to. * * @param string $key The key * @param bool $createKey Whether the key should be created if it doesn't exists, or not * @return bool true if the cache key could be set, false otherwise */ protected function _setKey($key, $createKey = false) { $groups = null; if (!empty($this->_groupPrefix)) { $groups = vsprintf($this->_groupPrefix, $this->groups()); } $dir = $this->settings['path'] . $groups; if (!is_dir($dir)) { mkdir($dir, 0775, true); } $path = new SplFileInfo($dir . $key); if (!$createKey && !$path->isFile()) { return false; } if (empty($this->_File) || $this->_File->getBaseName() !== $key) { $exists = file_exists($path->getPathname()); try { $this->_File = $path->openFile('c+'); } catch (Exception $e) { trigger_error($e->getMessage(), E_USER_WARNING); return false; } unset($path); if (!$exists && !chmod($this->_File->getPathname(), (int)$this->settings['mask'])) { trigger_error(__d( 'cake_dev', 'Could not apply permission mask "%s" on cache file "%s"', array($this->_File->getPathname(), $this->settings['mask'])), E_USER_WARNING); } } return true; } /** * Determine is cache directory is writable * * @return bool */ protected function _active() { $dir = new SplFileInfo($this->settings['path']); if (Configure::read('debug')) { $path = $dir->getPathname(); if (!is_dir($path)) { mkdir($path, 0775, true); } } if ($this->_init && !($dir->isDir() && $dir->isWritable())) { $this->_init = false; trigger_error(__d('cake_dev', '%s is not writable', $this->settings['path']), E_USER_WARNING); return false; } return true; } /** * Generates a safe key for use with cache engine storage engines. * * @param string $key the key passed over * @return mixed string $key or false */ public function key($key) { if (empty($key)) { return false; } $key = Inflector::underscore(str_replace(array(DS, '/', '.', '<', '>', '?', ':', '|', '*', '"'), '_', strval($key))); return $key; } /** * Recursively deletes all files under any directory named as $group * * @param string $group The group to clear. * @return bool success */ public function clearGroup($group) { $this->_File = null; $directoryIterator = new RecursiveDirectoryIterator($this->settings['path']); $contents = new RecursiveIteratorIterator($directoryIterator, RecursiveIteratorIterator::CHILD_FIRST); foreach ($contents as $object) { $containsGroup = strpos($object->getPathName(), DS . $group . DS) !== false; $hasPrefix = true; if (strlen($this->settings['prefix']) !== 0) { $hasPrefix = strpos($object->getBaseName(), $this->settings['prefix']) === 0; } if ($object->isFile() && $containsGroup && $hasPrefix) { $path = $object->getPathName(); $object = null; //@codingStandardsIgnoreStart @unlink($path); //@codingStandardsIgnoreEnd } } return true; } /** * Write data for key into cache if it doesn't exist already. * If it already exists, it fails and returns false. * * @param string $key Identifier for the data. * @param mixed $value Data to be cached. * @param int $duration How long to cache the data, in seconds. * @return bool True if the data was successfully cached, false on failure. */ public function add($key, $value, $duration) { $cachedValue = $this->read($key); if ($cachedValue === false) { return $this->write($key, $value, $duration); } return false; } } cakephp-2.8.0/lib/Cake/Cache/Engine/MemcacheEngine.php000066400000000000000000000217011265552240500223250ustar00rootroot00000000000000 127.0.0.1. If an * array MemcacheEngine will use them as a pool. * - compress = boolean, default => false * * @var array */ public $settings = array(); /** * Initialize the Cache Engine * * Called automatically by the cache frontend * To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array()); * * @param array $settings array of setting for the engine * @return bool True if the engine has been successfully initialized, false if not */ public function init($settings = array()) { if (!class_exists('Memcache')) { return false; } if (!isset($settings['prefix'])) { $settings['prefix'] = Inflector::slug(APP_DIR) . '_'; } $settings += array( 'engine' => 'Memcache', 'servers' => array('127.0.0.1'), 'compress' => false, 'persistent' => true ); parent::init($settings); if ($this->settings['compress']) { $this->settings['compress'] = MEMCACHE_COMPRESSED; } if (is_string($this->settings['servers'])) { $this->settings['servers'] = array($this->settings['servers']); } if (!isset($this->_Memcache)) { $return = false; $this->_Memcache = new Memcache(); foreach ($this->settings['servers'] as $server) { list($host, $port) = $this->_parseServerString($server); if ($this->_Memcache->addServer($host, $port, $this->settings['persistent'])) { $return = true; } } return $return; } return true; } /** * Parses the server address into the host/port. Handles both IPv6 and IPv4 * addresses and Unix sockets * * @param string $server The server address string. * @return array Array containing host, port */ protected function _parseServerString($server) { if (strpos($server, 'unix://') === 0) { return array($server, 0); } if (substr($server, 0, 1) === '[') { $position = strpos($server, ']:'); if ($position !== false) { $position++; } } else { $position = strpos($server, ':'); } $port = 11211; $host = $server; if ($position !== false) { $host = substr($server, 0, $position); $port = substr($server, $position + 1); } return array($host, $port); } /** * Write data for key into cache. When using memcache as your cache engine * remember that the Memcache pecl extension does not support cache expiry times greater * than 30 days in the future. Any duration greater than 30 days will be treated as never expiring. * * @param string $key Identifier for the data * @param mixed $value Data to be cached * @param int $duration How long to cache the data, in seconds * @return bool True if the data was successfully cached, false on failure * @see http://php.net/manual/en/memcache.set.php */ public function write($key, $value, $duration) { if ($duration > 30 * DAY) { $duration = 0; } return $this->_Memcache->set($key, $value, $this->settings['compress'], $duration); } /** * Read a key from the cache * * @param string $key Identifier for the data * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it */ public function read($key) { return $this->_Memcache->get($key); } /** * Increments the value of an integer cached key * * @param string $key Identifier for the data * @param int $offset How much to increment * @return New incremented value, false otherwise * @throws CacheException when you try to increment with compress = true */ public function increment($key, $offset = 1) { if ($this->settings['compress']) { throw new CacheException( __d('cake_dev', 'Method %s not implemented for compressed cache in %s', 'increment()', __CLASS__) ); } return $this->_Memcache->increment($key, $offset); } /** * Decrements the value of an integer cached key * * @param string $key Identifier for the data * @param int $offset How much to subtract * @return New decremented value, false otherwise * @throws CacheException when you try to decrement with compress = true */ public function decrement($key, $offset = 1) { if ($this->settings['compress']) { throw new CacheException( __d('cake_dev', 'Method %s not implemented for compressed cache in %s', 'decrement()', __CLASS__) ); } return $this->_Memcache->decrement($key, $offset); } /** * Delete a key from the cache * * @param string $key Identifier for the data * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ public function delete($key) { return $this->_Memcache->delete($key); } /** * Delete all keys from the cache * * @param bool $check If true no deletes will occur and instead CakePHP will rely * on key TTL values. * @return bool True if the cache was successfully cleared, false otherwise */ public function clear($check) { if ($check) { return true; } foreach ($this->_Memcache->getExtendedStats('slabs', 0) as $slabs) { foreach (array_keys($slabs) as $slabId) { if (!is_numeric($slabId)) { continue; } foreach ($this->_Memcache->getExtendedStats('cachedump', $slabId, 0) as $stats) { if (!is_array($stats)) { continue; } foreach (array_keys($stats) as $key) { if (strpos($key, $this->settings['prefix']) === 0) { $this->_Memcache->delete($key); } } } } } return true; } /** * Connects to a server in connection pool * * @param string $host host ip address or name * @param int $port Server port * @return bool True if memcache server was connected */ public function connect($host, $port = 11211) { if ($this->_Memcache->getServerStatus($host, $port) === 0) { if ($this->_Memcache->connect($host, $port)) { return true; } return false; } return true; } /** * Returns the `group value` for each of the configured groups * If the group initial value was not found, then it initializes * the group accordingly. * * @return array */ public function groups() { if (empty($this->_compiledGroupNames)) { foreach ($this->settings['groups'] as $group) { $this->_compiledGroupNames[] = $this->settings['prefix'] . $group; } } $groups = $this->_Memcache->get($this->_compiledGroupNames); if (count($groups) !== count($this->settings['groups'])) { foreach ($this->_compiledGroupNames as $group) { if (!isset($groups[$group])) { $this->_Memcache->set($group, 1, false, 0); $groups[$group] = 1; } } ksort($groups); } $result = array(); $groups = array_values($groups); foreach ($this->settings['groups'] as $i => $group) { $result[] = $group . $groups[$i]; } return $result; } /** * Increments the group value to simulate deletion of all keys under a group * old values will remain in storage until they expire. * * @param string $group The group to clear. * @return bool success */ public function clearGroup($group) { return (bool)$this->_Memcache->increment($this->settings['prefix'] . $group); } /** * Write data for key into cache if it doesn't exist already. When using memcached as your cache engine * remember that the Memcached PECL extension does not support cache expiry times greater * than 30 days in the future. Any duration greater than 30 days will be treated as never expiring. * If it already exists, it fails and returns false. * * @param string $key Identifier for the data. * @param mixed $value Data to be cached. * @param int $duration How long to cache the data, in seconds. * @return bool True if the data was successfully cached, false on failure. * @link http://php.net/manual/en/memcache.add.php */ public function add($key, $value, $duration) { if ($duration > 30 * DAY) { $duration = 0; } return $this->_Memcache->add($key, $value, $this->settings['compress'], $duration); } } cakephp-2.8.0/lib/Cake/Cache/Engine/MemcachedEngine.php000066400000000000000000000257371265552240500225060ustar00rootroot00000000000000 127.0.0.1. If an * array MemcacheEngine will use them as a pool. * - compress = boolean, default => false * - persistent = string The name of the persistent connection. All configurations using * the same persistent value will share a single underlying connection. * - serialize = string, default => php. The serializer engine used to serialize data. * Available engines are php, igbinary and json. Beside php, the memcached extension * must be compiled with the appropriate serializer support. * - options - Additional options for the memcached client. Should be an array of option => value. * Use the Memcached::OPT_* constants as keys. * * @var array */ public $settings = array(); /** * List of available serializer engines * * Memcached must be compiled with json and igbinary support to use these engines * * @var array */ protected $_serializers = array( 'igbinary' => Memcached::SERIALIZER_IGBINARY, 'json' => Memcached::SERIALIZER_JSON, 'php' => Memcached::SERIALIZER_PHP ); /** * Initialize the Cache Engine * * Called automatically by the cache frontend * To reinitialize the settings call Cache::engine('EngineName', [optional] settings = array()); * * @param array $settings array of setting for the engine * @return bool True if the engine has been successfully initialized, false if not * @throws CacheException when you try use authentication without Memcached compiled with SASL support */ public function init($settings = array()) { if (!class_exists('Memcached')) { return false; } if (!isset($settings['prefix'])) { $settings['prefix'] = Inflector::slug(APP_DIR) . '_'; } if (defined('Memcached::HAVE_MSGPACK') && Memcached::HAVE_MSGPACK) { $this->_serializers['msgpack'] = Memcached::SERIALIZER_MSGPACK; } $settings += array( 'engine' => 'Memcached', 'servers' => array('127.0.0.1'), 'compress' => false, 'persistent' => false, 'login' => null, 'password' => null, 'serialize' => 'php', 'options' => array() ); parent::init($settings); if (!is_array($this->settings['servers'])) { $this->settings['servers'] = array($this->settings['servers']); } if (isset($this->_Memcached)) { return true; } if (!$this->settings['persistent']) { $this->_Memcached = new Memcached(); } else { $this->_Memcached = new Memcached((string)$this->settings['persistent']); } $this->_setOptions(); if (count($this->_Memcached->getServerList())) { return true; } $servers = array(); foreach ($this->settings['servers'] as $server) { $servers[] = $this->_parseServerString($server); } if (!$this->_Memcached->addServers($servers)) { return false; } if ($this->settings['login'] !== null && $this->settings['password'] !== null) { if (!method_exists($this->_Memcached, 'setSaslAuthData')) { throw new CacheException( __d('cake_dev', 'Memcached extension is not build with SASL support') ); } $this->_Memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, true); $this->_Memcached->setSaslAuthData($this->settings['login'], $this->settings['password']); } if (is_array($this->settings['options'])) { foreach ($this->settings['options'] as $opt => $value) { $this->_Memcached->setOption($opt, $value); } } return true; } /** * Settings the memcached instance * * @throws CacheException when the Memcached extension is not built with the desired serializer engine * @return void */ protected function _setOptions() { $this->_Memcached->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true); $serializer = strtolower($this->settings['serialize']); if (!isset($this->_serializers[$serializer])) { throw new CacheException( __d('cake_dev', '%s is not a valid serializer engine for Memcached', $serializer) ); } if ($serializer !== 'php' && !constant('Memcached::HAVE_' . strtoupper($serializer))) { throw new CacheException( __d('cake_dev', 'Memcached extension is not compiled with %s support', $serializer) ); } $this->_Memcached->setOption(Memcached::OPT_SERIALIZER, $this->_serializers[$serializer]); // Check for Amazon ElastiCache instance if (defined('Memcached::OPT_CLIENT_MODE') && defined('Memcached::DYNAMIC_CLIENT_MODE')) { $this->_Memcached->setOption(Memcached::OPT_CLIENT_MODE, Memcached::DYNAMIC_CLIENT_MODE); } $this->_Memcached->setOption(Memcached::OPT_COMPRESSION, (bool)$this->settings['compress']); } /** * Parses the server address into the host/port. Handles both IPv6 and IPv4 * addresses and Unix sockets * * @param string $server The server address string. * @return array Array containing host, port */ protected function _parseServerString($server) { $socketTransport = 'unix://'; if (strpos($server, $socketTransport) === 0) { return array(substr($server, strlen($socketTransport)), 0); } if (substr($server, 0, 1) === '[') { $position = strpos($server, ']:'); if ($position !== false) { $position++; } } else { $position = strpos($server, ':'); } $port = 11211; $host = $server; if ($position !== false) { $host = substr($server, 0, $position); $port = substr($server, $position + 1); } return array($host, (int)$port); } /** * Write data for key into cache. When using memcached as your cache engine * remember that the Memcached PECL extension does not support cache expiry times greater * than 30 days in the future. Any duration greater than 30 days will be treated as never expiring. * * @param string $key Identifier for the data * @param mixed $value Data to be cached * @param int $duration How long to cache the data, in seconds * @return bool True if the data was successfully cached, false on failure * @see http://php.net/manual/en/memcache.set.php */ public function write($key, $value, $duration) { if ($duration > 30 * DAY) { $duration = 0; } return $this->_Memcached->set($key, $value, $duration); } /** * Read a key from the cache * * @param string $key Identifier for the data * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it */ public function read($key) { return $this->_Memcached->get($key); } /** * Increments the value of an integer cached key * * @param string $key Identifier for the data * @param int $offset How much to increment * @return New incremented value, false otherwise * @throws CacheException when you try to increment with compress = true */ public function increment($key, $offset = 1) { return $this->_Memcached->increment($key, $offset); } /** * Decrements the value of an integer cached key * * @param string $key Identifier for the data * @param int $offset How much to subtract * @return New decremented value, false otherwise * @throws CacheException when you try to decrement with compress = true */ public function decrement($key, $offset = 1) { return $this->_Memcached->decrement($key, $offset); } /** * Delete a key from the cache * * @param string $key Identifier for the data * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ public function delete($key) { return $this->_Memcached->delete($key); } /** * Delete all keys from the cache * * @param bool $check If true no deletes will occur and instead CakePHP will rely * on key TTL values. * @return bool True if the cache was successfully cleared, false otherwise. Will * also return false if you are using a binary protocol. */ public function clear($check) { if ($check) { return true; } $keys = $this->_Memcached->getAllKeys(); if ($keys === false) { return false; } foreach ($keys as $key) { if (strpos($key, $this->settings['prefix']) === 0) { $this->_Memcached->delete($key); } } return true; } /** * Returns the `group value` for each of the configured groups * If the group initial value was not found, then it initializes * the group accordingly. * * @return array */ public function groups() { if (empty($this->_compiledGroupNames)) { foreach ($this->settings['groups'] as $group) { $this->_compiledGroupNames[] = $this->settings['prefix'] . $group; } } $groups = $this->_Memcached->getMulti($this->_compiledGroupNames); if (count($groups) !== count($this->settings['groups'])) { foreach ($this->_compiledGroupNames as $group) { if (!isset($groups[$group])) { $this->_Memcached->set($group, 1, 0); $groups[$group] = 1; } } ksort($groups); } $result = array(); $groups = array_values($groups); foreach ($this->settings['groups'] as $i => $group) { $result[] = $group . $groups[$i]; } return $result; } /** * Increments the group value to simulate deletion of all keys under a group * old values will remain in storage until they expire. * * @param string $group The group to clear. * @return bool success */ public function clearGroup($group) { return (bool)$this->_Memcached->increment($this->settings['prefix'] . $group); } /** * Write data for key into cache if it doesn't exist already. When using memcached as your cache engine * remember that the Memcached pecl extension does not support cache expiry times greater * than 30 days in the future. Any duration greater than 30 days will be treated as never expiring. * If it already exists, it fails and returns false. * * @param string $key Identifier for the data. * @param mixed $value Data to be cached. * @param int $duration How long to cache the data, in seconds. * @return bool True if the data was successfully cached, false on failure. * @link http://php.net/manual/en/memcached.add.php */ public function add($key, $value, $duration) { if ($duration > 30 * DAY) { $duration = 0; } return $this->_Memcached->add($key, $value, $duration); } } cakephp-2.8.0/lib/Cake/Cache/Engine/RedisEngine.php000066400000000000000000000162151265552240500216750ustar00rootroot00000000000000 'Redis', 'prefix' => Inflector::slug(APP_DIR) . '_', 'server' => '127.0.0.1', 'database' => 0, 'port' => 6379, 'password' => false, 'timeout' => 0, 'persistent' => true, 'unix_socket' => false ), $settings) ); return $this->_connect(); } /** * Connects to a Redis server * * @return bool True if Redis server was connected */ protected function _connect() { try { $this->_Redis = new Redis(); if (!empty($this->settings['unix_socket'])) { $return = $this->_Redis->connect($this->settings['unix_socket']); } elseif (empty($this->settings['persistent'])) { $return = $this->_Redis->connect($this->settings['server'], $this->settings['port'], $this->settings['timeout']); } else { $persistentId = $this->settings['port'] . $this->settings['timeout'] . $this->settings['database']; $return = $this->_Redis->pconnect($this->settings['server'], $this->settings['port'], $this->settings['timeout'], $persistentId); } } catch (RedisException $e) { $return = false; } if (!$return) { return false; } if ($this->settings['password'] && !$this->_Redis->auth($this->settings['password'])) { return false; } return $this->_Redis->select($this->settings['database']); } /** * Write data for key into cache. * * @param string $key Identifier for the data * @param mixed $value Data to be cached * @param int $duration How long to cache the data, in seconds * @return bool True if the data was successfully cached, false on failure */ public function write($key, $value, $duration) { if (!is_int($value)) { $value = serialize($value); } if (!$this->_Redis->isConnected()) { $this->_connect(); } if ($duration === 0) { return $this->_Redis->set($key, $value); } return $this->_Redis->setex($key, $duration, $value); } /** * Read a key from the cache * * @param string $key Identifier for the data * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it */ public function read($key) { $value = $this->_Redis->get($key); if (ctype_digit($value)) { $value = (int)$value; } if ($value !== false && is_string($value)) { $value = unserialize($value); } return $value; } /** * Increments the value of an integer cached key * * @param string $key Identifier for the data * @param int $offset How much to increment * @return New incremented value, false otherwise * @throws CacheException when you try to increment with compress = true */ public function increment($key, $offset = 1) { return (int)$this->_Redis->incrBy($key, $offset); } /** * Decrements the value of an integer cached key * * @param string $key Identifier for the data * @param int $offset How much to subtract * @return New decremented value, false otherwise * @throws CacheException when you try to decrement with compress = true */ public function decrement($key, $offset = 1) { return (int)$this->_Redis->decrBy($key, $offset); } /** * Delete a key from the cache * * @param string $key Identifier for the data * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ public function delete($key) { return $this->_Redis->delete($key) > 0; } /** * Delete all keys from the cache * * @param bool $check Whether or not expiration keys should be checked. If * true, no keys will be removed as cache will rely on redis TTL's. * @return bool True if the cache was successfully cleared, false otherwise */ public function clear($check) { if ($check) { return true; } $keys = $this->_Redis->getKeys($this->settings['prefix'] . '*'); $this->_Redis->del($keys); return true; } /** * Returns the `group value` for each of the configured groups * If the group initial value was not found, then it initializes * the group accordingly. * * @return array */ public function groups() { $result = array(); foreach ($this->settings['groups'] as $group) { $value = $this->_Redis->get($this->settings['prefix'] . $group); if (!$value) { $value = 1; $this->_Redis->set($this->settings['prefix'] . $group, $value); } $result[] = $group . $value; } return $result; } /** * Increments the group value to simulate deletion of all keys under a group * old values will remain in storage until they expire. * * @param string $group The group name to clear. * @return bool success */ public function clearGroup($group) { return (bool)$this->_Redis->incr($this->settings['prefix'] . $group); } /** * Disconnects from the redis server */ public function __destruct() { if (!$this->settings['persistent']) { $this->_Redis->close(); } } /** * Write data for key into cache if it doesn't exist already. * If it already exists, it fails and returns false. * * @param string $key Identifier for the data. * @param mixed $value Data to be cached. * @param int $duration How long to cache the data, in seconds. * @return bool True if the data was successfully cached, false on failure. * @link https://github.com/phpredis/phpredis#setnx */ public function add($key, $value, $duration) { if (!is_int($value)) { $value = serialize($value); } $result = $this->_Redis->setnx($key, $value); // setnx() doesn't have an expiry option, so overwrite the key with one if ($result) { return $this->_Redis->setex($key, $duration, $value); } return false; } } cakephp-2.8.0/lib/Cake/Cache/Engine/WincacheEngine.php000066400000000000000000000133471265552240500223530ustar00rootroot00000000000000 'Wincache'); parent::init($settings); return function_exists('wincache_ucache_info'); } /** * Write data for key into cache * * @param string $key Identifier for the data * @param mixed $value Data to be cached * @param int $duration How long to cache the data, in seconds * @return bool True if the data was successfully cached, false on failure */ public function write($key, $value, $duration) { $expires = time() + $duration; $data = array( $key . '_expires' => $expires, $key => $value ); $result = wincache_ucache_set($data, null, $duration); return empty($result); } /** * Read a key from the cache * * @param string $key Identifier for the data * @return mixed The cached data, or false if the data doesn't exist, has expired, or if * there was an error fetching it */ public function read($key) { $time = time(); $cachetime = (int)wincache_ucache_get($key . '_expires'); if ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime) { return false; } return wincache_ucache_get($key); } /** * Increments the value of an integer cached key * * @param string $key Identifier for the data * @param int $offset How much to increment * @return New incremented value, false otherwise */ public function increment($key, $offset = 1) { return wincache_ucache_inc($key, $offset); } /** * Decrements the value of an integer cached key * * @param string $key Identifier for the data * @param int $offset How much to subtract * @return New decremented value, false otherwise */ public function decrement($key, $offset = 1) { return wincache_ucache_dec($key, $offset); } /** * Delete a key from the cache * * @param string $key Identifier for the data * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ public function delete($key) { return wincache_ucache_delete($key); } /** * Delete all keys from the cache. This will clear every * item in the cache matching the cache config prefix. * * @param bool $check If true, nothing will be cleared, as entries will * naturally expire in wincache.. * @return bool True Returns true. */ public function clear($check) { if ($check) { return true; } $info = wincache_ucache_info(); $cacheKeys = $info['ucache_entries']; unset($info); foreach ($cacheKeys as $key) { if (strpos($key['key_name'], $this->settings['prefix']) === 0) { wincache_ucache_delete($key['key_name']); } } return true; } /** * Returns the `group value` for each of the configured groups * If the group initial value was not found, then it initializes * the group accordingly. * * @return array */ public function groups() { if (empty($this->_compiledGroupNames)) { foreach ($this->settings['groups'] as $group) { $this->_compiledGroupNames[] = $this->settings['prefix'] . $group; } } $groups = wincache_ucache_get($this->_compiledGroupNames); if (count($groups) !== count($this->settings['groups'])) { foreach ($this->_compiledGroupNames as $group) { if (!isset($groups[$group])) { wincache_ucache_set($group, 1); $groups[$group] = 1; } } ksort($groups); } $result = array(); $groups = array_values($groups); foreach ($this->settings['groups'] as $i => $group) { $result[] = $group . $groups[$i]; } return $result; } /** * Increments the group value to simulate deletion of all keys under a group * old values will remain in storage until they expire. * * @param string $group The group to clear. * @return bool success */ public function clearGroup($group) { $success = null; wincache_ucache_inc($this->settings['prefix'] . $group, 1, $success); return $success; } /** * Write data for key into cache if it doesn't exist already. * If it already exists, it fails and returns false. * * @param string $key Identifier for the data. * @param mixed $value Data to be cached. * @param int $duration How long to cache the data, in seconds. * @return bool True if the data was successfully cached, false on failure. */ public function add($key, $value, $duration) { $cachedValue = $this->read($key); if ($cachedValue === false) { return $this->write($key, $value, $duration); } return false; } } cakephp-2.8.0/lib/Cake/Cache/Engine/XcacheEngine.php000066400000000000000000000144411265552240500220210ustar00rootroot00000000000000 'Xcache', 'prefix' => Inflector::slug(APP_DIR) . '_', 'PHP_AUTH_USER' => 'user', 'PHP_AUTH_PW' => 'password' ), $settings) ); return function_exists('xcache_info'); } return false; } /** * Write data for key into cache * * @param string $key Identifier for the data * @param mixed $value Data to be cached * @param int $duration How long to cache the data, in seconds * @return bool True if the data was successfully cached, false on failure */ public function write($key, $value, $duration) { $expires = time() + $duration; xcache_set($key . '_expires', $expires, $duration); return xcache_set($key, $value, $duration); } /** * Read a key from the cache * * @param string $key Identifier for the data * @return mixed The cached data, or false if the data doesn't exist, has expired, or if there was an error fetching it */ public function read($key) { if (xcache_isset($key)) { $time = time(); $cachetime = (int)xcache_get($key . '_expires'); if ($cachetime < $time || ($time + $this->settings['duration']) < $cachetime) { return false; } return xcache_get($key); } return false; } /** * Increments the value of an integer cached key * If the cache key is not an integer it will be treated as 0 * * @param string $key Identifier for the data * @param int $offset How much to increment * @return New incremented value, false otherwise */ public function increment($key, $offset = 1) { return xcache_inc($key, $offset); } /** * Decrements the value of an integer cached key. * If the cache key is not an integer it will be treated as 0 * * @param string $key Identifier for the data * @param int $offset How much to subtract * @return New decremented value, false otherwise */ public function decrement($key, $offset = 1) { return xcache_dec($key, $offset); } /** * Delete a key from the cache * * @param string $key Identifier for the data * @return bool True if the value was successfully deleted, false if it didn't exist or couldn't be removed */ public function delete($key) { return xcache_unset($key); } /** * Delete all keys from the cache * * @param bool $check If true no deletes will occur and instead CakePHP will rely * on key TTL values. * @return bool True if the cache was successfully cleared, false otherwise */ public function clear($check) { $this->_auth(); $max = xcache_count(XC_TYPE_VAR); for ($i = 0; $i < $max; $i++) { xcache_clear_cache(XC_TYPE_VAR, $i); } $this->_auth(true); return true; } /** * Returns the `group value` for each of the configured groups * If the group initial value was not found, then it initializes * the group accordingly. * * @return array */ public function groups() { $result = array(); foreach ($this->settings['groups'] as $group) { $value = xcache_get($this->settings['prefix'] . $group); if (!$value) { $value = 1; xcache_set($this->settings['prefix'] . $group, $value, 0); } $result[] = $group . $value; } return $result; } /** * Increments the group value to simulate deletion of all keys under a group * old values will remain in storage until they expire. * * @param string $group The group to clear. * @return bool success */ public function clearGroup($group) { return (bool)xcache_inc($this->settings['prefix'] . $group, 1); } /** * Populates and reverses $_SERVER authentication values * Makes necessary changes (and reverting them back) in $_SERVER * * This has to be done because xcache_clear_cache() needs to pass Basic Http Auth * (see xcache.admin configuration settings) * * @param bool $reverse Revert changes * @return void */ protected function _auth($reverse = false) { static $backup = array(); $keys = array('PHP_AUTH_USER' => 'user', 'PHP_AUTH_PW' => 'password'); foreach ($keys as $key => $setting) { if ($reverse) { if (isset($backup[$key])) { $_SERVER[$key] = $backup[$key]; unset($backup[$key]); } else { unset($_SERVER[$key]); } } else { $value = env($key); if (!empty($value)) { $backup[$key] = $value; } if (!empty($this->settings[$setting])) { $_SERVER[$key] = $this->settings[$setting]; } elseif (!empty($this->settings[$key])) { $_SERVER[$key] = $this->settings[$key]; } else { $_SERVER[$key] = $value; } } } } /** * Write data for key into cache if it doesn't exist already. * If it already exists, it fails and returns false. * * @param string $key Identifier for the data. * @param mixed $value Data to be cached. * @param int $duration How long to cache the data, in seconds. * @return bool True if the data was successfully cached, false on failure. */ public function add($key, $value, $duration) { $cachedValue = $this->read($key); if ($cachedValue === false) { return $this->write($key, $value, $duration); } return false; } } cakephp-2.8.0/lib/Cake/Config/000077500000000000000000000000001265552240500157605ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Config/cacert.pem000066400000000000000000007561031265552240500177400ustar00rootroot00000000000000## ## ca-bundle.crt -- Bundle of CA Root Certificates ## ## Certificate data from Mozilla as of: Thu Oct 18 19:05:59 2012 ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from Mozilla's root certificates ## file (certdata.txt). This file can be found in the mozilla source tree: ## http://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1 ## ## It contains the certificates in PEM format and therefore ## can be directly used with curl / libcurl / php_curl, or with ## an Apache+mod_ssl webserver for SSL client authentication. ## Just configure this file as the SSLCACertificateFile. ## # @(#) $RCSfile: certdata.txt,v $ $Revision: 1.86 $ $Date: 2012/10/18 16:26:52 $ GTE CyberTrust Global Root ========================== -----BEGIN CERTIFICATE----- MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0 IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ -----END CERTIFICATE----- Thawte Server CA ================ -----BEGIN CERTIFICATE----- MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0 ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl /Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7 1CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc= -----END CERTIFICATE----- Thawte Premium Server CA ======================== -----BEGIN CERTIFICATE----- MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2 aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2 aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/ qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf 8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t UCemDaYj+bvLpgcUQg== -----END CERTIFICATE----- Equifax Secure CA ================= -----BEGIN CERTIFICATE----- MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5 MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW 8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961 zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95 70+sB3c4 -----END CERTIFICATE----- Digital Signature Trust Co. Global CA 1 ======================================= -----BEGIN CERTIFICATE----- MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMTAeFw05ODEy MTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUA A4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJE NySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2i o74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw IoAPMTk5ODEyMTAxODEwMjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQY MBaAFGp5fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i+DAM BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB ACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lNQseSJqBcNJo4cvj9axY+IO6CizEq kzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4 RbyhkwS7hp86W0N6w4pl -----END CERTIFICATE----- Digital Signature Trust Co. Global CA 3 ======================================= -----BEGIN CERTIFICATE----- MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMjAeFw05ODEy MDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUA A4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGOD VvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JS xhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0 dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw IoAPMTk5ODEyMDkxOTE3MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQY MBaAFB6CTShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5WzAM BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB AEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHRxdf0CiUPPXiBng+xZ8SQTGPdXqfi up/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVLB3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1 mPnHfxsb1gYgAlihw6ID -----END CERTIFICATE----- Verisign Class 3 Public Primary Certification Authority ======================================================= -----BEGIN CERTIFICATE----- MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMx FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVow XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBAgUAA4GBALtMEivPLCYA TxQT3ab7/AoRhIzzKBxnki98tsX63/Dolbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59Ah WM1pF+NEHJwZRDmJXNycAA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2Omuf Tqj/ZA1k -----END CERTIFICATE----- Verisign Class 1 Public Primary Certification Authority - G2 ============================================================ -----BEGIN CERTIFICATE----- MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMgUHJpbWFy eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMgUHJpbWFy eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgd k4xWArzZbxpvUjZudVYKVdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIq WpDBucSmFc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQIDAQAB MA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0Jh9ZrbWB85a7FkCMM XErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2uluIncrKTdcu1OofdPvAbT6shkdHvC lUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68DzFc6PLZ -----END CERTIFICATE----- Verisign Class 2 Public Primary Certification Authority - G2 ============================================================ -----BEGIN CERTIFICATE----- MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQswCQYDVQQGEwJV UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1h cnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNp Z24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1 c3QgTmV0d29yazAeFw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJV UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1h cnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNp Z24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1 c3QgTmV0d29yazCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjx nNuX6Zr8wgQGE75fUsjMHiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRC wiNPStjwDqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cCAwEA ATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9jinb3/7aHmZuovCfTK 1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAXrXfMSTWqz9iP0b63GJZHc2pUIjRk LbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnInjBJ7xUS0rg== -----END CERTIFICATE----- Verisign Class 3 Public Primary Certification Authority - G2 ============================================================ -----BEGIN CERTIFICATE----- MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCO FoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71 lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQAB MA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT 1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTD Oaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpYoJ2daZH9 -----END CERTIFICATE----- GlobalSign Root CA ================== -----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE----- GlobalSign Root CA - R2 ======================= -----BEGIN CERTIFICATE----- MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== -----END CERTIFICATE----- ValiCert Class 1 VA =================== -----BEGIN CERTIFICATE----- MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIy MjM0OFoXDTE5MDYyNTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEg UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA A4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIi GQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCm DuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0LBwG lN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLWI8sogTLDAHkY7FkX icnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPwnXS3qT6gpf+2SQMT2iLM7XGCK5nP Orf1LXLI -----END CERTIFICATE----- ValiCert Class 2 VA =================== -----BEGIN CERTIFICATE----- MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw MTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIg UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA A4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVC CSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7Rf ZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZ SWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbV UjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8 W9ViH0Pd -----END CERTIFICATE----- RSA Root Certificate 1 ====================== -----BEGIN CERTIFICATE----- MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw MjIzM1oXDTE5MDYyNjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0 d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMg UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0 LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA A4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td 3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89H BFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliEZwgs 3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJn0WuPIqpsHEzXcjF V9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/APhmcGcwTTYJBtYze4D1gCCAPRX5r on+jjBXu -----END CERTIFICATE----- Verisign Class 1 Public Primary Certification Authority - G3 ============================================================ -----BEGIN CERTIFICATE----- MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkg Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAN2E1Lm0+afY8wR4nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/E bRrsC+MO8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjVojYJ rKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjbPG7PoBMAGrgnoeS+ Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP26KbqxzcSXKMpHgLZ2x87tNcPVkeB FQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vrn5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA q2aN17O6x5q25lXQBfGfMY1aqtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/N y9Sn2WCVhDr4wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrspSCAaWihT37h a88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4E1Z5T21Q6huwtVexN2ZYI/Pc D98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== -----END CERTIFICATE----- Verisign Class 2 Public Primary Certification Authority - G3 ============================================================ -----BEGIN CERTIFICATE----- MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJBgNVBAYTAlVT MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29y azE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ug b25seTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0 aW9uIEF1dGhvcml0eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJ BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1 c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y aXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBD ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEArwoNwtUs22e5LeWUJ92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6 tW8UvxDOJxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUYwZF7 C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9okoqQHgiBVrKtaaNS 0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjNqWm6o+sdDZykIKbBoMXRRkwXbdKs Zj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/ESrg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0 JhU8wI1NQ0kdvekhktdmnLfexbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf 0xwLRtxyID+u7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RIsH/7NiXaldDx JBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTPcjnhsUPgKM+351psE2tJs//j GHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q -----END CERTIFICATE----- Verisign Class 3 Public Primary Certification Authority - G3 ============================================================ -----BEGIN CERTIFICATE----- MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1 EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj 055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0 xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== -----END CERTIFICATE----- Verisign Class 4 Public Primary Certification Authority - G3 ============================================================ -----BEGIN CERTIFICATE----- MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM 8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== -----END CERTIFICATE----- Entrust.net Secure Server CA ============================ -----BEGIN CERTIFICATE----- MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMCVVMxFDASBgNV BAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5uZXQvQ1BTIGluY29ycC4gYnkg cmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl ZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhv cml0eTAeFw05OTA1MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIG A1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBi eSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1p dGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0 aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQ aO2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5 gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OCAdcw ggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHboIHYpIHVMIHSMQsw CQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5l dC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENl cnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0MFqBDzIwMTkw NTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0Bow HQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAaMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyN Ewr75Ji174z4xRAN95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9 n9cd2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= -----END CERTIFICATE----- Entrust.net Premium 2048 Secure Server CA ========================================= -----BEGIN CERTIFICATE----- MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx NzUwNTFaFw0xOTEyMjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo3QwcjARBglghkgBhvhC AQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGAvtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdER gL7YibkIozH5oSQJFrlwMB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0B AQUFAAOCAQEAWUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQh7A6tcOdBTcS o8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18f3v/rxzP5tsHrV7bhZ3QKw0z 2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfNB/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjX OP/swNlQ8C5LWK5Gb9Auw2DaclVyvUxFnmG6v4SBkgPR0ml8xQ== -----END CERTIFICATE----- Baltimore CyberTrust Root ========================= -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp -----END CERTIFICATE----- Equifax Secure Global eBusiness CA ================================== -----BEGIN CERTIFICATE----- MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT RXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNp bmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMx HDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEds b2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRV PEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzN qfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxn hcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j BBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hs MA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okEN I7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIY NMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV -----END CERTIFICATE----- Equifax Secure eBusiness CA 1 ============================= -----BEGIN CERTIFICATE----- MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT RXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENB LTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UE ChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNz IENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ 1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4a IZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBk MBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kW Nl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQF AAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5 lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+ KpYrtWKmpj29f5JZzVoqgrI3eQ== -----END CERTIFICATE----- Equifax Secure eBusiness CA 2 ============================= -----BEGIN CERTIFICATE----- MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEXMBUGA1UE ChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0y MB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoT DkVxdWlmYXggU2VjdXJlMSYwJAYDVQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCB nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn 2Z0GvxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/BPO3QSQ5 BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0CAwEAAaOCAQkwggEFMHAG A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUx JjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoG A1UdEAQTMBGBDzIwMTkwNjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9e uSBIplBqy/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQFMAMB Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAAyGgq3oThr1 jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia 78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUm V+GRMOrN -----END CERTIFICATE----- AddTrust Low-Value Services Root ================================ -----BEGIN CERTIFICATE----- MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6 54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1 Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= -----END CERTIFICATE----- AddTrust External Root ====================== -----BEGIN CERTIFICATE----- MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821 +iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy 2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7 7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355 e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= -----END CERTIFICATE----- AddTrust Public Services Root ============================= -----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB /zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4 JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL +YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9 Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H EufOX1362KqxMy3ZdvJOOjMMK7MtkAY= -----END CERTIFICATE----- AddTrust Qualified Certificates Root ==================================== -----BEGIN CERTIFICATE----- MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx 64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3 KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/ BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE= -----END CERTIFICATE----- Entrust Root Certification Authority ==================================== -----BEGIN CERTIFICATE----- MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8 -----END CERTIFICATE----- RSA Security 2048 v3 ==================== -----BEGIN CERTIFICATE----- MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7 Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP +Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/ MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj 0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395 nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA pKnXwiJPZ9d37CAFYd4= -----END CERTIFICATE----- GeoTrust Global CA ================== -----BEGIN CERTIFICATE----- MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet 8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4 d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2 mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm Mw== -----END CERTIFICATE----- GeoTrust Global CA 2 ==================== -----BEGIN CERTIFICATE----- MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/ NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7 srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF H4z1Ir+rzoPz4iIprn2DQKi6bA== -----END CERTIFICATE----- GeoTrust Universal CA ===================== -----BEGIN CERTIFICATE----- MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1 MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs 7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d 8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08 ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0 XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2 qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2 DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI P/rmMuGNG2+k5o7Y+SlIis5z/iw= -----END CERTIFICATE----- GeoTrust Universal CA 2 ======================= -----BEGIN CERTIFICATE----- MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0 MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0 DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17 j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2 WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP 20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG 8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2 +/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ 4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+ mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS -----END CERTIFICATE----- UTN-USER First-Network Applications =================================== -----BEGIN CERTIFICATE----- MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCBozELMAkGA1UE BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzAp BgNVBAMTIlVUTi1VU0VSRmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5 WhcNMTkwNzA5MTg1NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5T YWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3QtTmV0d29yayBB cHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz+5Gh5DZVhawGNFug mliy+LUPBXeDrjKxdpJo7CNKyXY/45y2N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4Cj DUeJT1FxL+78P/m4FoCHiZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXu Ozr0hAReYFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1axwi P8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6gyN7igEL66S/ozjIE j3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8w HQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPhahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9j cmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0G CSqGSIb3DQEBBQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6LzsQCv4AdRWOOTK RIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4ZSfP1FMa8Kxun08FDAOBp4Qp xFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qMYEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAq DbUMo2s/rn9X9R+WfN9v3YIwLGUbQErNaLly7HF27FSOH4UMAWr6pjisH8SE -----END CERTIFICATE----- America Online Root Certification Authority 1 ============================================= -----BEGIN CERTIFICATE----- MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp Y2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkG A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CG v2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44z DyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145LcxVR5lu9Rh sCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP 8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0T AQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Z o/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEf GDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrF VL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft 3OJvx8Fi8eNy1gTIdGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7 -----END CERTIFICATE----- America Online Root Certification Authority 2 ============================================= -----BEGIN CERTIFICATE----- MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp Y2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkG A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC206B89en fHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFciKtZHgVdEglZTvYYUAQv8 f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2JxhP7JsowtS013wMPgwr38oE18aO6lhO qKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JN RvCAOVIyD+OEsnpD8l7eXz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0 gBe4lL8BPeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn 6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEqZ8A9W6Wa6897Gqid FEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZo2C7HK2JNDJiuEMhBnIMoVxtRsX6 Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnj B453cMor9H124HhnAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3Op aaEg5+31IqEjFNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmnxPBUlgtk87FY T15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2LHo1YGwRgJfMqZJS5ivmae2p +DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzcccobGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXg JXUjhx5c3LqdsKyzadsXg8n33gy8CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//Zoy zH1kUQ7rVyZ2OuMeIjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgO ZtMADjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2FAjgQ5ANh 1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUXOm/9riW99XJZZLF0Kjhf GEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPbAZO1XB4Y3WRayhgoPmMEEf0cjQAPuDff Z4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQlZvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuP cX/9XhmgD0uRuMRUvAawRY8mkaKO/qk= -----END CERTIFICATE----- Visa eCommerce Root =================== -----BEGIN CERTIFICATE----- MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2 WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0 TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI /k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt 398znM/jra6O1I7mT1GvFpLgXPYHDw== -----END CERTIFICATE----- Certum Root CA ============== -----BEGIN CERTIFICATE----- MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ 89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+ GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/ 0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw== -----END CERTIFICATE----- Comodo AAA Services root ======================== -----BEGIN CERTIFICATE----- MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== -----END CERTIFICATE----- Comodo Secure Services root =========================== -----BEGIN CERTIFICATE----- MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP 9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm 4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H RR3B7Hzs/Sk= -----END CERTIFICATE----- Comodo Trusted Services root ============================ -----BEGIN CERTIFICATE----- MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7 3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y /9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6 juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB /zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O 9y5Xt5hwXsjEeLBi -----END CERTIFICATE----- QuoVadis Root CA ================ -----BEGIN CERTIFICATE----- MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7 MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0 aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6 tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi 5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi 5nrQNiOKSnQ2+Q== -----END CERTIFICATE----- QuoVadis Root CA 2 ================== -----BEGIN CERTIFICATE----- MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u -----END CERTIFICATE----- QuoVadis Root CA 3 ================== -----BEGIN CERTIFICATE----- MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto= -----END CERTIFICATE----- Security Communication Root CA ============================== -----BEGIN CERTIFICATE----- MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi FL39vmwLAw== -----END CERTIFICATE----- Sonera Class 1 Root CA ====================== -----BEGIN CERTIFICATE----- MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAxMDQwNjEwNDkxM1oXDTIxMDQw NjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh IENsYXNzMSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H88 7dF+2rDNbS82rDTG29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9 EJUkoVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk3w0LBUXl 0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBLqdReLjVQCfOAl/QMF645 2F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIINnvmLVz5MxxftLItyM19yejhW1ebZrgUa HXVFsculJRwSVzb9IjcCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZT iFIwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE9 28Jj2VuXZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0HDjxV yhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VOTzF2nBBhjrZTOqMR vq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2UvkVrCqIexVmiUefkl98HVrhq4uz2P qYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4wzMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9Z IRlXvVWa -----END CERTIFICATE----- Sonera Class 2 Root CA ====================== -----BEGIN CERTIFICATE----- MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3 /Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt 0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH llpwrN9M -----END CERTIFICATE----- Staat der Nederlanden Root CA ============================= -----BEGIN CERTIFICATE----- MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6 22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== -----END CERTIFICATE----- TDC Internet Root CA ==================== -----BEGIN CERTIFICATE----- MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJESzEVMBMGA1UE ChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTAeFw0wMTA0MDUx NjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJu ZXQxHTAbBgNVBAsTFFREQyBJbnRlcm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAxLhAvJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20j xsNuZp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a0vnRrEvL znWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc14izbSysseLlJ28TQx5yc 5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGNeGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6 otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcDR0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZI AYb4QgEBBAQDAgAHMGUGA1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMM VERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxMEQ1JM MTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3WjALBgNVHQ8EBAMC AQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAwHQYDVR0OBBYEFGxkAcf9hW2syNqe UAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0G CSqGSIb3DQEBBQUAA4IBAQBOQ8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540m gwV5dOy0uaOXwTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+ 2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm899qNLPg7kbWzb O0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0jUNAE4z9mQNUecYu6oah9jrU Cbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38aQNiuJkFBT1reBK9sG9l -----END CERTIFICATE----- TDC OCES Root CA ================ -----BEGIN CERTIFICATE----- MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJESzEMMAoGA1UE ChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEwODM5MzBaFw0zNzAyMTEwOTA5 MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNUREMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuH nEz9pPPEXyG9VhDr2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0 zY0s2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItUGBxIYXvV iGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKjdGqPqcNiKXEx5TukYBde dObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+rTpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO 3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB 5DCB4TCB3gYIKoFQgSkBAQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5k ay9yZXBvc2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRlciBm cmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEuMS4xLiBDZXJ0aWZp Y2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEuMS4x LjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1UdHwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEM MAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYm aHR0cDovL2NybC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZJ2cdUBVLc647 +RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqGSIb2fQdBAAQQMA4bCFY2LjA6 NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACromJkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4 A9G28kNBKWKnctj7fAXmMXAnVBhOinxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYsc A+UYyAFMP8uXBV2YcaaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9 AOoBmbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQYqbsFbS1 AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9BKNDLdr8C2LqL19iUw== -----END CERTIFICATE----- UTN DATACorp SGC Root CA ======================== -----BEGIN CERTIFICATE----- MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA 9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv 33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9 BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3 DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0 I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI -----END CERTIFICATE----- UTN USERFirst Email Root CA =========================== -----BEGIN CERTIFICATE----- MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCBrjELMAkGA1UE BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0 BgNVBAMTLVVUTi1VU0VSRmlyc3QtQ2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05 OTA3MDkxNzI4NTBaFw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQx FzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsx ITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UEAxMtVVROLVVTRVJGaXJz dC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWlsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3BYHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIx B8dOtINknS4p1aJkxIW9hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8 om+rWV6lL8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLmSGHG TPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM1tZUOt4KpLoDd7Nl yP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws6wIDAQABo4G5MIG2MAsGA1UdDwQE AwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNV HR8EUTBPME2gS6BJhkdodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGll bnRBdXRoZW50aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u7mFVbwQ+zzne xRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0xtcgBEXkzYABurorbs6q15L+ 5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQrfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarV NZ1yQAOJujEdxRBoUp7fooXFXAimeOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZ w7JHpsIyYdfHb0gkUSeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ= -----END CERTIFICATE----- UTN USERFirst Hardware Root CA ============================== -----BEGIN CERTIFICATE----- MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0 eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8 i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM //bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2 lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67 nfhmqA== -----END CERTIFICATE----- UTN USERFirst Object Root CA ============================ -----BEGIN CERTIFICATE----- MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UE BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAb BgNVBAMTFFVUTi1VU0VSRmlyc3QtT2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAz NlowgZUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkx HjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3dy51c2Vy dHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicPHxzfOpuCaDDASmEd8S8O+r5596Uj71VR loTN2+O5bj4x2AogZ8f02b+U60cEPgLOKqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQ w5ujm9M89RKZd7G3CeBo5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vu lBe3/IW+pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehbkkj7 RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUCAwEAAaOBrzCBrDAL BgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU2u1kdBScFDyr3ZmpvVsoTYs8 ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmly c3QtT2JqZWN0LmNybDApBgNVHSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQw DQYJKoZIhvcNAQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXBmMiKVl0+7kNO PmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU4U3GDZlDAQ0Slox4nb9QorFE qmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK581OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCG hU3IfdeLA/5u1fedFqySLKAj5ZyRUh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g= -----END CERTIFICATE----- Camerfirma Chambers of Commerce Root ==================================== -----BEGIN CERTIFICATE----- MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1 erfutGWaIZDgqtCYvDi1czyL+Nw= -----END CERTIFICATE----- Camerfirma Global Chambersign Root ================================== -----BEGIN CERTIFICATE----- MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J 1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl 6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c 8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/ BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4 IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== -----END CERTIFICATE----- NetLock Qualified (Class QA) Root ================================= -----BEGIN CERTIFICATE----- MIIG0TCCBbmgAwIBAgIBezANBgkqhkiG9w0BAQUFADCByTELMAkGA1UEBhMCSFUxETAPBgNVBAcT CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV BAsTEVRhbnVzaXR2YW55a2lhZG9rMUIwQAYDVQQDEzlOZXRMb2NrIE1pbm9zaXRldHQgS296amVn eXpvaSAoQ2xhc3MgUUEpIFRhbnVzaXR2YW55a2lhZG8xHjAcBgkqhkiG9w0BCQEWD2luZm9AbmV0 bG9jay5odTAeFw0wMzAzMzAwMTQ3MTFaFw0yMjEyMTUwMTQ3MTFaMIHJMQswCQYDVQQGEwJIVTER MA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNhZ2kgS2Z0 LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxQjBABgNVBAMTOU5ldExvY2sgTWlub3NpdGV0 dCBLb3pqZWd5em9pIChDbGFzcyBRQSkgVGFudXNpdHZhbnlraWFkbzEeMBwGCSqGSIb3DQEJARYP aW5mb0BuZXRsb2NrLmh1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx1Ilstg91IRV CacbvWy5FPSKAtt2/GoqeKvld/Bu4IwjZ9ulZJm53QE+b+8tmjwi8F3JV6BVQX/yQ15YglMxZc4e 8ia6AFQer7C8HORSjKAyr7c3sVNnaHRnUPYtLmTeriZ539+Zhqurf4XsoPuAzPS4DB6TRWO53Lhb m+1bOdRfYrCnjnxmOCyqsQhjF2d9zL2z8cM/z1A57dEZgxXbhxInlrfa6uWdvLrqOU+L73Sa58XQ 0uqGURzk/mQIKAR5BevKxXEOC++r6uwSEaEYBTJp0QwsGj0lmT+1fMptsK6ZmfoIYOcZwvK9UdPM 0wKswREMgM6r3JSda6M5UzrWhQIDAMV9o4ICwDCCArwwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV HQ8BAf8EBAMCAQYwggJ1BglghkgBhvhCAQ0EggJmFoICYkZJR1lFTEVNISBFemVuIHRhbnVzaXR2 YW55IGEgTmV0TG9jayBLZnQuIE1pbm9zaXRldHQgU3pvbGdhbHRhdGFzaSBTemFiYWx5emF0YWJh biBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBBIG1pbm9zaXRldHQgZWxla3Ryb25p a3VzIGFsYWlyYXMgam9naGF0YXMgZXJ2ZW55ZXN1bGVzZW5laywgdmFsYW1pbnQgZWxmb2dhZGFz YW5hayBmZWx0ZXRlbGUgYSBNaW5vc2l0ZXR0IFN6b2xnYWx0YXRhc2kgU3phYmFseXphdGJhbiwg YXogQWx0YWxhbm9zIFN6ZXJ6b2Rlc2kgRmVsdGV0ZWxla2JlbiBlbG9pcnQgZWxsZW5vcnplc2kg ZWxqYXJhcyBtZWd0ZXRlbGUuIEEgZG9rdW1lbnR1bW9rIG1lZ3RhbGFsaGF0b2sgYSBodHRwczov L3d3dy5uZXRsb2NrLmh1L2RvY3MvIGNpbWVuIHZhZ3kga2VyaGV0b2sgYXogaW5mb0BuZXRsb2Nr Lm5ldCBlLW1haWwgY2ltZW4uIFdBUk5JTkchIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0 aGlzIGNlcnRpZmljYXRlIGFyZSBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIFF1YWxpZmllZCBDUFMg YXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3Lm5ldGxvY2suaHUvZG9jcy8gb3IgYnkgZS1tYWlsIGF0 IGluZm9AbmV0bG9jay5uZXQwHQYDVR0OBBYEFAlqYhaSsFq7VQ7LdTI6MuWyIckoMA0GCSqGSIb3 DQEBBQUAA4IBAQCRalCc23iBmz+LQuM7/KbD7kPgz/PigDVJRXYC4uMvBcXxKufAQTPGtpvQMznN wNuhrWw3AkxYQTvyl5LGSKjN5Yo5iWH5Upfpvfb5lHTocQ68d4bDBsxafEp+NFAwLvt/MpqNPfMg W/hqyobzMUwsWYACff44yTB1HLdV47yfuqhthCgFdbOLDcCRVCHnpgu0mfVRQdzNo0ci2ccBgcTc R08m6h/t280NmPSjnLRzMkqWmf68f8glWPhY83ZmiVSkpj7EUFy6iRiCdUgh0k8T6GB+B3bbELVR 5qq5aKrN9p2QdRLqOBrKROi3macqaJVmlaut74nLYKkGEsaUR+ko -----END CERTIFICATE----- NetLock Notary (Class A) Root ============================= -----BEGIN CERTIFICATE----- MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC /tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7 tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6 4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0 ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5 ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM 8CgHrTwXZoi1/baI -----END CERTIFICATE----- NetLock Business (Class B) Root =============================== -----BEGIN CERTIFICATE----- MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUxETAPBgNVBAcT CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV BAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQDEylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikg VGFudXNpdHZhbnlraWFkbzAeFw05OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYD VQQGEwJIVTERMA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRv bnNhZ2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5ldExvY2sg VXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB iQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2S o/1bXHQawEfKOml2mrriRBf8TKPV/riXiK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr 1nGTLbO/CVRY7QbrqHvcQ7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV HQ8BAf8EBAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZ RUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRh dGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQuIEEgaGl0 ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRv c2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUg YXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBz Oi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6ZXNA bmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhl IHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2 YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBj cHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06sPgzTEdM 43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXan3BukxowOR0w2y7jfLKR stE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKSNitjrFgBazMpUIaD8QFI -----END CERTIFICATE----- NetLock Express (Class C) Root ============================== -----BEGIN CERTIFICATE----- MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUxETAPBgNVBAcT CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV BAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQDEytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBD KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJ BgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6 dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMrTmV0TG9j ayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzANBgkqhkiG9w0BAQEFAAOB jQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNAOoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3Z W3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63 euyucYT2BDMIJTLrdKwWRMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQw DgYDVR0PAQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEWggJN RklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0YWxhbm9zIFN6b2xn YWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBB IGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBOZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1i aXp0b3NpdGFzYSB2ZWRpLiBBIGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0 ZWxlIGF6IGVsb2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25sYXBqYW4gYSBo dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kga2VyaGV0byBheiBlbGxlbm9y emVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4gSU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5k IHRoZSB1c2Ugb2YgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQ UyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwg YXQgY3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmYta3UzbM2 xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2gpO0u9f38vf5NNwgMvOOW gyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4Fp1hBWeAyNDYpQcCNJgEjTME1A== -----END CERTIFICATE----- XRamp Global CA Root ==================== -----BEGIN CERTIFICATE----- MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw= -----END CERTIFICATE----- Go Daddy Class 2 CA =================== -----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b vZ8= -----END CERTIFICATE----- Starfield Class 2 CA ==================== -----BEGIN CERTIFICATE----- MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3 QBFGmh95DmK/D5fs4C8fF5Q= -----END CERTIFICATE----- StartCom Certification Authority ================================ -----BEGIN CERTIFICATE----- MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT 37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0 Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5 LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh 3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3 fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl 1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/ lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro g14= -----END CERTIFICATE----- Taiwan GRCA =========== -----BEGIN CERTIFICATE----- MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5 BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O 1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7 Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8 lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2 09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2 Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk 7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy +fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS -----END CERTIFICATE----- Firmaprofesional Root CA ======================== -----BEGIN CERTIFICATE----- MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMxIjAgBgNVBAcT GUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1dG9yaWRhZCBkZSBDZXJ0aWZp Y2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FA ZmlybWFwcm9mZXNpb25hbC5jb20wHhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTEL MAkGA1UEBhMCRVMxIjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMT OUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2 ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20wggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5uCp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5V j1H5WuretXDE7aTt/6MNbg9kUDGvASdYrv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJH lShbz++AbOCQl4oBPB3zhxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf 3H5idPayBQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcLiam8 NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcbAgMBAAGjgZ8wgZww KgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lvbmFsLmNvbTASBgNVHRMBAf8ECDAG AQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1Ud DwEB/wQEAwIBBjAdBgNVHQ4EFgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQAD ggEBAEdz/o0nVPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36mhoEyIwOdyPdf wUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzflZKG+TQyTmAyX9odtsz/ny4Cm 7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBpQWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YG VM+h4k0460tQtcsm9MracEpqoeJ5quGnM/b9Sh/22WA= -----END CERTIFICATE----- Wells Fargo Root CA =================== -----BEGIN CERTIFICATE----- MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMxFDASBgNV BAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhv cml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN MDAxMDExMTY0MTI4WhcNMjEwMTE0MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dl bGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEv MC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n135zHCLielTWi5MbqNQ1mX x3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHESxP9cMIlrCL1dQu3U+SlK93OvRw6esP3 E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4OJgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5 OEL8pahbSCOz6+MlsoCultQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4j sNtlAHCEAQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMBAAGj YTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcBCzAyMDAGCCsGAQUF BwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRwb2xpY3kwDQYJKoZIhvcNAQEFBQAD ggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrv m+0fazbuSCUlFLZWohDo7qd/0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0R OhPs7fpvcmR7nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ33ZwmVxwQ023 tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s= -----END CERTIFICATE----- Swisscom Root CA 1 ================== -----BEGIN CERTIFICATE----- MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4 MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn 7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5 haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9 MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3 1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW NY6E0F/6MBr1mmz0DlP5OlvRHA== -----END CERTIFICATE----- DigiCert Assured ID Root CA =========================== -----BEGIN CERTIFICATE----- MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== -----END CERTIFICATE----- DigiCert Global Root CA ======================= -----BEGIN CERTIFICATE----- MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE----- DigiCert High Assurance EV Root CA ================================== -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K -----END CERTIFICATE----- Certplus Class 2 Primary CA =========================== -----BEGIN CERTIFICATE----- MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR 5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+ 7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW //1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 l7+ijrRU -----END CERTIFICATE----- DST Root CA X3 ============== -----BEGIN CERTIFICATE----- MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1 cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9 UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ -----END CERTIFICATE----- DST ACES CA X6 ============== -----BEGIN CERTIFICATE----- MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2 5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3 oKfN5XozNmr6mis= -----END CERTIFICATE----- TURKTRUST Certificate Services Provider Root 1 ============================================== -----BEGIN CERTIFICATE----- MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0 acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ 8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4 W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46 sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H -----END CERTIFICATE----- TURKTRUST Certificate Services Provider Root 2 ============================================== -----BEGIN CERTIFICATE----- MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr 5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+ hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P 9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5 UrbnBEI= -----END CERTIFICATE----- SwissSign Platinum CA - G2 ========================== -----BEGIN CERTIFICATE----- MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCQ0gxFTAT BgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWduIFBsYXRpbnVtIENBIC0gRzIw HhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAwWjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMM U3dpc3NTaWduIEFHMSMwIQYDVQQDExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJ KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu 669yIIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2HtnIuJpX+UF eNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+6ixuEFGSzH7VozPY1kne WCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5objM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIo j5+saCB9bzuohTEJfwvH6GXp43gOCWcwizSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/6 8++QHkwFix7qepF6w9fl+zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34T aNhxKFrYzt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaPpZjy domyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtFKwH3HBqi7Ri6Cr2D +m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuWae5ogObnmLo2t/5u7Su9IPhlGdpV CX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMBAAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCv zAeHFUdvOMW0ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUAA4ICAQAIhab1 Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0uMoI3LQwnkAHFmtllXcBrqS3 NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4 U99REJNi54Av4tHgvI42Rncz7Lj7jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8 KV2LwUvJ4ooTHbG/u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl 9x8DYSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1puEa+S1B aYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXaicYwu+uPyyIIoK6q8QNs OktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbGDI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSY Mdp08YSTcU1f+2BY0fvEwW2JorsgH51xkcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAci IfNAChs0B0QTwoRqjt8ZWr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g== -----END CERTIFICATE----- SwissSign Gold CA - G2 ====================== -----BEGIN CERTIFICATE----- MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ -----END CERTIFICATE----- SwissSign Silver CA - G2 ======================== -----BEGIN CERTIFICATE----- MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u -----END CERTIFICATE----- GeoTrust Primary Certification Authority ======================================== -----BEGIN CERTIFICATE----- MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9 nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG 1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= -----END CERTIFICATE----- thawte Primary Root CA ====================== -----BEGIN CERTIFICATE----- MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3 MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ 1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89 jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA== -----END CERTIFICATE----- VeriSign Class 3 Public Primary Certification Authority - G5 ============================================================ -----BEGIN CERTIFICATE----- MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/ Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/ BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+ X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq -----END CERTIFICATE----- SecureTrust CA ============== -----BEGIN CERTIFICATE----- MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= -----END CERTIFICATE----- Secure Global CA ================ -----BEGIN CERTIFICATE----- MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+ OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW -----END CERTIFICATE----- COMODO Certification Authority ============================== -----BEGIN CERTIFICATE----- MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ== -----END CERTIFICATE----- Network Solutions Certificate Authority ======================================= -----BEGIN CERTIFICATE----- MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/ GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey -----END CERTIFICATE----- WellsSecure Public Root Certificate Authority ============================================= -----BEGIN CERTIFICATE----- MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1 iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13 i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8 bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0 bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ tylv2G0xffX8oRAHh84vWdw+WNs= -----END CERTIFICATE----- COMODO ECC Certification Authority ================================== -----BEGIN CERTIFICATE----- MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= -----END CERTIFICATE----- IGC/A ===== -----BEGIN CERTIFICATE----- MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8wDQYD VQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVE Q1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZy MB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQI EwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NT STEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaIs9z4iPf930Pfeo2aSVz2 TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCW So7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYy HF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNd frGoRpAxVs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQ tQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqB egF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDC iQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RK q89toB9RlPhJy3Q2FLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3Q MZsyK10XZZOYYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNI lQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF 0mBWWg== -----END CERTIFICATE----- Security Communication EV RootCA1 ================================= -----BEGIN CERTIFICATE----- MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO /VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4 bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK 9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 -----END CERTIFICATE----- OISTE WISeKey Global Root GA CA =============================== -----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5 IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9 Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ /yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4 +vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0= -----END CERTIFICATE----- S-TRUST Authentication and Encryption Root CA 2005 PN ===================================================== -----BEGIN CERTIFICATE----- MIIEezCCA2OgAwIBAgIQNxkY5lNUfBq1uMtZWts1tzANBgkqhkiG9w0BAQUFADCBrjELMAkGA1UE BhMCREUxIDAeBgNVBAgTF0JhZGVuLVd1ZXJ0dGVtYmVyZyAoQlcpMRIwEAYDVQQHEwlTdHV0dGdh cnQxKTAnBgNVBAoTIERldXRzY2hlciBTcGFya2Fzc2VuIFZlcmxhZyBHbWJIMT4wPAYDVQQDEzVT LVRSVVNUIEF1dGhlbnRpY2F0aW9uIGFuZCBFbmNyeXB0aW9uIFJvb3QgQ0EgMjAwNTpQTjAeFw0w NTA2MjIwMDAwMDBaFw0zMDA2MjEyMzU5NTlaMIGuMQswCQYDVQQGEwJERTEgMB4GA1UECBMXQmFk ZW4tV3VlcnR0ZW1iZXJnIChCVykxEjAQBgNVBAcTCVN0dXR0Z2FydDEpMCcGA1UEChMgRGV1dHNj aGVyIFNwYXJrYXNzZW4gVmVybGFnIEdtYkgxPjA8BgNVBAMTNVMtVFJVU1QgQXV0aGVudGljYXRp b24gYW5kIEVuY3J5cHRpb24gUm9vdCBDQSAyMDA1OlBOMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEA2bVKwdMz6tNGs9HiTNL1toPQb9UY6ZOvJ44TzbUlNlA0EmQpoVXhOmCTnijJ4/Ob 4QSwI7+Vio5bG0F/WsPoTUzVJBY+h0jUJ67m91MduwwA7z5hca2/OnpYH5Q9XIHV1W/fuJvS9eXL g3KSwlOyggLrra1fFi2SU3bxibYs9cEv4KdKb6AwajLrmnQDaHgTncovmwsdvs91DSaXm8f1Xgqf eN+zvOyauu9VjxuapgdjKRdZYgkqeQd3peDRF2npW932kKvimAoA0SVtnteFhy+S8dF2g08LOlk3 KC8zpxdQ1iALCvQm+Z845y2kuJuJja2tyWp9iRe79n+Ag3rm7QIDAQABo4GSMIGPMBIGA1UdEwEB /wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMCkGA1UdEQQiMCCkHjAcMRowGAYDVQQDExFTVFJv bmxpbmUxLTIwNDgtNTAdBgNVHQ4EFgQUD8oeXHngovMpttKFswtKtWXsa1IwHwYDVR0jBBgwFoAU D8oeXHngovMpttKFswtKtWXsa1IwDQYJKoZIhvcNAQEFBQADggEBAK8B8O0ZPCjoTVy7pWMciDMD pwCHpB8gq9Yc4wYfl35UvbfRssnV2oDsF9eK9XvCAPbpEW+EoFolMeKJ+aQAPzFoLtU96G7m1R08 P7K9n3frndOMusDXtk3sU5wPBG7qNWdX4wple5A64U8+wwCSersFiXOMy6ZNwPv2AtawB6MDwidA nwzkhYItr5pCHdDHjfhA7p0GVxzZotiAFP7hYy0yh9WUUpY6RsZxlj33mA6ykaqP2vROJAA5Veit F7nTNCtKqUDMFypVZUF0Qn71wK/Ik63yGFs9iQzbRzkk+OBM8h+wPQrKBU6JIRrjKpms/H+h8Q8b Hz2eBIPdltkdOpQ= -----END CERTIFICATE----- Microsec e-Szigno Root CA ========================= -----BEGIN CERTIFICATE----- MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0 MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3 LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA 4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6 Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a 86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= -----END CERTIFICATE----- Certigna ======== -----BEGIN CERTIFICATE----- MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+ ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== -----END CERTIFICATE----- AC Ra\xC3\xADz Certic\xC3\xA1mara S.A. ====================================== -----BEGIN CERTIFICATE----- MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNVBAYT AkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRpZmljYWNpw7NuIERpZ2l0YWwg LSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwaQUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4w HhcNMDYxMTI3MjA0NjI5WhcNMzAwNDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+ U29jaWVkYWQgQ2FtZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJh IFMuQS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeGqentLhM0R7LQcNzJPNCN yu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzLfDe3fezTf3MZsGqy2IiKLUV0qPezuMDU 2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQY5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU3 4ojC2I+GdV75LaeHM/J4Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP 2yYe68yQ54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+bMMCm 8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48jilSH5L887uvDdUhf HjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++EjYfDIJss2yKHzMI+ko6Kh3VOz3vCa Mh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/ztA/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK 5lw1omdMEWux+IBkAC1vImHFrEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1b czwmPS9KvqfJpxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCBlTCBkgYEVR0g ADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFyYS5jb20vZHBjLzBaBggrBgEF BQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW507WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2Ug cHVlZGVuIGVuY29udHJhciBlbiBsYSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEf AygPU3zmpFmps4p6xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuX EpBcunvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/Jre7Ir5v /zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dpezy4ydV/NgIlqmjCMRW3 MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42gzmRkBDI8ck1fj+404HGIGQatlDCIaR4 3NAvO2STdPCWkPHv+wlaNECW8DYSwaN0jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wk eZBWN7PGKX6jD/EpOe9+XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f /RWmnkJDW2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/RL5h RqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35rMDOhYil/SrnhLecU Iw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxkBYn8eNZcLCZDqQ== -----END CERTIFICATE----- TC TrustCenter Class 2 CA II ============================ -----BEGIN CERTIFICATE----- MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2 xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB 7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk vQ== -----END CERTIFICATE----- TC TrustCenter Class 3 CA II ============================ -----BEGIN CERTIFICATE----- MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy IENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYw MTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1 c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UE AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJWHt4bNwcwIi9v8Qbxq63W yKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+QVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo 6SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZ uV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk 2ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB 7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90 Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU cnVzdENlbnRlciUyMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzE O2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8 yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9 IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal 092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc 5A== -----END CERTIFICATE----- TC TrustCenter Universal CA I ============================= -----BEGIN CERTIFICATE----- MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG 1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3 ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a 7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY -----END CERTIFICATE----- Deutsche Telekom Root CA 2 ========================== -----BEGIN CERTIFICATE----- MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5 MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5 bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8 rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU Cm26OWMohpLzGITY+9HPBVZkVw== -----END CERTIFICATE----- ComSign CA ========== -----BEGIN CERTIFICATE----- MIIDkzCCAnugAwIBAgIQFBOWgxRVjOp7Y+X8NId3RDANBgkqhkiG9w0BAQUFADA0MRMwEQYDVQQD EwpDb21TaWduIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0wNDAzMjQxMTMy MThaFw0yOTAzMTkxNTAyMThaMDQxEzARBgNVBAMTCkNvbVNpZ24gQ0ExEDAOBgNVBAoTB0NvbVNp Z24xCzAJBgNVBAYTAklMMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8ORUaSvTx49q ROR+WCf4C9DklBKK8Rs4OC8fMZwG1Cyn3gsqrhqg455qv588x26i+YtkbDqthVVRVKU4VbirgwTy P2Q298CNQ0NqZtH3FyrV7zb6MBBC11PN+fozc0yz6YQgitZBJzXkOPqUm7h65HkfM/sb2CEJKHxN GGleZIp6GZPKfuzzcuc3B1hZKKxC+cX/zT/npfo4sdAMx9lSGlPWgcxCejVb7Us6eva1jsz/D3zk YDaHL63woSV9/9JLEYhwVKZBqGdTUkJe5DSe5L6j7KpiXd3DTKaCQeQzC6zJMw9kglcq/QytNuEM rkvF7zuZ2SOzW120V+x0cAwqTwIDAQABo4GgMIGdMAwGA1UdEwQFMAMBAf8wPQYDVR0fBDYwNDAy oDCgLoYsaHR0cDovL2ZlZGlyLmNvbXNpZ24uY28uaWwvY3JsL0NvbVNpZ25DQS5jcmwwDgYDVR0P AQH/BAQDAgGGMB8GA1UdIwQYMBaAFEsBmz5WGmU2dst7l6qSBe4y5ygxMB0GA1UdDgQWBBRLAZs+ VhplNnbLe5eqkgXuMucoMTANBgkqhkiG9w0BAQUFAAOCAQEA0Nmlfv4pYEWdfoPPbrxHbvUanlR2 QnG0PFg/LUAlQvaBnPGJEMgOqnhPOAlXsDzACPw1jvFIUY0McXS6hMTXcpuEfDhOZAYnKuGntewI mbQKDdSFc8gS4TXt8QUxHXOZDOuWyt3T5oWq8Ir7dcHyCTxlZWTzTNity4hp8+SDtwy9F1qWF8pb /627HOkthIDYIb6FUtnUdLlphbpN7Sgy6/lhSuTENh4Z3G+EER+V9YMoGKgzkkMn3V0TBEVPh9VG zT2ouvDzuFYkRes3x+F2T3I5GN9+dHLHcy056mDmrRGiVod7w2ia/viMcKjfZTL0pECMocJEAw6U AGegcQCCSA== -----END CERTIFICATE----- ComSign Secured CA ================== -----BEGIN CERTIFICATE----- MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs 49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH 7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1 9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP 51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== -----END CERTIFICATE----- Cybertrust Global Root ====================== -----BEGIN CERTIFICATE----- MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW WL1WMRJOEcgh4LMRkWXbtKaIOM5V -----END CERTIFICATE----- ePKI Root Certification Authority ================================= -----BEGIN CERTIFICATE----- MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+ ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/ vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw= -----END CERTIFICATE----- T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3 ============================================================================================================================= -----BEGIN CERTIFICATE----- MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4 MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1 xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR 6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4 N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI= -----END CERTIFICATE----- Buypass Class 2 CA 1 ==================== -----BEGIN CERTIFICATE----- MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2 MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83 0r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4 0Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV 1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt 7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2 fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho -----END CERTIFICATE----- Buypass Class 3 CA 1 ==================== -----BEGIN CERTIFICATE----- MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1 MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0 n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c 1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7 pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5 htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 -----END CERTIFICATE----- EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 ========================================================================== -----BEGIN CERTIFICATE----- MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNVBAMML0VCRyBF bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMTcwNQYDVQQKDC5FQkcg QmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXptZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAe Fw0wNjA4MTcwMDIxMDlaFw0xNjA4MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25p ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2lt IFRla25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h4fuXd7hxlugTlkaDT7by X3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAktiHq6yOU/im/+4mRDGSaBUorzAzu8T2b gmmkTPiab+ci2hC6X5L8GCcKqKpE+i4stPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfr eYteIAbTdgtsApWjluTLdlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZ TqNGFav4c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8UmTDGy Y5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z+kI2sSXFCjEmN1Zn uqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0OLna9XvNRiYuoP1Vzv9s6xiQFlpJI qkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMWOeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vm ExH8nYQKE3vwO9D8owrXieqWfo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0 Nokb+Clsi7n2l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB /wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgwFoAU587GT/wW Z5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+8ygjdsZs93/mQJ7ANtyVDR2t FcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgm zJNSroIBk5DKd8pNSe/iWtkqvTDOTLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64k XPBfrAowzIpAoHMEwfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqT bCmYIai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJnxk1Gj7sU RT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4QDgZxGhBM/nV+/x5XOULK 1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9qKd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt 2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11thie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQ Y9iJSrSq3RZj9W6+YKH47ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9 AahH3eU7QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT -----END CERTIFICATE----- certSIGN ROOT CA ================ -----BEGIN CERTIFICATE----- MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD -----END CERTIFICATE----- CNNIC ROOT ========== -----BEGIN CERTIFICATE----- MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5 Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8 BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2 G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m mxE= -----END CERTIFICATE----- ApplicationCA - Japanese Government =================================== -----BEGIN CERTIFICATE----- MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4 fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g /DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL rosot4LKGAfmt1t06SAZf7IbiVQ= -----END CERTIFICATE----- GeoTrust Primary Certification Authority - G3 ============================================= -----BEGIN CERTIFICATE----- MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0 IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr 2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9 cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt -----END CERTIFICATE----- thawte Primary Root CA - G2 =========================== -----BEGIN CERTIFICATE----- MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5 8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== -----END CERTIFICATE----- thawte Primary Root CA - G3 =========================== -----BEGIN CERTIFICATE----- MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC +BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY 7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC 8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A= -----END CERTIFICATE----- GeoTrust Primary Certification Authority - G2 ============================================= -----BEGIN CERTIFICATE----- MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1 OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+ EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2 npaqBA+K -----END CERTIFICATE----- VeriSign Universal Root Certification Authority =============================================== -----BEGIN CERTIFICATE----- MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj 1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72 9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3 Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4 mJO37M2CYfE45k+XmCpajQ== -----END CERTIFICATE----- VeriSign Class 3 Public Primary Certification Authority - G4 ============================================================ -----BEGIN CERTIFICATE----- MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3 b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8 Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB /zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== -----END CERTIFICATE----- NetLock Arany (Class Gold) Fร…โ€˜tanรƒยบsรƒยญtvรƒยกny ============================================ -----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= -----END CERTIFICATE----- Staat der Nederlanden Root CA - G2 ================================== -----BEGIN CERTIFICATE----- MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ 5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65 48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737 qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz +51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm 66+KAQ== -----END CERTIFICATE----- CA Disig ======== -----BEGIN CERTIFICATE----- MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3 mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA 4Z7CRneC9VkGjCFMhwnN5ag= -----END CERTIFICATE----- Juur-SK ======= -----BEGIN CERTIFICATE----- MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglwa2lA c2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMRAw DgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqG SIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVy aW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOBSvZiF3tf TQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkzABpTpyHhOEvWgxutr2TC +Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvHLCu3GFH+4Hv2qEivbDtPL+/40UceJlfw UR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDa Tpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQF MAMBAf8wggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHD HoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABh AHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUA cwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABr AGkAbgBuAGkAdABhAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nw cy8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4G A1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo ERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyL abVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678 IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkh Mp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0ZTbvGRNs2 yyqcjg== -----END CERTIFICATE----- Hongkong Post Root CA 1 ======================= -----BEGIN CERTIFICATE----- MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT c4afU9hDDl3WY4JxHYB0yvbiAmvZWg== -----END CERTIFICATE----- SecureSign RootCA11 =================== -----BEGIN CERTIFICATE----- MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I= -----END CERTIFICATE----- ACEDICOM Root ============= -----BEGIN CERTIFICATE----- MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4 MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2 3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9 2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz 4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU 9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1 ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA== -----END CERTIFICATE----- Verisign Class 1 Public Primary Certification Authority ======================================================= -----BEGIN CERTIFICATE----- MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmltYXJ5 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAx IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA A4GNADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0fzGVuDLDQ VoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHiTkVWaR94AoDa3EeRKbs2 yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFgVKTk8d6Pa XCUDfGD67gmZPCcQcMgMCeazh88K4hiWNWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n 0a3hUKw8fGJLj7qE1xIVGx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZ RjXZ+Hxb -----END CERTIFICATE----- Verisign Class 3 Public Primary Certification Authority ======================================================= -----BEGIN CERTIFICATE----- MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94 f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABByUqkFFBky CEHwxWsKzH4PIRnN5GfcX6kb5sroc50i2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWX bj9T/UWZYB2oK0z5XqcJ2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/ D/xwzoiQ -----END CERTIFICATE----- Microsec e-Szigno Root CA 2009 ============================== -----BEGIN CERTIFICATE----- MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi LXpUq3DDfSJlgnCW -----END CERTIFICATE----- E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi =================================================== -----BEGIN CERTIFICATE----- MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG EwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoGA1UEAxMz ZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3 MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0 cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9u aWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdUMZTe1RK6UxYC6lhj71vY 8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlTL/jDj/6z/P2douNffb7tC+Bg62nsM+3Y jfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAI JjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk 9Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQD AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqG SIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5d F4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwq D2fK/A+JYZ1lpTzlvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4 Vwpm+Vganf2XKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX -----END CERTIFICATE----- GlobalSign Root CA - R3 ======================= -----BEGIN CERTIFICATE----- MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r kpeDMdmztcpHWD9f -----END CERTIFICATE----- TC TrustCenter Universal CA III =============================== -----BEGIN CERTIFICATE----- MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezELMAkGA1UEBhMC REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy IFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAe Fw0wOTA5MDkwODE1MjdaFw0yOTEyMzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNU QyBUcnVzdENlbnRlciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0Ex KDAmBgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF5+cvAqBNLaT6hdqbJYUt QCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYvDIRlzg9uwliT6CwLOunBjvvya8o84pxO juT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8vzArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+Eut CHnNaYlAJ/Uqwa1D7KRTyGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1 M4BDj5yjdipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBhMB8G A1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI4jANBgkqhkiG9w0BAQUFAAOCAQEA g8ev6n9NCjw5sWi+e22JLumzCecYV42FmhfzdkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+ KGwWaODIl0YgoGhnYIg5IFHYaAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhK BgePxLcHsU0GDeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPHLQNjO9Po5KIq woIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg== -----END CERTIFICATE----- Autoridad de Certificacion Firmaprofesional CIF A62634068 ========================================================= -----BEGIN CERTIFICATE----- MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V -----END CERTIFICATE----- Izenpe.com ========== -----BEGIN CERTIFICATE----- MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+ 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+ SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== -----END CERTIFICATE----- Chambers of Commerce Root - 2008 ================================ -----BEGIN CERTIFICATE----- MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/ ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331 lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ 0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2 EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1 wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH 3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6 M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1 YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF 9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ -----END CERTIFICATE----- Global Chambersign Root - 2008 ============================== -----BEGIN CERTIFICATE----- MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0 ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB /gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp 1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0 dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG /5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6 ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg 9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B -----END CERTIFICATE----- Go Daddy Root Certificate Authority - G2 ======================================== -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1 -----END CERTIFICATE----- Starfield Root Certificate Authority - G2 ========================================= -----BEGIN CERTIFICATE----- MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 -----END CERTIFICATE----- Starfield Services Root Certificate Authority - G2 ================================================== -----BEGIN CERTIFICATE----- MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6 -----END CERTIFICATE----- AffirmTrust Commercial ====================== -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= -----END CERTIFICATE----- AffirmTrust Networking ====================== -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= -----END CERTIFICATE----- AffirmTrust Premium =================== -----BEGIN CERTIFICATE----- MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw== -----END CERTIFICATE----- AffirmTrust Premium ECC ======================= -----BEGIN CERTIFICATE----- MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM eQ== -----END CERTIFICATE----- Certum Trusted Network CA ========================= -----BEGIN CERTIFICATE----- MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= -----END CERTIFICATE----- Certinomis - Autoritรƒยฉ Racine ============================= -----BEGIN CERTIFICATE----- MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw 2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g 530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna 4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40 nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/ vgt2Fl43N+bYdJeimUV5 -----END CERTIFICATE----- Root CA Generalitat Valenciana ============================== -----BEGIN CERTIFICATE----- MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0GA1UE ChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290 IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3 WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UE CxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+WmmmO3I2 F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKjSgbwJ/BXufjpTjJ3Cj9B ZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGlu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQ D0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXte JajCq+TA81yc477OMUxkHl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMB AAGjggM7MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5n dmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIB ADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBl AHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIA YQBsAGkAdABhAHQAIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQBy AGEAYwBpAPMAbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBt AGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA YQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBu AHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAA OgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0 dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+yeAT8MIGV BgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQswCQYDVQQGEwJFUzEfMB0G A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5S b290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRh TvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdz Ckj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63 NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OH iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt +GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= -----END CERTIFICATE----- A-Trust-nQual-03 ================ -----BEGIN CERTIFICATE----- MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0 ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1 c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4 iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40 ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6 ahq97BvIxYSazQ== -----END CERTIFICATE----- TWCA Root Certification Authority ================================= -----BEGIN CERTIFICATE----- MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== -----END CERTIFICATE----- Security Communication RootCA2 ============================== -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++ +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 -----END CERTIFICATE----- EC-ACC ====== -----BEGIN CERTIFICATE----- MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D 5EI= -----END CERTIFICATE----- Hellenic Academic and Research Institutions RootCA 2011 ======================================================= -----BEGIN CERTIFICATE----- MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/ MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4 -----END CERTIFICATE----- Actalis Authentication Root CA ============================== -----BEGIN CERTIFICATE----- MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+ Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== -----END CERTIFICATE----- Trustis FPS Root CA =================== -----BEGIN CERTIFICATE----- MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290 IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P 8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl iB6XzCGcKQENZetX2fNXlrtIzYE= -----END CERTIFICATE----- StartCom Certification Authority ================================ -----BEGIN CERTIFICATE----- MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0 NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/ Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/ untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT 37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0 dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0 aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0 aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5 fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA 2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8= -----END CERTIFICATE----- StartCom Certification Authority G2 =================================== -----BEGIN CERTIFICATE----- MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG 4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K 2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+ JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG /+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm 7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm obp573PYtlNXLfbQ4ddI -----END CERTIFICATE----- Buypass Class 2 Root CA ======================= -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN rJgWVqA= -----END CERTIFICATE----- Buypass Class 3 Root CA ======================= -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi Cp/HuZc= -----END CERTIFICATE----- Tรƒล“RKTRUST Elektronik Sertifika Hizmet Saร„ลธlayร„ยฑcร„ยฑsร„ยฑ ====================================================== -----BEGIN CERTIFICATE----- MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK poRq0Tl9 -----END CERTIFICATE----- T-TeleSec GlobalRoot Class 3 ============================ -----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw== -----END CERTIFICATE----- EE Certification Centre Root CA =============================== -----BEGIN CERTIFICATE----- MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2 rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw 93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU 3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM dcGWxZ0= -----END CERTIFICATE----- cakephp-2.8.0/lib/Cake/Config/config.php000066400000000000000000000014211265552240500177340ustar00rootroot00000000000000 $value) { $plugins[$key] = Inflector::underscore($value); } $pluginPattern = implode('|', $plugins); $match = array('plugin' => $pluginPattern, 'defaultRoute' => true); $shortParams = array('routeClass' => 'PluginShortRoute', 'plugin' => $pluginPattern, 'defaultRoute' => true); foreach ($prefixes as $prefix) { $params = array('prefix' => $prefix, $prefix => true); $indexParams = $params + array('action' => 'index'); Router::connect("/{$prefix}/:plugin", $indexParams, $shortParams); Router::connect("/{$prefix}/:plugin/:controller", $indexParams, $match); Router::connect("/{$prefix}/:plugin/:controller/:action/*", $params, $match); } Router::connect('/:plugin', array('action' => 'index'), $shortParams); Router::connect('/:plugin/:controller', array('action' => 'index'), $match); Router::connect('/:plugin/:controller/:action/*', array(), $match); } foreach ($prefixes as $prefix) { $params = array('prefix' => $prefix, $prefix => true); $indexParams = $params + array('action' => 'index'); Router::connect("/{$prefix}/:controller", $indexParams, array('defaultRoute' => true)); Router::connect("/{$prefix}/:controller/:action/*", $params, array('defaultRoute' => true)); } Router::connect('/:controller', array('action' => 'index'), array('defaultRoute' => true)); Router::connect('/:controller/:action/*', array(), array('defaultRoute' => true)); $namedConfig = Router::namedConfig(); if ($namedConfig['rules'] === false) { Router::connectNamed(true); } unset($namedConfig, $params, $indexParams, $prefix, $prefixes, $shortParams, $match, $pluginPattern, $plugins, $key, $value); cakephp-2.8.0/lib/Cake/Config/unicode/000077500000000000000000000000001265552240500174065ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/000077500000000000000000000000001265552240500216645ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/0080_00ff.php000066400000000000000000000136431265552240500236060ustar00rootroot00000000000000 181, 'status' => 'C', 'lower' => array(956)); $config['0080_00ff'][] = array('upper' => 924, 'status' => 'C', 'lower' => array(181)); $config['0080_00ff'][] = array('upper' => 192, 'status' => 'C', 'lower' => array(224)); /* LATIN CAPITAL LETTER A WITH GRAVE */ $config['0080_00ff'][] = array('upper' => 193, 'status' => 'C', 'lower' => array(225)); /* LATIN CAPITAL LETTER A WITH ACUTE */ $config['0080_00ff'][] = array('upper' => 194, 'status' => 'C', 'lower' => array(226)); /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ $config['0080_00ff'][] = array('upper' => 195, 'status' => 'C', 'lower' => array(227)); /* LATIN CAPITAL LETTER A WITH TILDE */ $config['0080_00ff'][] = array('upper' => 196, 'status' => 'C', 'lower' => array(228)); /* LATIN CAPITAL LETTER A WITH DIAERESIS */ $config['0080_00ff'][] = array('upper' => 197, 'status' => 'C', 'lower' => array(229)); /* LATIN CAPITAL LETTER A WITH RING ABOVE */ $config['0080_00ff'][] = array('upper' => 198, 'status' => 'C', 'lower' => array(230)); /* LATIN CAPITAL LETTER AE */ $config['0080_00ff'][] = array('upper' => 199, 'status' => 'C', 'lower' => array(231)); /* LATIN CAPITAL LETTER C WITH CEDILLA */ $config['0080_00ff'][] = array('upper' => 200, 'status' => 'C', 'lower' => array(232)); /* LATIN CAPITAL LETTER E WITH GRAVE */ $config['0080_00ff'][] = array('upper' => 201, 'status' => 'C', 'lower' => array(233)); /* LATIN CAPITAL LETTER E WITH ACUTE */ $config['0080_00ff'][] = array('upper' => 202, 'status' => 'C', 'lower' => array(234)); /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */ $config['0080_00ff'][] = array('upper' => 203, 'status' => 'C', 'lower' => array(235)); /* LATIN CAPITAL LETTER E WITH DIAERESIS */ $config['0080_00ff'][] = array('upper' => 204, 'status' => 'C', 'lower' => array(236)); /* LATIN CAPITAL LETTER I WITH GRAVE */ $config['0080_00ff'][] = array('upper' => 205, 'status' => 'C', 'lower' => array(237)); /* LATIN CAPITAL LETTER I WITH ACUTE */ $config['0080_00ff'][] = array('upper' => 206, 'status' => 'C', 'lower' => array(238)); /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ $config['0080_00ff'][] = array('upper' => 207, 'status' => 'C', 'lower' => array(239)); /* LATIN CAPITAL LETTER I WITH DIAERESIS */ $config['0080_00ff'][] = array('upper' => 208, 'status' => 'C', 'lower' => array(240)); /* LATIN CAPITAL LETTER ETH */ $config['0080_00ff'][] = array('upper' => 209, 'status' => 'C', 'lower' => array(241)); /* LATIN CAPITAL LETTER N WITH TILDE */ $config['0080_00ff'][] = array('upper' => 210, 'status' => 'C', 'lower' => array(242)); /* LATIN CAPITAL LETTER O WITH GRAVE */ $config['0080_00ff'][] = array('upper' => 211, 'status' => 'C', 'lower' => array(243)); /* LATIN CAPITAL LETTER O WITH ACUTE */ $config['0080_00ff'][] = array('upper' => 212, 'status' => 'C', 'lower' => array(244)); /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ $config['0080_00ff'][] = array('upper' => 213, 'status' => 'C', 'lower' => array(245)); /* LATIN CAPITAL LETTER O WITH TILDE */ $config['0080_00ff'][] = array('upper' => 214, 'status' => 'C', 'lower' => array(246)); /* LATIN CAPITAL LETTER O WITH DIAERESIS */ $config['0080_00ff'][] = array('upper' => 216, 'status' => 'C', 'lower' => array(248)); /* LATIN CAPITAL LETTER O WITH STROKE */ $config['0080_00ff'][] = array('upper' => 217, 'status' => 'C', 'lower' => array(249)); /* LATIN CAPITAL LETTER U WITH GRAVE */ $config['0080_00ff'][] = array('upper' => 218, 'status' => 'C', 'lower' => array(250)); /* LATIN CAPITAL LETTER U WITH ACUTE */ $config['0080_00ff'][] = array('upper' => 219, 'status' => 'C', 'lower' => array(251)); /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ $config['0080_00ff'][] = array('upper' => 220, 'status' => 'C', 'lower' => array(252)); /* LATIN CAPITAL LETTER U WITH DIAERESIS */ $config['0080_00ff'][] = array('upper' => 221, 'status' => 'C', 'lower' => array(253)); /* LATIN CAPITAL LETTER Y WITH ACUTE */ $config['0080_00ff'][] = array('upper' => 222, 'status' => 'C', 'lower' => array(254)); /* LATIN CAPITAL LETTER THORN */ $config['0080_00ff'][] = array('upper' => 223, 'status' => 'F', 'lower' => array(115, 115)); /* LATIN SMALL LETTER SHARP S */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/0100_017f.php000066400000000000000000000242771265552240500235260ustar00rootroot00000000000000 256, 'status' => 'C', 'lower' => array(257)); /* LATIN CAPITAL LETTER A WITH MACRON */ $config['0100_017f'][] = array('upper' => 258, 'status' => 'C', 'lower' => array(259)); /* LATIN CAPITAL LETTER A WITH BREVE */ $config['0100_017f'][] = array('upper' => 260, 'status' => 'C', 'lower' => array(261)); /* LATIN CAPITAL LETTER A WITH OGONEK */ $config['0100_017f'][] = array('upper' => 262, 'status' => 'C', 'lower' => array(263)); /* LATIN CAPITAL LETTER C WITH ACUTE */ $config['0100_017f'][] = array('upper' => 264, 'status' => 'C', 'lower' => array(265)); /* LATIN CAPITAL LETTER C WITH CIRCUMFLEX */ $config['0100_017f'][] = array('upper' => 266, 'status' => 'C', 'lower' => array(267)); /* LATIN CAPITAL LETTER C WITH DOT ABOVE */ $config['0100_017f'][] = array('upper' => 268, 'status' => 'C', 'lower' => array(269)); /* LATIN CAPITAL LETTER C WITH CARON */ $config['0100_017f'][] = array('upper' => 270, 'status' => 'C', 'lower' => array(271)); /* LATIN CAPITAL LETTER D WITH CARON */ $config['0100_017f'][] = array('upper' => 272, 'status' => 'C', 'lower' => array(273)); /* LATIN CAPITAL LETTER D WITH STROKE */ $config['0100_017f'][] = array('upper' => 274, 'status' => 'C', 'lower' => array(275)); /* LATIN CAPITAL LETTER E WITH MACRON */ $config['0100_017f'][] = array('upper' => 276, 'status' => 'C', 'lower' => array(277)); /* LATIN CAPITAL LETTER E WITH BREVE */ $config['0100_017f'][] = array('upper' => 278, 'status' => 'C', 'lower' => array(279)); /* LATIN CAPITAL LETTER E WITH DOT ABOVE */ $config['0100_017f'][] = array('upper' => 280, 'status' => 'C', 'lower' => array(281)); /* LATIN CAPITAL LETTER E WITH OGONEK */ $config['0100_017f'][] = array('upper' => 282, 'status' => 'C', 'lower' => array(283)); /* LATIN CAPITAL LETTER E WITH CARON */ $config['0100_017f'][] = array('upper' => 284, 'status' => 'C', 'lower' => array(285)); /* LATIN CAPITAL LETTER G WITH CIRCUMFLEX */ $config['0100_017f'][] = array('upper' => 286, 'status' => 'C', 'lower' => array(287)); /* LATIN CAPITAL LETTER G WITH BREVE */ $config['0100_017f'][] = array('upper' => 288, 'status' => 'C', 'lower' => array(289)); /* LATIN CAPITAL LETTER G WITH DOT ABOVE */ $config['0100_017f'][] = array('upper' => 290, 'status' => 'C', 'lower' => array(291)); /* LATIN CAPITAL LETTER G WITH CEDILLA */ $config['0100_017f'][] = array('upper' => 292, 'status' => 'C', 'lower' => array(293)); /* LATIN CAPITAL LETTER H WITH CIRCUMFLEX */ $config['0100_017f'][] = array('upper' => 294, 'status' => 'C', 'lower' => array(295)); /* LATIN CAPITAL LETTER H WITH STROKE */ $config['0100_017f'][] = array('upper' => 296, 'status' => 'C', 'lower' => array(297)); /* LATIN CAPITAL LETTER I WITH TILDE */ $config['0100_017f'][] = array('upper' => 298, 'status' => 'C', 'lower' => array(299)); /* LATIN CAPITAL LETTER I WITH MACRON */ $config['0100_017f'][] = array('upper' => 300, 'status' => 'C', 'lower' => array(301)); /* LATIN CAPITAL LETTER I WITH BREVE */ $config['0100_017f'][] = array('upper' => 302, 'status' => 'C', 'lower' => array(303)); /* LATIN CAPITAL LETTER I WITH OGONEK */ $config['0100_017f'][] = array('upper' => 304, 'status' => 'F', 'lower' => array(105, 775)); /* LATIN CAPITAL LETTER I WITH DOT ABOVE */ $config['0100_017f'][] = array('upper' => 304, 'status' => 'T', 'lower' => array(105)); /* LATIN CAPITAL LETTER I WITH DOT ABOVE */ $config['0100_017f'][] = array('upper' => 306, 'status' => 'C', 'lower' => array(307)); /* LATIN CAPITAL LIGATURE IJ */ $config['0100_017f'][] = array('upper' => 308, 'status' => 'C', 'lower' => array(309)); /* LATIN CAPITAL LETTER J WITH CIRCUMFLEX */ $config['0100_017f'][] = array('upper' => 310, 'status' => 'C', 'lower' => array(311)); /* LATIN CAPITAL LETTER K WITH CEDILLA */ $config['0100_017f'][] = array('upper' => 313, 'status' => 'C', 'lower' => array(314)); /* LATIN CAPITAL LETTER L WITH ACUTE */ $config['0100_017f'][] = array('upper' => 315, 'status' => 'C', 'lower' => array(316)); /* LATIN CAPITAL LETTER L WITH CEDILLA */ $config['0100_017f'][] = array('upper' => 317, 'status' => 'C', 'lower' => array(318)); /* LATIN CAPITAL LETTER L WITH CARON */ $config['0100_017f'][] = array('upper' => 319, 'status' => 'C', 'lower' => array(320)); /* LATIN CAPITAL LETTER L WITH MIDDLE DOT */ $config['0100_017f'][] = array('upper' => 321, 'status' => 'C', 'lower' => array(322)); /* LATIN CAPITAL LETTER L WITH STROKE */ $config['0100_017f'][] = array('upper' => 323, 'status' => 'C', 'lower' => array(324)); /* LATIN CAPITAL LETTER N WITH ACUTE */ $config['0100_017f'][] = array('upper' => 325, 'status' => 'C', 'lower' => array(326)); /* LATIN CAPITAL LETTER N WITH CEDILLA */ $config['0100_017f'][] = array('upper' => 327, 'status' => 'C', 'lower' => array(328)); /* LATIN CAPITAL LETTER N WITH CARON */ $config['0100_017f'][] = array('upper' => 329, 'status' => 'F', 'lower' => array(700, 110)); /* LATIN SMALL LETTER N PRECEDED BY APOSTROPHE */ $config['0100_017f'][] = array('upper' => 330, 'status' => 'C', 'lower' => array(331)); /* LATIN CAPITAL LETTER ENG */ $config['0100_017f'][] = array('upper' => 332, 'status' => 'C', 'lower' => array(333)); /* LATIN CAPITAL LETTER O WITH MACRON */ $config['0100_017f'][] = array('upper' => 334, 'status' => 'C', 'lower' => array(335)); /* LATIN CAPITAL LETTER O WITH BREVE */ $config['0100_017f'][] = array('upper' => 336, 'status' => 'C', 'lower' => array(337)); /* LATIN CAPITAL LETTER O WITH DOUBLE ACUTE */ $config['0100_017f'][] = array('upper' => 338, 'status' => 'C', 'lower' => array(339)); /* LATIN CAPITAL LIGATURE OE */ $config['0100_017f'][] = array('upper' => 340, 'status' => 'C', 'lower' => array(341)); /* LATIN CAPITAL LETTER R WITH ACUTE */ $config['0100_017f'][] = array('upper' => 342, 'status' => 'C', 'lower' => array(343)); /* LATIN CAPITAL LETTER R WITH CEDILLA */ $config['0100_017f'][] = array('upper' => 344, 'status' => 'C', 'lower' => array(345)); /* LATIN CAPITAL LETTER R WITH CARON */ $config['0100_017f'][] = array('upper' => 346, 'status' => 'C', 'lower' => array(347)); /* LATIN CAPITAL LETTER S WITH ACUTE */ $config['0100_017f'][] = array('upper' => 348, 'status' => 'C', 'lower' => array(349)); /* LATIN CAPITAL LETTER S WITH CIRCUMFLEX */ $config['0100_017f'][] = array('upper' => 350, 'status' => 'C', 'lower' => array(351)); /* LATIN CAPITAL LETTER S WITH CEDILLA */ $config['0100_017f'][] = array('upper' => 352, 'status' => 'C', 'lower' => array(353)); /* LATIN CAPITAL LETTER S WITH CARON */ $config['0100_017f'][] = array('upper' => 354, 'status' => 'C', 'lower' => array(355)); /* LATIN CAPITAL LETTER T WITH CEDILLA */ $config['0100_017f'][] = array('upper' => 356, 'status' => 'C', 'lower' => array(357)); /* LATIN CAPITAL LETTER T WITH CARON */ $config['0100_017f'][] = array('upper' => 358, 'status' => 'C', 'lower' => array(359)); /* LATIN CAPITAL LETTER T WITH STROKE */ $config['0100_017f'][] = array('upper' => 360, 'status' => 'C', 'lower' => array(361)); /* LATIN CAPITAL LETTER U WITH TILDE */ $config['0100_017f'][] = array('upper' => 362, 'status' => 'C', 'lower' => array(363)); /* LATIN CAPITAL LETTER U WITH MACRON */ $config['0100_017f'][] = array('upper' => 364, 'status' => 'C', 'lower' => array(365)); /* LATIN CAPITAL LETTER U WITH BREVE */ $config['0100_017f'][] = array('upper' => 366, 'status' => 'C', 'lower' => array(367)); /* LATIN CAPITAL LETTER U WITH RING ABOVE */ $config['0100_017f'][] = array('upper' => 368, 'status' => 'C', 'lower' => array(369)); /* LATIN CAPITAL LETTER U WITH DOUBLE ACUTE */ $config['0100_017f'][] = array('upper' => 370, 'status' => 'C', 'lower' => array(371)); /* LATIN CAPITAL LETTER U WITH OGONEK */ $config['0100_017f'][] = array('upper' => 372, 'status' => 'C', 'lower' => array(373)); /* LATIN CAPITAL LETTER W WITH CIRCUMFLEX */ $config['0100_017f'][] = array('upper' => 374, 'status' => 'C', 'lower' => array(375)); /* LATIN CAPITAL LETTER Y WITH CIRCUMFLEX */ $config['0100_017f'][] = array('upper' => 376, 'status' => 'C', 'lower' => array(255)); /* LATIN CAPITAL LETTER Y WITH DIAERESIS */ $config['0100_017f'][] = array('upper' => 377, 'status' => 'C', 'lower' => array(378)); /* LATIN CAPITAL LETTER Z WITH ACUTE */ $config['0100_017f'][] = array('upper' => 379, 'status' => 'C', 'lower' => array(380)); /* LATIN CAPITAL LETTER Z WITH DOT ABOVE */ $config['0100_017f'][] = array('upper' => 381, 'status' => 'C', 'lower' => array(382)); /* LATIN CAPITAL LETTER Z WITH CARON */ $config['0100_017f'][] = array('upper' => 383, 'status' => 'C', 'lower' => array(115)); /* LATIN SMALL LETTER LONG S */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/0180_024F.php000066400000000000000000000370571265552240500234740ustar00rootroot00000000000000 385, 'status' => 'C', 'lower' => array(595)); /* LATIN CAPITAL LETTER B WITH HOOK */ $config['0180_024F'][] = array('upper' => 386, 'status' => 'C', 'lower' => array(387)); /* LATIN CAPITAL LETTER B WITH TOPBAR */ $config['0180_024F'][] = array('upper' => 388, 'status' => 'C', 'lower' => array(389)); /* LATIN CAPITAL LETTER TONE SIX */ $config['0180_024F'][] = array('upper' => 390, 'status' => 'C', 'lower' => array(596)); /* LATIN CAPITAL LETTER OPEN O */ $config['0180_024F'][] = array('upper' => 391, 'status' => 'C', 'lower' => array(392)); /* LATIN CAPITAL LETTER C WITH HOOK */ $config['0180_024F'][] = array('upper' => 393, 'status' => 'C', 'lower' => array(598)); /* LATIN CAPITAL LETTER AFRICAN D */ $config['0180_024F'][] = array('upper' => 394, 'status' => 'C', 'lower' => array(599)); /* LATIN CAPITAL LETTER D WITH HOOK */ $config['0180_024F'][] = array('upper' => 395, 'status' => 'C', 'lower' => array(396)); /* LATIN CAPITAL LETTER D WITH TOPBAR */ $config['0180_024F'][] = array('upper' => 398, 'status' => 'C', 'lower' => array(477)); /* LATIN CAPITAL LETTER REVERSED E */ $config['0180_024F'][] = array('upper' => 399, 'status' => 'C', 'lower' => array(601)); /* LATIN CAPITAL LETTER SCHWA */ $config['0180_024F'][] = array('upper' => 400, 'status' => 'C', 'lower' => array(603)); /* LATIN CAPITAL LETTER OPEN E */ $config['0180_024F'][] = array('upper' => 401, 'status' => 'C', 'lower' => array(402)); /* LATIN CAPITAL LETTER F WITH HOOK */ $config['0180_024F'][] = array('upper' => 403, 'status' => 'C', 'lower' => array(608)); /* LATIN CAPITAL LETTER G WITH HOOK */ $config['0180_024F'][] = array('upper' => 404, 'status' => 'C', 'lower' => array(611)); /* LATIN CAPITAL LETTER GAMMA */ $config['0180_024F'][] = array('upper' => 406, 'status' => 'C', 'lower' => array(617)); /* LATIN CAPITAL LETTER IOTA */ $config['0180_024F'][] = array('upper' => 407, 'status' => 'C', 'lower' => array(616)); /* LATIN CAPITAL LETTER I WITH STROKE */ $config['0180_024F'][] = array('upper' => 408, 'status' => 'C', 'lower' => array(409)); /* LATIN CAPITAL LETTER K WITH HOOK */ $config['0180_024F'][] = array('upper' => 412, 'status' => 'C', 'lower' => array(623)); /* LATIN CAPITAL LETTER TURNED M */ $config['0180_024F'][] = array('upper' => 413, 'status' => 'C', 'lower' => array(626)); /* LATIN CAPITAL LETTER N WITH LEFT HOOK */ $config['0180_024F'][] = array('upper' => 415, 'status' => 'C', 'lower' => array(629)); /* LATIN CAPITAL LETTER O WITH MIDDLE TILDE */ $config['0180_024F'][] = array('upper' => 416, 'status' => 'C', 'lower' => array(417)); /* LATIN CAPITAL LETTER O WITH HORN */ $config['0180_024F'][] = array('upper' => 418, 'status' => 'C', 'lower' => array(419)); /* LATIN CAPITAL LETTER OI */ $config['0180_024F'][] = array('upper' => 420, 'status' => 'C', 'lower' => array(421)); /* LATIN CAPITAL LETTER P WITH HOOK */ $config['0180_024F'][] = array('upper' => 422, 'status' => 'C', 'lower' => array(640)); /* LATIN LETTER YR */ $config['0180_024F'][] = array('upper' => 423, 'status' => 'C', 'lower' => array(424)); /* LATIN CAPITAL LETTER TONE TWO */ $config['0180_024F'][] = array('upper' => 425, 'status' => 'C', 'lower' => array(643)); /* LATIN CAPITAL LETTER ESH */ $config['0180_024F'][] = array('upper' => 428, 'status' => 'C', 'lower' => array(429)); /* LATIN CAPITAL LETTER T WITH HOOK */ $config['0180_024F'][] = array('upper' => 430, 'status' => 'C', 'lower' => array(648)); /* LATIN CAPITAL LETTER T WITH RETROFLEX HOOK */ $config['0180_024F'][] = array('upper' => 431, 'status' => 'C', 'lower' => array(432)); /* LATIN CAPITAL LETTER U WITH HORN */ $config['0180_024F'][] = array('upper' => 433, 'status' => 'C', 'lower' => array(650)); /* LATIN CAPITAL LETTER UPSILON */ $config['0180_024F'][] = array('upper' => 434, 'status' => 'C', 'lower' => array(651)); /* LATIN CAPITAL LETTER V WITH HOOK */ $config['0180_024F'][] = array('upper' => 435, 'status' => 'C', 'lower' => array(436)); /* LATIN CAPITAL LETTER Y WITH HOOK */ $config['0180_024F'][] = array('upper' => 437, 'status' => 'C', 'lower' => array(438)); /* LATIN CAPITAL LETTER Z WITH STROKE */ $config['0180_024F'][] = array('upper' => 439, 'status' => 'C', 'lower' => array(658)); /* LATIN CAPITAL LETTER EZH */ $config['0180_024F'][] = array('upper' => 440, 'status' => 'C', 'lower' => array(441)); /* LATIN CAPITAL LETTER EZH REVERSED */ $config['0180_024F'][] = array('upper' => 444, 'status' => 'C', 'lower' => array(445)); /* LATIN CAPITAL LETTER TONE FIVE */ $config['0180_024F'][] = array('upper' => 452, 'status' => 'C', 'lower' => array(454)); /* LATIN CAPITAL LETTER DZ WITH CARON */ $config['0180_024F'][] = array('upper' => 453, 'status' => 'C', 'lower' => array(454)); /* LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON */ $config['0180_024F'][] = array('upper' => 455, 'status' => 'C', 'lower' => array(457)); /* LATIN CAPITAL LETTER LJ */ $config['0180_024F'][] = array('upper' => 456, 'status' => 'C', 'lower' => array(457)); /* LATIN CAPITAL LETTER L WITH SMALL LETTER J */ $config['0180_024F'][] = array('upper' => 458, 'status' => 'C', 'lower' => array(460)); /* LATIN CAPITAL LETTER NJ */ $config['0180_024F'][] = array('upper' => 459, 'status' => 'C', 'lower' => array(460)); /* LATIN CAPITAL LETTER N WITH SMALL LETTER J */ $config['0180_024F'][] = array('upper' => 461, 'status' => 'C', 'lower' => array(462)); /* LATIN CAPITAL LETTER A WITH CARON */ $config['0180_024F'][] = array('upper' => 463, 'status' => 'C', 'lower' => array(464)); /* LATIN CAPITAL LETTER I WITH CARON */ $config['0180_024F'][] = array('upper' => 465, 'status' => 'C', 'lower' => array(466)); /* LATIN CAPITAL LETTER O WITH CARON */ $config['0180_024F'][] = array('upper' => 467, 'status' => 'C', 'lower' => array(468)); /* LATIN CAPITAL LETTER U WITH CARON */ $config['0180_024F'][] = array('upper' => 469, 'status' => 'C', 'lower' => array(470)); /* LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON */ $config['0180_024F'][] = array('upper' => 471, 'status' => 'C', 'lower' => array(472)); /* LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE */ $config['0180_024F'][] = array('upper' => 473, 'status' => 'C', 'lower' => array(474)); /* LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON */ $config['0180_024F'][] = array('upper' => 475, 'status' => 'C', 'lower' => array(476)); /* LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE */ $config['0180_024F'][] = array('upper' => 478, 'status' => 'C', 'lower' => array(479)); /* LATIN CAPITAL LETTER A WITH DIAERESIS AND MACRON */ $config['0180_024F'][] = array('upper' => 480, 'status' => 'C', 'lower' => array(481)); /* LATIN CAPITAL LETTER A WITH DOT ABOVE AND MACRON */ $config['0180_024F'][] = array('upper' => 482, 'status' => 'C', 'lower' => array(483)); /* LATIN CAPITAL LETTER AE WITH MACRON */ $config['0180_024F'][] = array('upper' => 484, 'status' => 'C', 'lower' => array(485)); /* LATIN CAPITAL LETTER G WITH STROKE */ $config['0180_024F'][] = array('upper' => 486, 'status' => 'C', 'lower' => array(487)); /* LATIN CAPITAL LETTER G WITH CARON */ $config['0180_024F'][] = array('upper' => 488, 'status' => 'C', 'lower' => array(489)); /* LATIN CAPITAL LETTER K WITH CARON */ $config['0180_024F'][] = array('upper' => 490, 'status' => 'C', 'lower' => array(491)); /* LATIN CAPITAL LETTER O WITH OGONEK */ $config['0180_024F'][] = array('upper' => 492, 'status' => 'C', 'lower' => array(493)); /* LATIN CAPITAL LETTER O WITH OGONEK AND MACRON */ $config['0180_024F'][] = array('upper' => 494, 'status' => 'C', 'lower' => array(495)); /* LATIN CAPITAL LETTER EZH WITH CARON */ $config['0180_024F'][] = array('upper' => 496, 'status' => 'F', 'lower' => array(106, 780)); /* LATIN SMALL LETTER J WITH CARON */ $config['0180_024F'][] = array('upper' => 497, 'status' => 'C', 'lower' => array(499)); /* LATIN CAPITAL LETTER DZ */ $config['0180_024F'][] = array('upper' => 498, 'status' => 'C', 'lower' => array(499)); /* LATIN CAPITAL LETTER D WITH SMALL LETTER Z */ $config['0180_024F'][] = array('upper' => 500, 'status' => 'C', 'lower' => array(501)); /* LATIN CAPITAL LETTER G WITH ACUTE */ $config['0180_024F'][] = array('upper' => 502, 'status' => 'C', 'lower' => array(405)); /* LATIN CAPITAL LETTER HWAIR */ $config['0180_024F'][] = array('upper' => 503, 'status' => 'C', 'lower' => array(447)); /* LATIN CAPITAL LETTER WYNN */ $config['0180_024F'][] = array('upper' => 504, 'status' => 'C', 'lower' => array(505)); /* LATIN CAPITAL LETTER N WITH GRAVE */ $config['0180_024F'][] = array('upper' => 506, 'status' => 'C', 'lower' => array(507)); /* LATIN CAPITAL LETTER A WITH RING ABOVE AND ACUTE */ $config['0180_024F'][] = array('upper' => 508, 'status' => 'C', 'lower' => array(509)); /* LATIN CAPITAL LETTER AE WITH ACUTE */ $config['0180_024F'][] = array('upper' => 510, 'status' => 'C', 'lower' => array(511)); /* LATIN CAPITAL LETTER O WITH STROKE AND ACUTE */ $config['0180_024F'][] = array('upper' => 512, 'status' => 'C', 'lower' => array(513)); /* LATIN CAPITAL LETTER A WITH DOUBLE GRAVE */ $config['0180_024F'][] = array('upper' => 514, 'status' => 'C', 'lower' => array(515)); /* LATIN CAPITAL LETTER A WITH INVERTED BREVE */ $config['0180_024F'][] = array('upper' => 516, 'status' => 'C', 'lower' => array(517)); /* LATIN CAPITAL LETTER E WITH DOUBLE GRAVE */ $config['0180_024F'][] = array('upper' => 518, 'status' => 'C', 'lower' => array(519)); /* LATIN CAPITAL LETTER E WITH INVERTED BREVE */ $config['0180_024F'][] = array('upper' => 520, 'status' => 'C', 'lower' => array(521)); /* LATIN CAPITAL LETTER I WITH DOUBLE GRAVE */ $config['0180_024F'][] = array('upper' => 522, 'status' => 'C', 'lower' => array(523)); /* LATIN CAPITAL LETTER I WITH INVERTED BREVE */ $config['0180_024F'][] = array('upper' => 524, 'status' => 'C', 'lower' => array(525)); /* LATIN CAPITAL LETTER O WITH DOUBLE GRAVE */ $config['0180_024F'][] = array('upper' => 526, 'status' => 'C', 'lower' => array(527)); /* LATIN CAPITAL LETTER O WITH INVERTED BREVE */ $config['0180_024F'][] = array('upper' => 528, 'status' => 'C', 'lower' => array(529)); /* LATIN CAPITAL LETTER R WITH DOUBLE GRAVE */ $config['0180_024F'][] = array('upper' => 530, 'status' => 'C', 'lower' => array(531)); /* LATIN CAPITAL LETTER R WITH INVERTED BREVE */ $config['0180_024F'][] = array('upper' => 532, 'status' => 'C', 'lower' => array(533)); /* LATIN CAPITAL LETTER U WITH DOUBLE GRAVE */ $config['0180_024F'][] = array('upper' => 534, 'status' => 'C', 'lower' => array(535)); /* LATIN CAPITAL LETTER U WITH INVERTED BREVE */ $config['0180_024F'][] = array('upper' => 536, 'status' => 'C', 'lower' => array(537)); /* LATIN CAPITAL LETTER S WITH COMMA BELOW */ $config['0180_024F'][] = array('upper' => 538, 'status' => 'C', 'lower' => array(539)); /* LATIN CAPITAL LETTER T WITH COMMA BELOW */ $config['0180_024F'][] = array('upper' => 540, 'status' => 'C', 'lower' => array(541)); /* LATIN CAPITAL LETTER YOGH */ $config['0180_024F'][] = array('upper' => 542, 'status' => 'C', 'lower' => array(543)); /* LATIN CAPITAL LETTER H WITH CARON */ $config['0180_024F'][] = array('upper' => 544, 'status' => 'C', 'lower' => array(414)); /* LATIN CAPITAL LETTER N WITH LONG RIGHT LEG */ $config['0180_024F'][] = array('upper' => 546, 'status' => 'C', 'lower' => array(547)); /* LATIN CAPITAL LETTER OU */ $config['0180_024F'][] = array('upper' => 548, 'status' => 'C', 'lower' => array(549)); /* LATIN CAPITAL LETTER Z WITH HOOK */ $config['0180_024F'][] = array('upper' => 550, 'status' => 'C', 'lower' => array(551)); /* LATIN CAPITAL LETTER A WITH DOT ABOVE */ $config['0180_024F'][] = array('upper' => 552, 'status' => 'C', 'lower' => array(553)); /* LATIN CAPITAL LETTER E WITH CEDILLA */ $config['0180_024F'][] = array('upper' => 554, 'status' => 'C', 'lower' => array(555)); /* LATIN CAPITAL LETTER O WITH DIAERESIS AND MACRON */ $config['0180_024F'][] = array('upper' => 556, 'status' => 'C', 'lower' => array(557)); /* LATIN CAPITAL LETTER O WITH TILDE AND MACRON */ $config['0180_024F'][] = array('upper' => 558, 'status' => 'C', 'lower' => array(559)); /* LATIN CAPITAL LETTER O WITH DOT ABOVE */ $config['0180_024F'][] = array('upper' => 560, 'status' => 'C', 'lower' => array(561)); /* LATIN CAPITAL LETTER O WITH DOT ABOVE AND MACRON */ $config['0180_024F'][] = array('upper' => 562, 'status' => 'C', 'lower' => array(563)); /* LATIN CAPITAL LETTER Y WITH MACRON */ $config['0180_024F'][] = array('upper' => 570, 'status' => 'C', 'lower' => array(11365)); /* LATIN CAPITAL LETTER A WITH STROKE */ $config['0180_024F'][] = array('upper' => 571, 'status' => 'C', 'lower' => array(572)); /* LATIN CAPITAL LETTER C WITH STROKE */ $config['0180_024F'][] = array('upper' => 573, 'status' => 'C', 'lower' => array(410)); /* LATIN CAPITAL LETTER L WITH BAR */ $config['0180_024F'][] = array('upper' => 574, 'status' => 'C', 'lower' => array(11366)); /* LATIN CAPITAL LETTER T WITH DIAGONAL STROKE */ $config['0180_024F'][] = array('upper' => 577, 'status' => 'C', 'lower' => array(578)); /* LATIN CAPITAL LETTER GLOTTAL STOP */ $config['0180_024F'][] = array('upper' => 579, 'status' => 'C', 'lower' => array(384)); /* LATIN CAPITAL LETTER B WITH STROKE */ $config['0180_024F'][] = array('upper' => 580, 'status' => 'C', 'lower' => array(649)); /* LATIN CAPITAL LETTER U BAR */ $config['0180_024F'][] = array('upper' => 581, 'status' => 'C', 'lower' => array(652)); /* LATIN CAPITAL LETTER TURNED V */ $config['0180_024F'][] = array('upper' => 582, 'status' => 'C', 'lower' => array(583)); /* LATIN CAPITAL LETTER E WITH STROKE */ $config['0180_024F'][] = array('upper' => 584, 'status' => 'C', 'lower' => array(585)); /* LATIN CAPITAL LETTER J WITH STROKE */ $config['0180_024F'][] = array('upper' => 586, 'status' => 'C', 'lower' => array(587)); /* LATIN CAPITAL LETTER SMALL Q WITH HOOK TAIL */ $config['0180_024F'][] = array('upper' => 588, 'status' => 'C', 'lower' => array(589)); /* LATIN CAPITAL LETTER R WITH STROKE */ $config['0180_024F'][] = array('upper' => 590, 'status' => 'C', 'lower' => array(591)); /* LATIN CAPITAL LETTER Y WITH STROKE */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/0250_02af.php000066400000000000000000000036621265552240500236020ustar00rootroot00000000000000 422, 'status' => 'C', 'lower' => array(640)); cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/0370_03ff.php000066400000000000000000000225051265552240500236100ustar00rootroot00000000000000 902, 'status' => 'C', 'lower' => array(940)); /* GREEK CAPITAL LETTER ALPHA WITH TONOS */ $config['0370_03ff'][] = array('upper' => 904, 'status' => 'C', 'lower' => array(941)); /* GREEK CAPITAL LETTER EPSILON WITH TONOS */ $config['0370_03ff'][] = array('upper' => 905, 'status' => 'C', 'lower' => array(942)); /* GREEK CAPITAL LETTER ETA WITH TONOS */ $config['0370_03ff'][] = array('upper' => 906, 'status' => 'C', 'lower' => array(943)); /* GREEK CAPITAL LETTER IOTA WITH TONOS */ $config['0370_03ff'][] = array('upper' => 908, 'status' => 'C', 'lower' => array(972)); /* GREEK CAPITAL LETTER OMICRON WITH TONOS */ $config['0370_03ff'][] = array('upper' => 910, 'status' => 'C', 'lower' => array(973)); /* GREEK CAPITAL LETTER UPSILON WITH TONOS */ $config['0370_03ff'][] = array('upper' => 911, 'status' => 'C', 'lower' => array(974)); /* GREEK CAPITAL LETTER OMEGA WITH TONOS */ //$config['0370_03ff'][] = array('upper' => 912, 'status' => 'F', 'lower' => array(953, 776, 769)); /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS */ $config['0370_03ff'][] = array('upper' => 913, 'status' => 'C', 'lower' => array(945)); /* GREEK CAPITAL LETTER ALPHA */ $config['0370_03ff'][] = array('upper' => 914, 'status' => 'C', 'lower' => array(946)); /* GREEK CAPITAL LETTER BETA */ $config['0370_03ff'][] = array('upper' => 915, 'status' => 'C', 'lower' => array(947)); /* GREEK CAPITAL LETTER GAMMA */ $config['0370_03ff'][] = array('upper' => 916, 'status' => 'C', 'lower' => array(948)); /* GREEK CAPITAL LETTER DELTA */ $config['0370_03ff'][] = array('upper' => 917, 'status' => 'C', 'lower' => array(949)); /* GREEK CAPITAL LETTER EPSILON */ $config['0370_03ff'][] = array('upper' => 918, 'status' => 'C', 'lower' => array(950)); /* GREEK CAPITAL LETTER ZETA */ $config['0370_03ff'][] = array('upper' => 919, 'status' => 'C', 'lower' => array(951)); /* GREEK CAPITAL LETTER ETA */ $config['0370_03ff'][] = array('upper' => 920, 'status' => 'C', 'lower' => array(952)); /* GREEK CAPITAL LETTER THETA */ $config['0370_03ff'][] = array('upper' => 921, 'status' => 'C', 'lower' => array(953)); /* GREEK CAPITAL LETTER IOTA */ $config['0370_03ff'][] = array('upper' => 922, 'status' => 'C', 'lower' => array(954)); /* GREEK CAPITAL LETTER KAPPA */ $config['0370_03ff'][] = array('upper' => 923, 'status' => 'C', 'lower' => array(955)); /* GREEK CAPITAL LETTER LAMDA */ $config['0370_03ff'][] = array('upper' => 924, 'status' => 'C', 'lower' => array(956)); /* GREEK CAPITAL LETTER MU */ $config['0370_03ff'][] = array('upper' => 925, 'status' => 'C', 'lower' => array(957)); /* GREEK CAPITAL LETTER NU */ $config['0370_03ff'][] = array('upper' => 926, 'status' => 'C', 'lower' => array(958)); /* GREEK CAPITAL LETTER XI */ $config['0370_03ff'][] = array('upper' => 927, 'status' => 'C', 'lower' => array(959)); /* GREEK CAPITAL LETTER OMICRON */ $config['0370_03ff'][] = array('upper' => 928, 'status' => 'C', 'lower' => array(960)); /* GREEK CAPITAL LETTER PI */ $config['0370_03ff'][] = array('upper' => 929, 'status' => 'C', 'lower' => array(961)); /* GREEK CAPITAL LETTER RHO */ $config['0370_03ff'][] = array('upper' => 931, 'status' => 'C', 'lower' => array(963)); /* GREEK CAPITAL LETTER SIGMA */ $config['0370_03ff'][] = array('upper' => 932, 'status' => 'C', 'lower' => array(964)); /* GREEK CAPITAL LETTER TAU */ $config['0370_03ff'][] = array('upper' => 933, 'status' => 'C', 'lower' => array(965)); /* GREEK CAPITAL LETTER UPSILON */ $config['0370_03ff'][] = array('upper' => 934, 'status' => 'C', 'lower' => array(966)); /* GREEK CAPITAL LETTER PHI */ $config['0370_03ff'][] = array('upper' => 935, 'status' => 'C', 'lower' => array(967)); /* GREEK CAPITAL LETTER CHI */ $config['0370_03ff'][] = array('upper' => 936, 'status' => 'C', 'lower' => array(968)); /* GREEK CAPITAL LETTER PSI */ $config['0370_03ff'][] = array('upper' => 937, 'status' => 'C', 'lower' => array(969)); /* GREEK CAPITAL LETTER OMEGA */ $config['0370_03ff'][] = array('upper' => 938, 'status' => 'C', 'lower' => array(970)); /* GREEK CAPITAL LETTER IOTA WITH DIALYTIKA */ $config['0370_03ff'][] = array('upper' => 939, 'status' => 'C', 'lower' => array(971)); /* GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA */ $config['0370_03ff'][] = array('upper' => 944, 'status' => 'F', 'lower' => array(965, 776, 769)); /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS */ $config['0370_03ff'][] = array('upper' => 962, 'status' => 'C', 'lower' => array(963)); /* GREEK SMALL LETTER FINAL SIGMA */ $config['0370_03ff'][] = array('upper' => 976, 'status' => 'C', 'lower' => array(946)); /* GREEK BETA SYMBOL */ $config['0370_03ff'][] = array('upper' => 977, 'status' => 'C', 'lower' => array(952)); /* GREEK THETA SYMBOL */ $config['0370_03ff'][] = array('upper' => 981, 'status' => 'C', 'lower' => array(966)); /* GREEK PHI SYMBOL */ $config['0370_03ff'][] = array('upper' => 982, 'status' => 'C', 'lower' => array(960)); /* GREEK PI SYMBOL */ $config['0370_03ff'][] = array('upper' => 984, 'status' => 'C', 'lower' => array(985)); /* GREEK LETTER ARCHAIC KOPPA */ $config['0370_03ff'][] = array('upper' => 986, 'status' => 'C', 'lower' => array(987)); /* GREEK LETTER STIGMA */ $config['0370_03ff'][] = array('upper' => 988, 'status' => 'C', 'lower' => array(989)); /* GREEK LETTER DIGAMMA */ $config['0370_03ff'][] = array('upper' => 990, 'status' => 'C', 'lower' => array(991)); /* GREEK LETTER KOPPA */ $config['0370_03ff'][] = array('upper' => 992, 'status' => 'C', 'lower' => array(993)); /* GREEK LETTER SAMPI */ $config['0370_03ff'][] = array('upper' => 994, 'status' => 'C', 'lower' => array(995)); /* COPTIC CAPITAL LETTER SHEI */ $config['0370_03ff'][] = array('upper' => 996, 'status' => 'C', 'lower' => array(997)); /* COPTIC CAPITAL LETTER FEI */ $config['0370_03ff'][] = array('upper' => 998, 'status' => 'C', 'lower' => array(999)); /* COPTIC CAPITAL LETTER KHEI */ $config['0370_03ff'][] = array('upper' => 1000, 'status' => 'C', 'lower' => array(1001)); /* COPTIC CAPITAL LETTER HORI */ $config['0370_03ff'][] = array('upper' => 1002, 'status' => 'C', 'lower' => array(1003)); /* COPTIC CAPITAL LETTER GANGIA */ $config['0370_03ff'][] = array('upper' => 1004, 'status' => 'C', 'lower' => array(1005)); /* COPTIC CAPITAL LETTER SHIMA */ $config['0370_03ff'][] = array('upper' => 1006, 'status' => 'C', 'lower' => array(1007)); /* COPTIC CAPITAL LETTER DEI */ $config['0370_03ff'][] = array('upper' => 1008, 'status' => 'C', 'lower' => array(954)); /* GREEK KAPPA SYMBOL */ $config['0370_03ff'][] = array('upper' => 1009, 'status' => 'C', 'lower' => array(961)); /* GREEK RHO SYMBOL */ $config['0370_03ff'][] = array('upper' => 1012, 'status' => 'C', 'lower' => array(952)); /* GREEK CAPITAL THETA SYMBOL */ $config['0370_03ff'][] = array('upper' => 1013, 'status' => 'C', 'lower' => array(949)); /* GREEK LUNATE EPSILON SYMBOL */ $config['0370_03ff'][] = array('upper' => 1015, 'status' => 'C', 'lower' => array(1016)); /* GREEK CAPITAL LETTER SHO */ $config['0370_03ff'][] = array('upper' => 1017, 'status' => 'C', 'lower' => array(1010)); /* GREEK CAPITAL LUNATE SIGMA SYMBOL */ $config['0370_03ff'][] = array('upper' => 1018, 'status' => 'C', 'lower' => array(1019)); /* GREEK CAPITAL LETTER SAN */ $config['0370_03ff'][] = array('upper' => 1021, 'status' => 'C', 'lower' => array(891)); /* GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL */ $config['0370_03ff'][] = array('upper' => 1022, 'status' => 'C', 'lower' => array(892)); /* GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL */ $config['0370_03ff'][] = array('upper' => 1023, 'status' => 'C', 'lower' => array(893)); /* GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/0400_04ff.php000066400000000000000000000432731265552240500236100ustar00rootroot00000000000000 1024, 'status' => 'C', 'lower' => array(1104)); /* CYRILLIC CAPITAL LETTER IE WITH GRAVE */ $config['0400_04ff'][] = array('upper' => 1025, 'status' => 'C', 'lower' => array(1105)); /* CYRILLIC CAPITAL LETTER IO */ $config['0400_04ff'][] = array('upper' => 1026, 'status' => 'C', 'lower' => array(1106)); /* CYRILLIC CAPITAL LETTER DJE */ $config['0400_04ff'][] = array('upper' => 1027, 'status' => 'C', 'lower' => array(1107)); /* CYRILLIC CAPITAL LETTER GJE */ $config['0400_04ff'][] = array('upper' => 1028, 'status' => 'C', 'lower' => array(1108)); /* CYRILLIC CAPITAL LETTER UKRAINIAN IE */ $config['0400_04ff'][] = array('upper' => 1029, 'status' => 'C', 'lower' => array(1109)); /* CYRILLIC CAPITAL LETTER DZE */ $config['0400_04ff'][] = array('upper' => 1030, 'status' => 'C', 'lower' => array(1110)); /* CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I */ $config['0400_04ff'][] = array('upper' => 1031, 'status' => 'C', 'lower' => array(1111)); /* CYRILLIC CAPITAL LETTER YI */ $config['0400_04ff'][] = array('upper' => 1032, 'status' => 'C', 'lower' => array(1112)); /* CYRILLIC CAPITAL LETTER JE */ $config['0400_04ff'][] = array('upper' => 1033, 'status' => 'C', 'lower' => array(1113)); /* CYRILLIC CAPITAL LETTER LJE */ $config['0400_04ff'][] = array('upper' => 1034, 'status' => 'C', 'lower' => array(1114)); /* CYRILLIC CAPITAL LETTER NJE */ $config['0400_04ff'][] = array('upper' => 1035, 'status' => 'C', 'lower' => array(1115)); /* CYRILLIC CAPITAL LETTER TSHE */ $config['0400_04ff'][] = array('upper' => 1036, 'status' => 'C', 'lower' => array(1116)); /* CYRILLIC CAPITAL LETTER KJE */ $config['0400_04ff'][] = array('upper' => 1037, 'status' => 'C', 'lower' => array(1117)); /* CYRILLIC CAPITAL LETTER I WITH GRAVE */ $config['0400_04ff'][] = array('upper' => 1038, 'status' => 'C', 'lower' => array(1118)); /* CYRILLIC CAPITAL LETTER SHORT U */ $config['0400_04ff'][] = array('upper' => 1039, 'status' => 'C', 'lower' => array(1119)); /* CYRILLIC CAPITAL LETTER DZHE */ $config['0400_04ff'][] = array('upper' => 1040, 'status' => 'C', 'lower' => array(1072)); /* CYRILLIC CAPITAL LETTER A */ $config['0400_04ff'][] = array('upper' => 1041, 'status' => 'C', 'lower' => array(1073)); /* CYRILLIC CAPITAL LETTER BE */ $config['0400_04ff'][] = array('upper' => 1042, 'status' => 'C', 'lower' => array(1074)); /* CYRILLIC CAPITAL LETTER VE */ $config['0400_04ff'][] = array('upper' => 1043, 'status' => 'C', 'lower' => array(1075)); /* CYRILLIC CAPITAL LETTER GHE */ $config['0400_04ff'][] = array('upper' => 1044, 'status' => 'C', 'lower' => array(1076)); /* CYRILLIC CAPITAL LETTER DE */ $config['0400_04ff'][] = array('upper' => 1045, 'status' => 'C', 'lower' => array(1077)); /* CYRILLIC CAPITAL LETTER IE */ $config['0400_04ff'][] = array('upper' => 1046, 'status' => 'C', 'lower' => array(1078)); /* CYRILLIC CAPITAL LETTER ZHE */ $config['0400_04ff'][] = array('upper' => 1047, 'status' => 'C', 'lower' => array(1079)); /* CYRILLIC CAPITAL LETTER ZE */ $config['0400_04ff'][] = array('upper' => 1048, 'status' => 'C', 'lower' => array(1080)); /* CYRILLIC CAPITAL LETTER I */ $config['0400_04ff'][] = array('upper' => 1049, 'status' => 'C', 'lower' => array(1081)); /* CYRILLIC CAPITAL LETTER SHORT I */ $config['0400_04ff'][] = array('upper' => 1050, 'status' => 'C', 'lower' => array(1082)); /* CYRILLIC CAPITAL LETTER KA */ $config['0400_04ff'][] = array('upper' => 1051, 'status' => 'C', 'lower' => array(1083)); /* CYRILLIC CAPITAL LETTER EL */ $config['0400_04ff'][] = array('upper' => 1052, 'status' => 'C', 'lower' => array(1084)); /* CYRILLIC CAPITAL LETTER EM */ $config['0400_04ff'][] = array('upper' => 1053, 'status' => 'C', 'lower' => array(1085)); /* CYRILLIC CAPITAL LETTER EN */ $config['0400_04ff'][] = array('upper' => 1054, 'status' => 'C', 'lower' => array(1086)); /* CYRILLIC CAPITAL LETTER O */ $config['0400_04ff'][] = array('upper' => 1055, 'status' => 'C', 'lower' => array(1087)); /* CYRILLIC CAPITAL LETTER PE */ $config['0400_04ff'][] = array('upper' => 1056, 'status' => 'C', 'lower' => array(1088)); /* CYRILLIC CAPITAL LETTER ER */ $config['0400_04ff'][] = array('upper' => 1057, 'status' => 'C', 'lower' => array(1089)); /* CYRILLIC CAPITAL LETTER ES */ $config['0400_04ff'][] = array('upper' => 1058, 'status' => 'C', 'lower' => array(1090)); /* CYRILLIC CAPITAL LETTER TE */ $config['0400_04ff'][] = array('upper' => 1059, 'status' => 'C', 'lower' => array(1091)); /* CYRILLIC CAPITAL LETTER U */ $config['0400_04ff'][] = array('upper' => 1060, 'status' => 'C', 'lower' => array(1092)); /* CYRILLIC CAPITAL LETTER EF */ $config['0400_04ff'][] = array('upper' => 1061, 'status' => 'C', 'lower' => array(1093)); /* CYRILLIC CAPITAL LETTER HA */ $config['0400_04ff'][] = array('upper' => 1062, 'status' => 'C', 'lower' => array(1094)); /* CYRILLIC CAPITAL LETTER TSE */ $config['0400_04ff'][] = array('upper' => 1063, 'status' => 'C', 'lower' => array(1095)); /* CYRILLIC CAPITAL LETTER CHE */ $config['0400_04ff'][] = array('upper' => 1064, 'status' => 'C', 'lower' => array(1096)); /* CYRILLIC CAPITAL LETTER SHA */ $config['0400_04ff'][] = array('upper' => 1065, 'status' => 'C', 'lower' => array(1097)); /* CYRILLIC CAPITAL LETTER SHCHA */ $config['0400_04ff'][] = array('upper' => 1066, 'status' => 'C', 'lower' => array(1098)); /* CYRILLIC CAPITAL LETTER HARD SIGN */ $config['0400_04ff'][] = array('upper' => 1067, 'status' => 'C', 'lower' => array(1099)); /* CYRILLIC CAPITAL LETTER YERU */ $config['0400_04ff'][] = array('upper' => 1068, 'status' => 'C', 'lower' => array(1100)); /* CYRILLIC CAPITAL LETTER SOFT SIGN */ $config['0400_04ff'][] = array('upper' => 1069, 'status' => 'C', 'lower' => array(1101)); /* CYRILLIC CAPITAL LETTER E */ $config['0400_04ff'][] = array('upper' => 1070, 'status' => 'C', 'lower' => array(1102)); /* CYRILLIC CAPITAL LETTER YU */ $config['0400_04ff'][] = array('upper' => 1071, 'status' => 'C', 'lower' => array(1103)); /* CYRILLIC CAPITAL LETTER YA */ $config['0400_04ff'][] = array('upper' => 1120, 'status' => 'C', 'lower' => array(1121)); /* CYRILLIC CAPITAL LETTER OMEGA */ $config['0400_04ff'][] = array('upper' => 1122, 'status' => 'C', 'lower' => array(1123)); /* CYRILLIC CAPITAL LETTER YAT */ $config['0400_04ff'][] = array('upper' => 1124, 'status' => 'C', 'lower' => array(1125)); /* CYRILLIC CAPITAL LETTER IOTIFIED E */ $config['0400_04ff'][] = array('upper' => 1126, 'status' => 'C', 'lower' => array(1127)); /* CYRILLIC CAPITAL LETTER LITTLE YUS */ $config['0400_04ff'][] = array('upper' => 1128, 'status' => 'C', 'lower' => array(1129)); /* CYRILLIC CAPITAL LETTER IOTIFIED LITTLE YUS */ $config['0400_04ff'][] = array('upper' => 1130, 'status' => 'C', 'lower' => array(1131)); /* CYRILLIC CAPITAL LETTER BIG YUS */ $config['0400_04ff'][] = array('upper' => 1132, 'status' => 'C', 'lower' => array(1133)); /* CYRILLIC CAPITAL LETTER IOTIFIED BIG YUS */ $config['0400_04ff'][] = array('upper' => 1134, 'status' => 'C', 'lower' => array(1135)); /* CYRILLIC CAPITAL LETTER KSI */ $config['0400_04ff'][] = array('upper' => 1136, 'status' => 'C', 'lower' => array(1137)); /* CYRILLIC CAPITAL LETTER PSI */ $config['0400_04ff'][] = array('upper' => 1138, 'status' => 'C', 'lower' => array(1139)); /* CYRILLIC CAPITAL LETTER FITA */ $config['0400_04ff'][] = array('upper' => 1140, 'status' => 'C', 'lower' => array(1141)); /* CYRILLIC CAPITAL LETTER IZHITSA */ $config['0400_04ff'][] = array('upper' => 1142, 'status' => 'C', 'lower' => array(1143)); /* CYRILLIC CAPITAL LETTER IZHITSA WITH DOUBLE GRAVE ACCENT */ $config['0400_04ff'][] = array('upper' => 1144, 'status' => 'C', 'lower' => array(1145)); /* CYRILLIC CAPITAL LETTER UK */ $config['0400_04ff'][] = array('upper' => 1146, 'status' => 'C', 'lower' => array(1147)); /* CYRILLIC CAPITAL LETTER ROUND OMEGA */ $config['0400_04ff'][] = array('upper' => 1148, 'status' => 'C', 'lower' => array(1149)); /* CYRILLIC CAPITAL LETTER OMEGA WITH TITLO */ $config['0400_04ff'][] = array('upper' => 1150, 'status' => 'C', 'lower' => array(1151)); /* CYRILLIC CAPITAL LETTER OT */ $config['0400_04ff'][] = array('upper' => 1152, 'status' => 'C', 'lower' => array(1153)); /* CYRILLIC CAPITAL LETTER KOPPA */ $config['0400_04ff'][] = array('upper' => 1162, 'status' => 'C', 'lower' => array(1163)); /* CYRILLIC CAPITAL LETTER SHORT I WITH TAIL */ $config['0400_04ff'][] = array('upper' => 1164, 'status' => 'C', 'lower' => array(1165)); /* CYRILLIC CAPITAL LETTER SEMISOFT SIGN */ $config['0400_04ff'][] = array('upper' => 1166, 'status' => 'C', 'lower' => array(1167)); /* CYRILLIC CAPITAL LETTER ER WITH TICK */ $config['0400_04ff'][] = array('upper' => 1168, 'status' => 'C', 'lower' => array(1169)); /* CYRILLIC CAPITAL LETTER GHE WITH UPTURN */ $config['0400_04ff'][] = array('upper' => 1170, 'status' => 'C', 'lower' => array(1171)); /* CYRILLIC CAPITAL LETTER GHE WITH STROKE */ $config['0400_04ff'][] = array('upper' => 1172, 'status' => 'C', 'lower' => array(1173)); /* CYRILLIC CAPITAL LETTER GHE WITH MIDDLE HOOK */ $config['0400_04ff'][] = array('upper' => 1174, 'status' => 'C', 'lower' => array(1175)); /* CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER */ $config['0400_04ff'][] = array('upper' => 1176, 'status' => 'C', 'lower' => array(1177)); /* CYRILLIC CAPITAL LETTER ZE WITH DESCENDER */ $config['0400_04ff'][] = array('upper' => 1178, 'status' => 'C', 'lower' => array(1179)); /* CYRILLIC CAPITAL LETTER KA WITH DESCENDER */ $config['0400_04ff'][] = array('upper' => 1180, 'status' => 'C', 'lower' => array(1181)); /* CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE */ $config['0400_04ff'][] = array('upper' => 1182, 'status' => 'C', 'lower' => array(1183)); /* CYRILLIC CAPITAL LETTER KA WITH STROKE */ $config['0400_04ff'][] = array('upper' => 1184, 'status' => 'C', 'lower' => array(1185)); /* CYRILLIC CAPITAL LETTER BASHKIR KA */ $config['0400_04ff'][] = array('upper' => 1186, 'status' => 'C', 'lower' => array(1187)); /* CYRILLIC CAPITAL LETTER EN WITH DESCENDER */ $config['0400_04ff'][] = array('upper' => 1188, 'status' => 'C', 'lower' => array(1189)); /* CYRILLIC CAPITAL LIGATURE EN GHE */ $config['0400_04ff'][] = array('upper' => 1190, 'status' => 'C', 'lower' => array(1191)); /* CYRILLIC CAPITAL LETTER PE WITH MIDDLE HOOK */ $config['0400_04ff'][] = array('upper' => 1192, 'status' => 'C', 'lower' => array(1193)); /* CYRILLIC CAPITAL LETTER ABKHASIAN HA */ $config['0400_04ff'][] = array('upper' => 1194, 'status' => 'C', 'lower' => array(1195)); /* CYRILLIC CAPITAL LETTER ES WITH DESCENDER */ $config['0400_04ff'][] = array('upper' => 1196, 'status' => 'C', 'lower' => array(1197)); /* CYRILLIC CAPITAL LETTER TE WITH DESCENDER */ $config['0400_04ff'][] = array('upper' => 1198, 'status' => 'C', 'lower' => array(1199)); /* CYRILLIC CAPITAL LETTER STRAIGHT U */ $config['0400_04ff'][] = array('upper' => 1200, 'status' => 'C', 'lower' => array(1201)); /* CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE */ $config['0400_04ff'][] = array('upper' => 1202, 'status' => 'C', 'lower' => array(1203)); /* CYRILLIC CAPITAL LETTER HA WITH DESCENDER */ $config['0400_04ff'][] = array('upper' => 1204, 'status' => 'C', 'lower' => array(1205)); /* CYRILLIC CAPITAL LIGATURE TE TSE */ $config['0400_04ff'][] = array('upper' => 1206, 'status' => 'C', 'lower' => array(1207)); /* CYRILLIC CAPITAL LETTER CHE WITH DESCENDER */ $config['0400_04ff'][] = array('upper' => 1208, 'status' => 'C', 'lower' => array(1209)); /* CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE */ $config['0400_04ff'][] = array('upper' => 1210, 'status' => 'C', 'lower' => array(1211)); /* CYRILLIC CAPITAL LETTER SHHA */ $config['0400_04ff'][] = array('upper' => 1212, 'status' => 'C', 'lower' => array(1213)); /* CYRILLIC CAPITAL LETTER ABKHASIAN CHE */ $config['0400_04ff'][] = array('upper' => 1214, 'status' => 'C', 'lower' => array(1215)); /* CYRILLIC CAPITAL LETTER ABKHASIAN CHE WITH DESCENDER */ $config['0400_04ff'][] = array('upper' => 1216, 'status' => 'C', 'lower' => array(1231)); /* CYRILLIC LETTER PALOCHKA */ $config['0400_04ff'][] = array('upper' => 1217, 'status' => 'C', 'lower' => array(1218)); /* CYRILLIC CAPITAL LETTER ZHE WITH BREVE */ $config['0400_04ff'][] = array('upper' => 1219, 'status' => 'C', 'lower' => array(1220)); /* CYRILLIC CAPITAL LETTER KA WITH HOOK */ $config['0400_04ff'][] = array('upper' => 1221, 'status' => 'C', 'lower' => array(1222)); /* CYRILLIC CAPITAL LETTER EL WITH TAIL */ $config['0400_04ff'][] = array('upper' => 1223, 'status' => 'C', 'lower' => array(1224)); /* CYRILLIC CAPITAL LETTER EN WITH HOOK */ $config['0400_04ff'][] = array('upper' => 1225, 'status' => 'C', 'lower' => array(1226)); /* CYRILLIC CAPITAL LETTER EN WITH TAIL */ $config['0400_04ff'][] = array('upper' => 1227, 'status' => 'C', 'lower' => array(1228)); /* CYRILLIC CAPITAL LETTER KHAKASSIAN CHE */ $config['0400_04ff'][] = array('upper' => 1229, 'status' => 'C', 'lower' => array(1230)); /* CYRILLIC CAPITAL LETTER EM WITH TAIL */ $config['0400_04ff'][] = array('upper' => 1232, 'status' => 'C', 'lower' => array(1233)); /* CYRILLIC CAPITAL LETTER A WITH BREVE */ $config['0400_04ff'][] = array('upper' => 1234, 'status' => 'C', 'lower' => array(1235)); /* CYRILLIC CAPITAL LETTER A WITH DIAERESIS */ $config['0400_04ff'][] = array('upper' => 1236, 'status' => 'C', 'lower' => array(1237)); /* CYRILLIC CAPITAL LIGATURE A IE */ $config['0400_04ff'][] = array('upper' => 1238, 'status' => 'C', 'lower' => array(1239)); /* CYRILLIC CAPITAL LETTER IE WITH BREVE */ $config['0400_04ff'][] = array('upper' => 1240, 'status' => 'C', 'lower' => array(1241)); /* CYRILLIC CAPITAL LETTER SCHWA */ $config['0400_04ff'][] = array('upper' => 1242, 'status' => 'C', 'lower' => array(1243)); /* CYRILLIC CAPITAL LETTER SCHWA WITH DIAERESIS */ $config['0400_04ff'][] = array('upper' => 1244, 'status' => 'C', 'lower' => array(1245)); /* CYRILLIC CAPITAL LETTER ZHE WITH DIAERESIS */ $config['0400_04ff'][] = array('upper' => 1246, 'status' => 'C', 'lower' => array(1247)); /* CYRILLIC CAPITAL LETTER ZE WITH DIAERESIS */ $config['0400_04ff'][] = array('upper' => 1248, 'status' => 'C', 'lower' => array(1249)); /* CYRILLIC CAPITAL LETTER ABKHASIAN DZE */ $config['0400_04ff'][] = array('upper' => 1250, 'status' => 'C', 'lower' => array(1251)); /* CYRILLIC CAPITAL LETTER I WITH MACRON */ $config['0400_04ff'][] = array('upper' => 1252, 'status' => 'C', 'lower' => array(1253)); /* CYRILLIC CAPITAL LETTER I WITH DIAERESIS */ $config['0400_04ff'][] = array('upper' => 1254, 'status' => 'C', 'lower' => array(1255)); /* CYRILLIC CAPITAL LETTER O WITH DIAERESIS */ $config['0400_04ff'][] = array('upper' => 1256, 'status' => 'C', 'lower' => array(1257)); /* CYRILLIC CAPITAL LETTER BARRED O */ $config['0400_04ff'][] = array('upper' => 1258, 'status' => 'C', 'lower' => array(1259)); /* CYRILLIC CAPITAL LETTER BARRED O WITH DIAERESIS */ $config['0400_04ff'][] = array('upper' => 1260, 'status' => 'C', 'lower' => array(1261)); /* CYRILLIC CAPITAL LETTER E WITH DIAERESIS */ $config['0400_04ff'][] = array('upper' => 1262, 'status' => 'C', 'lower' => array(1263)); /* CYRILLIC CAPITAL LETTER U WITH MACRON */ $config['0400_04ff'][] = array('upper' => 1264, 'status' => 'C', 'lower' => array(1265)); /* CYRILLIC CAPITAL LETTER U WITH DIAERESIS */ $config['0400_04ff'][] = array('upper' => 1266, 'status' => 'C', 'lower' => array(1267)); /* CYRILLIC CAPITAL LETTER U WITH DOUBLE ACUTE */ $config['0400_04ff'][] = array('upper' => 1268, 'status' => 'C', 'lower' => array(1269)); /* CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS */ $config['0400_04ff'][] = array('upper' => 1270, 'status' => 'C', 'lower' => array(1271)); /* CYRILLIC CAPITAL LETTER GHE WITH DESCENDER */ $config['0400_04ff'][] = array('upper' => 1272, 'status' => 'C', 'lower' => array(1273)); /* CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS */ $config['0400_04ff'][] = array('upper' => 1274, 'status' => 'C', 'lower' => array(1275)); /* CYRILLIC CAPITAL LETTER GHE WITH STROKE AND HOOK */ $config['0400_04ff'][] = array('upper' => 1276, 'status' => 'C', 'lower' => array(1277)); /* CYRILLIC CAPITAL LETTER HA WITH HOOK */ $config['0400_04ff'][] = array('upper' => 1278, 'status' => 'C', 'lower' => array(1279)); /* CYRILLIC CAPITAL LETTER HA WITH STROKE */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/0500_052f.php000066400000000000000000000061421265552240500235200ustar00rootroot00000000000000 1280, 'status' => 'C', 'lower' => array(1281)); /* CYRILLIC CAPITAL LETTER KOMI DE */ $config['0500_052f'][] = array('upper' => 1282, 'status' => 'C', 'lower' => array(1283)); /* CYRILLIC CAPITAL LETTER KOMI DJE */ $config['0500_052f'][] = array('upper' => 1284, 'status' => 'C', 'lower' => array(1285)); /* CYRILLIC CAPITAL LETTER KOMI ZJE */ $config['0500_052f'][] = array('upper' => 1286, 'status' => 'C', 'lower' => array(1287)); /* CYRILLIC CAPITAL LETTER KOMI DZJE */ $config['0500_052f'][] = array('upper' => 1288, 'status' => 'C', 'lower' => array(1289)); /* CYRILLIC CAPITAL LETTER KOMI LJE */ $config['0500_052f'][] = array('upper' => 1290, 'status' => 'C', 'lower' => array(1291)); /* CYRILLIC CAPITAL LETTER KOMI NJE */ $config['0500_052f'][] = array('upper' => 1292, 'status' => 'C', 'lower' => array(1293)); /* CYRILLIC CAPITAL LETTER KOMI SJE */ $config['0500_052f'][] = array('upper' => 1294, 'status' => 'C', 'lower' => array(1295)); /* CYRILLIC CAPITAL LETTER KOMI TJE */ $config['0500_052f'][] = array('upper' => 1296, 'status' => 'C', 'lower' => array(1297)); /* CYRILLIC CAPITAL LETTER ZE */ $config['0500_052f'][] = array('upper' => 1298, 'status' => 'C', 'lower' => array(1299)); /* CYRILLIC CAPITAL LETTER El with hook */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/0530_058f.php000066400000000000000000000146741265552240500235420ustar00rootroot00000000000000 1329, 'status' => 'C', 'lower' => array(1377)); /* ARMENIAN CAPITAL LETTER AYB */ $config['0530_058f'][] = array('upper' => 1330, 'status' => 'C', 'lower' => array(1378)); /* ARMENIAN CAPITAL LETTER BEN */ $config['0530_058f'][] = array('upper' => 1331, 'status' => 'C', 'lower' => array(1379)); /* ARMENIAN CAPITAL LETTER GIM */ $config['0530_058f'][] = array('upper' => 1332, 'status' => 'C', 'lower' => array(1380)); /* ARMENIAN CAPITAL LETTER DA */ $config['0530_058f'][] = array('upper' => 1333, 'status' => 'C', 'lower' => array(1381)); /* ARMENIAN CAPITAL LETTER ECH */ $config['0530_058f'][] = array('upper' => 1334, 'status' => 'C', 'lower' => array(1382)); /* ARMENIAN CAPITAL LETTER ZA */ $config['0530_058f'][] = array('upper' => 1335, 'status' => 'C', 'lower' => array(1383)); /* ARMENIAN CAPITAL LETTER EH */ $config['0530_058f'][] = array('upper' => 1336, 'status' => 'C', 'lower' => array(1384)); /* ARMENIAN CAPITAL LETTER ET */ $config['0530_058f'][] = array('upper' => 1337, 'status' => 'C', 'lower' => array(1385)); /* ARMENIAN CAPITAL LETTER TO */ $config['0530_058f'][] = array('upper' => 1338, 'status' => 'C', 'lower' => array(1386)); /* ARMENIAN CAPITAL LETTER ZHE */ $config['0530_058f'][] = array('upper' => 1339, 'status' => 'C', 'lower' => array(1387)); /* ARMENIAN CAPITAL LETTER INI */ $config['0530_058f'][] = array('upper' => 1340, 'status' => 'C', 'lower' => array(1388)); /* ARMENIAN CAPITAL LETTER LIWN */ $config['0530_058f'][] = array('upper' => 1341, 'status' => 'C', 'lower' => array(1389)); /* ARMENIAN CAPITAL LETTER XEH */ $config['0530_058f'][] = array('upper' => 1342, 'status' => 'C', 'lower' => array(1390)); /* ARMENIAN CAPITAL LETTER CA */ $config['0530_058f'][] = array('upper' => 1343, 'status' => 'C', 'lower' => array(1391)); /* ARMENIAN CAPITAL LETTER KEN */ $config['0530_058f'][] = array('upper' => 1344, 'status' => 'C', 'lower' => array(1392)); /* ARMENIAN CAPITAL LETTER HO */ $config['0530_058f'][] = array('upper' => 1345, 'status' => 'C', 'lower' => array(1393)); /* ARMENIAN CAPITAL LETTER JA */ $config['0530_058f'][] = array('upper' => 1346, 'status' => 'C', 'lower' => array(1394)); /* ARMENIAN CAPITAL LETTER GHAD */ $config['0530_058f'][] = array('upper' => 1347, 'status' => 'C', 'lower' => array(1395)); /* ARMENIAN CAPITAL LETTER CHEH */ $config['0530_058f'][] = array('upper' => 1348, 'status' => 'C', 'lower' => array(1396)); /* ARMENIAN CAPITAL LETTER MEN */ $config['0530_058f'][] = array('upper' => 1349, 'status' => 'C', 'lower' => array(1397)); /* ARMENIAN CAPITAL LETTER YI */ $config['0530_058f'][] = array('upper' => 1350, 'status' => 'C', 'lower' => array(1398)); /* ARMENIAN CAPITAL LETTER NOW */ $config['0530_058f'][] = array('upper' => 1351, 'status' => 'C', 'lower' => array(1399)); /* ARMENIAN CAPITAL LETTER SHA */ $config['0530_058f'][] = array('upper' => 1352, 'status' => 'C', 'lower' => array(1400)); /* ARMENIAN CAPITAL LETTER VO */ $config['0530_058f'][] = array('upper' => 1353, 'status' => 'C', 'lower' => array(1401)); /* ARMENIAN CAPITAL LETTER CHA */ $config['0530_058f'][] = array('upper' => 1354, 'status' => 'C', 'lower' => array(1402)); /* ARMENIAN CAPITAL LETTER PEH */ $config['0530_058f'][] = array('upper' => 1355, 'status' => 'C', 'lower' => array(1403)); /* ARMENIAN CAPITAL LETTER JHEH */ $config['0530_058f'][] = array('upper' => 1356, 'status' => 'C', 'lower' => array(1404)); /* ARMENIAN CAPITAL LETTER RA */ $config['0530_058f'][] = array('upper' => 1357, 'status' => 'C', 'lower' => array(1405)); /* ARMENIAN CAPITAL LETTER SEH */ $config['0530_058f'][] = array('upper' => 1358, 'status' => 'C', 'lower' => array(1406)); /* ARMENIAN CAPITAL LETTER VEW */ $config['0530_058f'][] = array('upper' => 1359, 'status' => 'C', 'lower' => array(1407)); /* ARMENIAN CAPITAL LETTER TIWN */ $config['0530_058f'][] = array('upper' => 1360, 'status' => 'C', 'lower' => array(1408)); /* ARMENIAN CAPITAL LETTER REH */ $config['0530_058f'][] = array('upper' => 1361, 'status' => 'C', 'lower' => array(1409)); /* ARMENIAN CAPITAL LETTER CO */ $config['0530_058f'][] = array('upper' => 1362, 'status' => 'C', 'lower' => array(1410)); /* ARMENIAN CAPITAL LETTER YIWN */ $config['0530_058f'][] = array('upper' => 1363, 'status' => 'C', 'lower' => array(1411)); /* ARMENIAN CAPITAL LETTER PIWR */ $config['0530_058f'][] = array('upper' => 1364, 'status' => 'C', 'lower' => array(1412)); /* ARMENIAN CAPITAL LETTER KEH */ $config['0530_058f'][] = array('upper' => 1365, 'status' => 'C', 'lower' => array(1413)); /* ARMENIAN CAPITAL LETTER OH */ $config['0530_058f'][] = array('upper' => 1366, 'status' => 'C', 'lower' => array(1414)); /* ARMENIAN CAPITAL LETTER FEH */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/1e00_1eff.php000066400000000000000000000455101265552240500237500ustar00rootroot00000000000000 7680, 'status' => 'C', 'lower' => array(7681)); /* LATIN CAPITAL LETTER A WITH RING BELOW */ $config['1e00_1eff'][] = array('upper' => 7682, 'status' => 'C', 'lower' => array(7683)); /* LATIN CAPITAL LETTER B WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7684, 'status' => 'C', 'lower' => array(7685)); /* LATIN CAPITAL LETTER B WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7686, 'status' => 'C', 'lower' => array(7687)); /* LATIN CAPITAL LETTER B WITH LINE BELOW */ $config['1e00_1eff'][] = array('upper' => 7688, 'status' => 'C', 'lower' => array(7689)); /* LATIN CAPITAL LETTER C WITH CEDILLA AND ACUTE */ $config['1e00_1eff'][] = array('upper' => 7690, 'status' => 'C', 'lower' => array(7691)); /* LATIN CAPITAL LETTER D WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7692, 'status' => 'C', 'lower' => array(7693)); /* LATIN CAPITAL LETTER D WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7694, 'status' => 'C', 'lower' => array(7695)); /* LATIN CAPITAL LETTER D WITH LINE BELOW */ $config['1e00_1eff'][] = array('upper' => 7696, 'status' => 'C', 'lower' => array(7697)); /* LATIN CAPITAL LETTER D WITH CEDILLA */ $config['1e00_1eff'][] = array('upper' => 7698, 'status' => 'C', 'lower' => array(7699)); /* LATIN CAPITAL LETTER D WITH CIRCUMFLEX BELOW */ $config['1e00_1eff'][] = array('upper' => 7700, 'status' => 'C', 'lower' => array(7701)); /* LATIN CAPITAL LETTER E WITH MACRON AND GRAVE */ $config['1e00_1eff'][] = array('upper' => 7702, 'status' => 'C', 'lower' => array(7703)); /* LATIN CAPITAL LETTER E WITH MACRON AND ACUTE */ $config['1e00_1eff'][] = array('upper' => 7704, 'status' => 'C', 'lower' => array(7705)); /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX BELOW */ $config['1e00_1eff'][] = array('upper' => 7706, 'status' => 'C', 'lower' => array(7707)); /* LATIN CAPITAL LETTER E WITH TILDE BELOW */ $config['1e00_1eff'][] = array('upper' => 7708, 'status' => 'C', 'lower' => array(7709)); /* LATIN CAPITAL LETTER E WITH CEDILLA AND BREVE */ $config['1e00_1eff'][] = array('upper' => 7710, 'status' => 'C', 'lower' => array(7711)); /* LATIN CAPITAL LETTER F WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7712, 'status' => 'C', 'lower' => array(7713)); /* LATIN CAPITAL LETTER G WITH MACRON */ $config['1e00_1eff'][] = array('upper' => 7714, 'status' => 'C', 'lower' => array(7715)); /* LATIN CAPITAL LETTER H WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7716, 'status' => 'C', 'lower' => array(7717)); /* LATIN CAPITAL LETTER H WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7718, 'status' => 'C', 'lower' => array(7719)); /* LATIN CAPITAL LETTER H WITH DIAERESIS */ $config['1e00_1eff'][] = array('upper' => 7720, 'status' => 'C', 'lower' => array(7721)); /* LATIN CAPITAL LETTER H WITH CEDILLA */ $config['1e00_1eff'][] = array('upper' => 7722, 'status' => 'C', 'lower' => array(7723)); /* LATIN CAPITAL LETTER H WITH BREVE BELOW */ $config['1e00_1eff'][] = array('upper' => 7724, 'status' => 'C', 'lower' => array(7725)); /* LATIN CAPITAL LETTER I WITH TILDE BELOW */ $config['1e00_1eff'][] = array('upper' => 7726, 'status' => 'C', 'lower' => array(7727)); /* LATIN CAPITAL LETTER I WITH DIAERESIS AND ACUTE */ $config['1e00_1eff'][] = array('upper' => 7728, 'status' => 'C', 'lower' => array(7729)); /* LATIN CAPITAL LETTER K WITH ACUTE */ $config['1e00_1eff'][] = array('upper' => 7730, 'status' => 'C', 'lower' => array(7731)); /* LATIN CAPITAL LETTER K WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7732, 'status' => 'C', 'lower' => array(7733)); /* LATIN CAPITAL LETTER K WITH LINE BELOW */ $config['1e00_1eff'][] = array('upper' => 7734, 'status' => 'C', 'lower' => array(7735)); /* LATIN CAPITAL LETTER L WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7736, 'status' => 'C', 'lower' => array(7737)); /* LATIN CAPITAL LETTER L WITH DOT BELOW AND MACRON */ $config['1e00_1eff'][] = array('upper' => 7738, 'status' => 'C', 'lower' => array(7739)); /* LATIN CAPITAL LETTER L WITH LINE BELOW */ $config['1e00_1eff'][] = array('upper' => 7740, 'status' => 'C', 'lower' => array(7741)); /* LATIN CAPITAL LETTER L WITH CIRCUMFLEX BELOW */ $config['1e00_1eff'][] = array('upper' => 7742, 'status' => 'C', 'lower' => array(7743)); /* LATIN CAPITAL LETTER M WITH ACUTE */ $config['1e00_1eff'][] = array('upper' => 7744, 'status' => 'C', 'lower' => array(7745)); /* LATIN CAPITAL LETTER M WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7746, 'status' => 'C', 'lower' => array(7747)); /* LATIN CAPITAL LETTER M WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7748, 'status' => 'C', 'lower' => array(7749)); /* LATIN CAPITAL LETTER N WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7750, 'status' => 'C', 'lower' => array(7751)); /* LATIN CAPITAL LETTER N WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7752, 'status' => 'C', 'lower' => array(7753)); /* LATIN CAPITAL LETTER N WITH LINE BELOW */ $config['1e00_1eff'][] = array('upper' => 7754, 'status' => 'C', 'lower' => array(7755)); /* LATIN CAPITAL LETTER N WITH CIRCUMFLEX BELOW */ $config['1e00_1eff'][] = array('upper' => 7756, 'status' => 'C', 'lower' => array(7757)); /* LATIN CAPITAL LETTER O WITH TILDE AND ACUTE */ $config['1e00_1eff'][] = array('upper' => 7758, 'status' => 'C', 'lower' => array(7759)); /* LATIN CAPITAL LETTER O WITH TILDE AND DIAERESIS */ $config['1e00_1eff'][] = array('upper' => 7760, 'status' => 'C', 'lower' => array(7761)); /* LATIN CAPITAL LETTER O WITH MACRON AND GRAVE */ $config['1e00_1eff'][] = array('upper' => 7762, 'status' => 'C', 'lower' => array(7763)); /* LATIN CAPITAL LETTER O WITH MACRON AND ACUTE */ $config['1e00_1eff'][] = array('upper' => 7764, 'status' => 'C', 'lower' => array(7765)); /* LATIN CAPITAL LETTER P WITH ACUTE */ $config['1e00_1eff'][] = array('upper' => 7766, 'status' => 'C', 'lower' => array(7767)); /* LATIN CAPITAL LETTER P WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7768, 'status' => 'C', 'lower' => array(7769)); /* LATIN CAPITAL LETTER R WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7770, 'status' => 'C', 'lower' => array(7771)); /* LATIN CAPITAL LETTER R WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7772, 'status' => 'C', 'lower' => array(7773)); /* LATIN CAPITAL LETTER R WITH DOT BELOW AND MACRON */ $config['1e00_1eff'][] = array('upper' => 7774, 'status' => 'C', 'lower' => array(7775)); /* LATIN CAPITAL LETTER R WITH LINE BELOW */ $config['1e00_1eff'][] = array('upper' => 7776, 'status' => 'C', 'lower' => array(7777)); /* LATIN CAPITAL LETTER S WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7778, 'status' => 'C', 'lower' => array(7779)); /* LATIN CAPITAL LETTER S WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7780, 'status' => 'C', 'lower' => array(7781)); /* LATIN CAPITAL LETTER S WITH ACUTE AND DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7782, 'status' => 'C', 'lower' => array(7783)); /* LATIN CAPITAL LETTER S WITH CARON AND DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7784, 'status' => 'C', 'lower' => array(7785)); /* LATIN CAPITAL LETTER S WITH DOT BELOW AND DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7786, 'status' => 'C', 'lower' => array(7787)); /* LATIN CAPITAL LETTER T WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7788, 'status' => 'C', 'lower' => array(7789)); /* LATIN CAPITAL LETTER T WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7790, 'status' => 'C', 'lower' => array(7791)); /* LATIN CAPITAL LETTER T WITH LINE BELOW */ $config['1e00_1eff'][] = array('upper' => 7792, 'status' => 'C', 'lower' => array(7793)); /* LATIN CAPITAL LETTER T WITH CIRCUMFLEX BELOW */ $config['1e00_1eff'][] = array('upper' => 7794, 'status' => 'C', 'lower' => array(7795)); /* LATIN CAPITAL LETTER U WITH DIAERESIS BELOW */ $config['1e00_1eff'][] = array('upper' => 7796, 'status' => 'C', 'lower' => array(7797)); /* LATIN CAPITAL LETTER U WITH TILDE BELOW */ $config['1e00_1eff'][] = array('upper' => 7798, 'status' => 'C', 'lower' => array(7799)); /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX BELOW */ $config['1e00_1eff'][] = array('upper' => 7800, 'status' => 'C', 'lower' => array(7801)); /* LATIN CAPITAL LETTER U WITH TILDE AND ACUTE */ $config['1e00_1eff'][] = array('upper' => 7802, 'status' => 'C', 'lower' => array(7803)); /* LATIN CAPITAL LETTER U WITH MACRON AND DIAERESIS */ $config['1e00_1eff'][] = array('upper' => 7804, 'status' => 'C', 'lower' => array(7805)); /* LATIN CAPITAL LETTER V WITH TILDE */ $config['1e00_1eff'][] = array('upper' => 7806, 'status' => 'C', 'lower' => array(7807)); /* LATIN CAPITAL LETTER V WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7808, 'status' => 'C', 'lower' => array(7809)); /* LATIN CAPITAL LETTER W WITH GRAVE */ $config['1e00_1eff'][] = array('upper' => 7810, 'status' => 'C', 'lower' => array(7811)); /* LATIN CAPITAL LETTER W WITH ACUTE */ $config['1e00_1eff'][] = array('upper' => 7812, 'status' => 'C', 'lower' => array(7813)); /* LATIN CAPITAL LETTER W WITH DIAERESIS */ $config['1e00_1eff'][] = array('upper' => 7814, 'status' => 'C', 'lower' => array(7815)); /* LATIN CAPITAL LETTER W WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7816, 'status' => 'C', 'lower' => array(7817)); /* LATIN CAPITAL LETTER W WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7818, 'status' => 'C', 'lower' => array(7819)); /* LATIN CAPITAL LETTER X WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7820, 'status' => 'C', 'lower' => array(7821)); /* LATIN CAPITAL LETTER X WITH DIAERESIS */ $config['1e00_1eff'][] = array('upper' => 7822, 'status' => 'C', 'lower' => array(7823)); /* LATIN CAPITAL LETTER Y WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7824, 'status' => 'C', 'lower' => array(7825)); /* LATIN CAPITAL LETTER Z WITH CIRCUMFLEX */ $config['1e00_1eff'][] = array('upper' => 7826, 'status' => 'C', 'lower' => array(7827)); /* LATIN CAPITAL LETTER Z WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7828, 'status' => 'C', 'lower' => array(7829)); /* LATIN CAPITAL LETTER Z WITH LINE BELOW */ //$config['1e00_1eff'][] = array('upper' => 7830, 'status' => 'F', 'lower' => array(104, 817)); /* LATIN SMALL LETTER H WITH LINE BELOW */ //$config['1e00_1eff'][] = array('upper' => 7831, 'status' => 'F', 'lower' => array(116, 776)); /* LATIN SMALL LETTER T WITH DIAERESIS */ //$config['1e00_1eff'][] = array('upper' => 7832, 'status' => 'F', 'lower' => array(119, 778)); /* LATIN SMALL LETTER W WITH RING ABOVE */ //$config['1e00_1eff'][] = array('upper' => 7833, 'status' => 'F', 'lower' => array(121, 778)); /* LATIN SMALL LETTER Y WITH RING ABOVE */ //$config['1e00_1eff'][] = array('upper' => 7834, 'status' => 'F', 'lower' => array(97, 702)); /* LATIN SMALL LETTER A WITH RIGHT HALF RING */ //$config['1e00_1eff'][] = array('upper' => 7835, 'status' => 'C', 'lower' => array(7777)); /* LATIN SMALL LETTER LONG S WITH DOT ABOVE */ $config['1e00_1eff'][] = array('upper' => 7840, 'status' => 'C', 'lower' => array(7841)); /* LATIN CAPITAL LETTER A WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7842, 'status' => 'C', 'lower' => array(7843)); /* LATIN CAPITAL LETTER A WITH HOOK ABOVE */ $config['1e00_1eff'][] = array('upper' => 7844, 'status' => 'C', 'lower' => array(7845)); /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE */ $config['1e00_1eff'][] = array('upper' => 7846, 'status' => 'C', 'lower' => array(7847)); /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE */ $config['1e00_1eff'][] = array('upper' => 7848, 'status' => 'C', 'lower' => array(7849)); /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE */ $config['1e00_1eff'][] = array('upper' => 7850, 'status' => 'C', 'lower' => array(7851)); /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE */ $config['1e00_1eff'][] = array('upper' => 7852, 'status' => 'C', 'lower' => array(7853)); /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7854, 'status' => 'C', 'lower' => array(7855)); /* LATIN CAPITAL LETTER A WITH BREVE AND ACUTE */ $config['1e00_1eff'][] = array('upper' => 7856, 'status' => 'C', 'lower' => array(7857)); /* LATIN CAPITAL LETTER A WITH BREVE AND GRAVE */ $config['1e00_1eff'][] = array('upper' => 7858, 'status' => 'C', 'lower' => array(7859)); /* LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE */ $config['1e00_1eff'][] = array('upper' => 7860, 'status' => 'C', 'lower' => array(7861)); /* LATIN CAPITAL LETTER A WITH BREVE AND TILDE */ $config['1e00_1eff'][] = array('upper' => 7862, 'status' => 'C', 'lower' => array(7863)); /* LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7864, 'status' => 'C', 'lower' => array(7865)); /* LATIN CAPITAL LETTER E WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7866, 'status' => 'C', 'lower' => array(7867)); /* LATIN CAPITAL LETTER E WITH HOOK ABOVE */ $config['1e00_1eff'][] = array('upper' => 7868, 'status' => 'C', 'lower' => array(7869)); /* LATIN CAPITAL LETTER E WITH TILDE */ $config['1e00_1eff'][] = array('upper' => 7870, 'status' => 'C', 'lower' => array(7871)); /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE */ $config['1e00_1eff'][] = array('upper' => 7872, 'status' => 'C', 'lower' => array(7873)); /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE */ $config['1e00_1eff'][] = array('upper' => 7874, 'status' => 'C', 'lower' => array(7875)); /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE */ $config['1e00_1eff'][] = array('upper' => 7876, 'status' => 'C', 'lower' => array(7877)); /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE */ $config['1e00_1eff'][] = array('upper' => 7878, 'status' => 'C', 'lower' => array(7879)); /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7880, 'status' => 'C', 'lower' => array(7881)); /* LATIN CAPITAL LETTER I WITH HOOK ABOVE */ $config['1e00_1eff'][] = array('upper' => 7882, 'status' => 'C', 'lower' => array(7883)); /* LATIN CAPITAL LETTER I WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7884, 'status' => 'C', 'lower' => array(7885)); /* LATIN CAPITAL LETTER O WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7886, 'status' => 'C', 'lower' => array(7887)); /* LATIN CAPITAL LETTER O WITH HOOK ABOVE */ $config['1e00_1eff'][] = array('upper' => 7888, 'status' => 'C', 'lower' => array(7889)); /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE */ $config['1e00_1eff'][] = array('upper' => 7890, 'status' => 'C', 'lower' => array(7891)); /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE */ $config['1e00_1eff'][] = array('upper' => 7892, 'status' => 'C', 'lower' => array(7893)); /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE */ $config['1e00_1eff'][] = array('upper' => 7894, 'status' => 'C', 'lower' => array(7895)); /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE */ $config['1e00_1eff'][] = array('upper' => 7896, 'status' => 'C', 'lower' => array(7897)); /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7898, 'status' => 'C', 'lower' => array(7899)); /* LATIN CAPITAL LETTER O WITH HORN AND ACUTE */ $config['1e00_1eff'][] = array('upper' => 7900, 'status' => 'C', 'lower' => array(7901)); /* LATIN CAPITAL LETTER O WITH HORN AND GRAVE */ $config['1e00_1eff'][] = array('upper' => 7902, 'status' => 'C', 'lower' => array(7903)); /* LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE */ $config['1e00_1eff'][] = array('upper' => 7904, 'status' => 'C', 'lower' => array(7905)); /* LATIN CAPITAL LETTER O WITH HORN AND TILDE */ $config['1e00_1eff'][] = array('upper' => 7906, 'status' => 'C', 'lower' => array(7907)); /* LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7908, 'status' => 'C', 'lower' => array(7909)); /* LATIN CAPITAL LETTER U WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7910, 'status' => 'C', 'lower' => array(7911)); /* LATIN CAPITAL LETTER U WITH HOOK ABOVE */ $config['1e00_1eff'][] = array('upper' => 7912, 'status' => 'C', 'lower' => array(7913)); /* LATIN CAPITAL LETTER U WITH HORN AND ACUTE */ $config['1e00_1eff'][] = array('upper' => 7914, 'status' => 'C', 'lower' => array(7915)); /* LATIN CAPITAL LETTER U WITH HORN AND GRAVE */ $config['1e00_1eff'][] = array('upper' => 7916, 'status' => 'C', 'lower' => array(7917)); /* LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE */ $config['1e00_1eff'][] = array('upper' => 7918, 'status' => 'C', 'lower' => array(7919)); /* LATIN CAPITAL LETTER U WITH HORN AND TILDE */ $config['1e00_1eff'][] = array('upper' => 7920, 'status' => 'C', 'lower' => array(7921)); /* LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7922, 'status' => 'C', 'lower' => array(7923)); /* LATIN CAPITAL LETTER Y WITH GRAVE */ $config['1e00_1eff'][] = array('upper' => 7924, 'status' => 'C', 'lower' => array(7925)); /* LATIN CAPITAL LETTER Y WITH DOT BELOW */ $config['1e00_1eff'][] = array('upper' => 7926, 'status' => 'C', 'lower' => array(7927)); /* LATIN CAPITAL LETTER Y WITH HOOK ABOVE */ $config['1e00_1eff'][] = array('upper' => 7928, 'status' => 'C', 'lower' => array(7929)); /* LATIN CAPITAL LETTER Y WITH TILDE */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/1f00_1fff.php000066400000000000000000000675441265552240500237650ustar00rootroot00000000000000 7944, 'status' => 'C', 'lower' => array(7936, 953)); /* GREEK CAPITAL LETTER ALPHA WITH PSILI */ $config['1f00_1fff'][] = array('upper' => 7945, 'status' => 'C', 'lower' => array(7937)); /* GREEK CAPITAL LETTER ALPHA WITH DASIA */ $config['1f00_1fff'][] = array('upper' => 7946, 'status' => 'C', 'lower' => array(7938)); /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA */ $config['1f00_1fff'][] = array('upper' => 7947, 'status' => 'C', 'lower' => array(7939)); /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA */ $config['1f00_1fff'][] = array('upper' => 7948, 'status' => 'C', 'lower' => array(7940)); /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA */ $config['1f00_1fff'][] = array('upper' => 7949, 'status' => 'C', 'lower' => array(7941)); /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA */ $config['1f00_1fff'][] = array('upper' => 7950, 'status' => 'C', 'lower' => array(7942)); /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 7951, 'status' => 'C', 'lower' => array(7943)); /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 7960, 'status' => 'C', 'lower' => array(7952)); /* GREEK CAPITAL LETTER EPSILON WITH PSILI */ $config['1f00_1fff'][] = array('upper' => 7961, 'status' => 'C', 'lower' => array(7953)); /* GREEK CAPITAL LETTER EPSILON WITH DASIA */ $config['1f00_1fff'][] = array('upper' => 7962, 'status' => 'C', 'lower' => array(7954)); /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND VARIA */ $config['1f00_1fff'][] = array('upper' => 7963, 'status' => 'C', 'lower' => array(7955)); /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND VARIA */ $config['1f00_1fff'][] = array('upper' => 7964, 'status' => 'C', 'lower' => array(7956)); /* GREEK CAPITAL LETTER EPSILON WITH PSILI AND OXIA */ $config['1f00_1fff'][] = array('upper' => 7965, 'status' => 'C', 'lower' => array(7957)); /* GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA */ $config['1f00_1fff'][] = array('upper' => 7976, 'status' => 'C', 'lower' => array(7968)); /* GREEK CAPITAL LETTER ETA WITH PSILI */ $config['1f00_1fff'][] = array('upper' => 7977, 'status' => 'C', 'lower' => array(7969)); /* GREEK CAPITAL LETTER ETA WITH DASIA */ $config['1f00_1fff'][] = array('upper' => 7978, 'status' => 'C', 'lower' => array(7970)); /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA */ $config['1f00_1fff'][] = array('upper' => 7979, 'status' => 'C', 'lower' => array(7971)); /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA */ $config['1f00_1fff'][] = array('upper' => 7980, 'status' => 'C', 'lower' => array(7972)); /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA */ $config['1f00_1fff'][] = array('upper' => 7981, 'status' => 'C', 'lower' => array(7973)); /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA */ $config['1f00_1fff'][] = array('upper' => 7982, 'status' => 'C', 'lower' => array(7974)); /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 7983, 'status' => 'C', 'lower' => array(7975)); /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 7992, 'status' => 'C', 'lower' => array(7984)); /* GREEK CAPITAL LETTER IOTA WITH PSILI */ $config['1f00_1fff'][] = array('upper' => 7993, 'status' => 'C', 'lower' => array(7985)); /* GREEK CAPITAL LETTER IOTA WITH DASIA */ $config['1f00_1fff'][] = array('upper' => 7994, 'status' => 'C', 'lower' => array(7986)); /* GREEK CAPITAL LETTER IOTA WITH PSILI AND VARIA */ $config['1f00_1fff'][] = array('upper' => 7995, 'status' => 'C', 'lower' => array(7987)); /* GREEK CAPITAL LETTER IOTA WITH DASIA AND VARIA */ $config['1f00_1fff'][] = array('upper' => 7996, 'status' => 'C', 'lower' => array(7988)); /* GREEK CAPITAL LETTER IOTA WITH PSILI AND OXIA */ $config['1f00_1fff'][] = array('upper' => 7997, 'status' => 'C', 'lower' => array(7989)); /* GREEK CAPITAL LETTER IOTA WITH DASIA AND OXIA */ $config['1f00_1fff'][] = array('upper' => 7998, 'status' => 'C', 'lower' => array(7990)); /* GREEK CAPITAL LETTER IOTA WITH PSILI AND PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 7999, 'status' => 'C', 'lower' => array(7991)); /* GREEK CAPITAL LETTER IOTA WITH DASIA AND PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 8008, 'status' => 'C', 'lower' => array(8000)); /* GREEK CAPITAL LETTER OMICRON WITH PSILI */ $config['1f00_1fff'][] = array('upper' => 8009, 'status' => 'C', 'lower' => array(8001)); /* GREEK CAPITAL LETTER OMICRON WITH DASIA */ $config['1f00_1fff'][] = array('upper' => 8010, 'status' => 'C', 'lower' => array(8002)); /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND VARIA */ $config['1f00_1fff'][] = array('upper' => 8011, 'status' => 'C', 'lower' => array(8003)); /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND VARIA */ $config['1f00_1fff'][] = array('upper' => 8012, 'status' => 'C', 'lower' => array(8004)); /* GREEK CAPITAL LETTER OMICRON WITH PSILI AND OXIA */ $config['1f00_1fff'][] = array('upper' => 8013, 'status' => 'C', 'lower' => array(8005)); /* GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA */ $config['1f00_1fff'][] = array('upper' => 8016, 'status' => 'F', 'lower' => array(965, 787)); /* GREEK SMALL LETTER UPSILON WITH PSILI */ $config['1f00_1fff'][] = array('upper' => 8018, 'status' => 'F', 'lower' => array(965, 787, 768)); /* GREEK SMALL LETTER UPSILON WITH PSILI AND VARIA */ $config['1f00_1fff'][] = array('upper' => 8020, 'status' => 'F', 'lower' => array(965, 787, 769)); /* GREEK SMALL LETTER UPSILON WITH PSILI AND OXIA */ $config['1f00_1fff'][] = array('upper' => 8022, 'status' => 'F', 'lower' => array(965, 787, 834)); /* GREEK SMALL LETTER UPSILON WITH PSILI AND PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 8025, 'status' => 'C', 'lower' => array(8017)); /* GREEK CAPITAL LETTER UPSILON WITH DASIA */ $config['1f00_1fff'][] = array('upper' => 8027, 'status' => 'C', 'lower' => array(8019)); /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA */ $config['1f00_1fff'][] = array('upper' => 8029, 'status' => 'C', 'lower' => array(8021)); /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA */ $config['1f00_1fff'][] = array('upper' => 8031, 'status' => 'C', 'lower' => array(8023)); /* GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 8040, 'status' => 'C', 'lower' => array(8032)); /* GREEK CAPITAL LETTER OMEGA WITH PSILI */ $config['1f00_1fff'][] = array('upper' => 8041, 'status' => 'C', 'lower' => array(8033)); /* GREEK CAPITAL LETTER OMEGA WITH DASIA */ $config['1f00_1fff'][] = array('upper' => 8042, 'status' => 'C', 'lower' => array(8034)); /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA */ $config['1f00_1fff'][] = array('upper' => 8043, 'status' => 'C', 'lower' => array(8035)); /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA */ $config['1f00_1fff'][] = array('upper' => 8044, 'status' => 'C', 'lower' => array(8036)); /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA */ $config['1f00_1fff'][] = array('upper' => 8045, 'status' => 'C', 'lower' => array(8037)); /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA */ $config['1f00_1fff'][] = array('upper' => 8046, 'status' => 'C', 'lower' => array(8038)); /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 8047, 'status' => 'C', 'lower' => array(8039)); /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 8064, 'status' => 'F', 'lower' => array(7936, 953)); /* GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8065, 'status' => 'F', 'lower' => array(7937, 953)); /* GREEK SMALL LETTER ALPHA WITH DASIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8066, 'status' => 'F', 'lower' => array(7938, 953)); /* GREEK SMALL LETTER ALPHA WITH PSILI AND VARIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8067, 'status' => 'F', 'lower' => array(7939, 953)); /* GREEK SMALL LETTER ALPHA WITH DASIA AND VARIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8068, 'status' => 'F', 'lower' => array(7940, 953)); /* GREEK SMALL LETTER ALPHA WITH PSILI AND OXIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8069, 'status' => 'F', 'lower' => array(7941, 953)); /* GREEK SMALL LETTER ALPHA WITH DASIA AND OXIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8070, 'status' => 'F', 'lower' => array(7942, 953)); /* GREEK SMALL LETTER ALPHA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8071, 'status' => 'F', 'lower' => array(7943, 953)); /* GREEK SMALL LETTER ALPHA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8072, 'status' => 'F', 'lower' => array(7936, 953)); /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8072, 'status' => 'S', 'lower' => array(8064)); /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8073, 'status' => 'F', 'lower' => array(7937, 953)); /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8073, 'status' => 'S', 'lower' => array(8065)); /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8074, 'status' => 'F', 'lower' => array(7938, 953)); /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8074, 'status' => 'S', 'lower' => array(8066)); /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8075, 'status' => 'F', 'lower' => array(7939, 953)); /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8075, 'status' => 'S', 'lower' => array(8067)); /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8076, 'status' => 'F', 'lower' => array(7940, 953)); /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8076, 'status' => 'S', 'lower' => array(8068)); /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8077, 'status' => 'F', 'lower' => array(7941, 953)); /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8077, 'status' => 'S', 'lower' => array(8069)); /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8078, 'status' => 'F', 'lower' => array(7942, 953)); /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8078, 'status' => 'S', 'lower' => array(8070)); /* GREEK CAPITAL LETTER ALPHA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8079, 'status' => 'F', 'lower' => array(7943, 953)); /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8079, 'status' => 'S', 'lower' => array(8071)); /* GREEK CAPITAL LETTER ALPHA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8080, 'status' => 'F', 'lower' => array(7968, 953)); /* GREEK SMALL LETTER ETA WITH PSILI AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8081, 'status' => 'F', 'lower' => array(7969, 953)); /* GREEK SMALL LETTER ETA WITH DASIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8082, 'status' => 'F', 'lower' => array(7970, 953)); /* GREEK SMALL LETTER ETA WITH PSILI AND VARIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8083, 'status' => 'F', 'lower' => array(7971, 953)); /* GREEK SMALL LETTER ETA WITH DASIA AND VARIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8084, 'status' => 'F', 'lower' => array(7972, 953)); /* GREEK SMALL LETTER ETA WITH PSILI AND OXIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8085, 'status' => 'F', 'lower' => array(7973, 953)); /* GREEK SMALL LETTER ETA WITH DASIA AND OXIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8086, 'status' => 'F', 'lower' => array(7974, 953)); /* GREEK SMALL LETTER ETA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8087, 'status' => 'F', 'lower' => array(7975, 953)); /* GREEK SMALL LETTER ETA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8088, 'status' => 'F', 'lower' => array(7968, 953)); /* GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8088, 'status' => 'S', 'lower' => array(8080)); /* GREEK CAPITAL LETTER ETA WITH PSILI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8089, 'status' => 'F', 'lower' => array(7969, 953)); /* GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8089, 'status' => 'S', 'lower' => array(8081)); /* GREEK CAPITAL LETTER ETA WITH DASIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8090, 'status' => 'F', 'lower' => array(7970, 953)); /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8090, 'status' => 'S', 'lower' => array(8082)); /* GREEK CAPITAL LETTER ETA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8091, 'status' => 'F', 'lower' => array(7971, 953)); /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8091, 'status' => 'S', 'lower' => array(8083)); /* GREEK CAPITAL LETTER ETA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8092, 'status' => 'F', 'lower' => array(7972, 953)); /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8092, 'status' => 'S', 'lower' => array(8084)); /* GREEK CAPITAL LETTER ETA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8093, 'status' => 'F', 'lower' => array(7973, 953)); /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8093, 'status' => 'S', 'lower' => array(8085)); /* GREEK CAPITAL LETTER ETA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8094, 'status' => 'F', 'lower' => array(7974, 953)); /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8094, 'status' => 'S', 'lower' => array(8086)); /* GREEK CAPITAL LETTER ETA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8095, 'status' => 'F', 'lower' => array(7975, 953)); /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8095, 'status' => 'S', 'lower' => array(8087)); /* GREEK CAPITAL LETTER ETA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8096, 'status' => 'F', 'lower' => array(8032, 953)); /* GREEK SMALL LETTER OMEGA WITH PSILI AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8097, 'status' => 'F', 'lower' => array(8033, 953)); /* GREEK SMALL LETTER OMEGA WITH DASIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8098, 'status' => 'F', 'lower' => array(8034, 953)); /* GREEK SMALL LETTER OMEGA WITH PSILI AND VARIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8099, 'status' => 'F', 'lower' => array(8035, 953)); /* GREEK SMALL LETTER OMEGA WITH DASIA AND VARIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8100, 'status' => 'F', 'lower' => array(8036, 953)); /* GREEK SMALL LETTER OMEGA WITH PSILI AND OXIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8101, 'status' => 'F', 'lower' => array(8037, 953)); /* GREEK SMALL LETTER OMEGA WITH DASIA AND OXIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8102, 'status' => 'F', 'lower' => array(8038, 953)); /* GREEK SMALL LETTER OMEGA WITH PSILI AND PERISPOMENI AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8103, 'status' => 'F', 'lower' => array(8039, 953)); /* GREEK SMALL LETTER OMEGA WITH DASIA AND PERISPOMENI AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8104, 'status' => 'F', 'lower' => array(8032, 953)); /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8104, 'status' => 'S', 'lower' => array(8096)); /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8105, 'status' => 'F', 'lower' => array(8033, 953)); /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8105, 'status' => 'S', 'lower' => array(8097)); /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8106, 'status' => 'F', 'lower' => array(8034, 953)); /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8106, 'status' => 'S', 'lower' => array(8098)); /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND VARIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8107, 'status' => 'F', 'lower' => array(8035, 953)); /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8107, 'status' => 'S', 'lower' => array(8099)); /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND VARIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8108, 'status' => 'F', 'lower' => array(8036, 953)); /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8108, 'status' => 'S', 'lower' => array(8100)); /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND OXIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8109, 'status' => 'F', 'lower' => array(8037, 953)); /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8109, 'status' => 'S', 'lower' => array(8101)); /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND OXIA AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8110, 'status' => 'F', 'lower' => array(8038, 953)); /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8110, 'status' => 'S', 'lower' => array(8102)); /* GREEK CAPITAL LETTER OMEGA WITH PSILI AND PERISPOMENI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8111, 'status' => 'F', 'lower' => array(8039, 953)); /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8111, 'status' => 'S', 'lower' => array(8103)); /* GREEK CAPITAL LETTER OMEGA WITH DASIA AND PERISPOMENI AND PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8114, 'status' => 'F', 'lower' => array(8048, 953)); /* GREEK SMALL LETTER ALPHA WITH VARIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8115, 'status' => 'F', 'lower' => array(945, 953)); /* GREEK SMALL LETTER ALPHA WITH YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8116, 'status' => 'F', 'lower' => array(940, 953)); /* GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8118, 'status' => 'F', 'lower' => array(945, 834)); /* GREEK SMALL LETTER ALPHA WITH PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 8119, 'status' => 'F', 'lower' => array(945, 834, 953)); /* GREEK SMALL LETTER ALPHA WITH PERISPOMENI AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8120, 'status' => 'C', 'lower' => array(8112)); /* GREEK CAPITAL LETTER ALPHA WITH VRACHY */ $config['1f00_1fff'][] = array('upper' => 8121, 'status' => 'C', 'lower' => array(8113)); /* GREEK CAPITAL LETTER ALPHA WITH MACRON */ $config['1f00_1fff'][] = array('upper' => 8122, 'status' => 'C', 'lower' => array(8048)); /* GREEK CAPITAL LETTER ALPHA WITH VARIA */ $config['1f00_1fff'][] = array('upper' => 8123, 'status' => 'C', 'lower' => array(8049)); /* GREEK CAPITAL LETTER ALPHA WITH OXIA */ $config['1f00_1fff'][] = array('upper' => 8124, 'status' => 'F', 'lower' => array(945, 953)); /* GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8124, 'status' => 'S', 'lower' => array(8115)); /* GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8126, 'status' => 'C', 'lower' => array(953)); /* GREEK PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8130, 'status' => 'F', 'lower' => array(8052, 953)); /* GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8131, 'status' => 'F', 'lower' => array(951, 953)); /* GREEK SMALL LETTER ETA WITH YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8132, 'status' => 'F', 'lower' => array(942, 953)); /* GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8134, 'status' => 'F', 'lower' => array(951, 834)); /* GREEK SMALL LETTER ETA WITH PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 8135, 'status' => 'F', 'lower' => array(951, 834, 953)); /* GREEK SMALL LETTER ETA WITH PERISPOMENI AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8136, 'status' => 'C', 'lower' => array(8050)); /* GREEK CAPITAL LETTER EPSILON WITH VARIA */ $config['1f00_1fff'][] = array('upper' => 8137, 'status' => 'C', 'lower' => array(8051)); /* GREEK CAPITAL LETTER EPSILON WITH OXIA */ $config['1f00_1fff'][] = array('upper' => 8138, 'status' => 'C', 'lower' => array(8052)); /* GREEK CAPITAL LETTER ETA WITH VARIA */ $config['1f00_1fff'][] = array('upper' => 8139, 'status' => 'C', 'lower' => array(8053)); /* GREEK CAPITAL LETTER ETA WITH OXIA */ $config['1f00_1fff'][] = array('upper' => 8140, 'status' => 'F', 'lower' => array(951, 953)); /* GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8140, 'status' => 'S', 'lower' => array(8131)); /* GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8146, 'status' => 'F', 'lower' => array(953, 776, 768)); /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA */ $config['1f00_1fff'][] = array('upper' => 8147, 'status' => 'F', 'lower' => array(953, 776, 769)); /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA */ $config['1f00_1fff'][] = array('upper' => 8150, 'status' => 'F', 'lower' => array(953, 834)); /* GREEK SMALL LETTER IOTA WITH PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 8151, 'status' => 'F', 'lower' => array(953, 776, 834)); /* GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 8152, 'status' => 'C', 'lower' => array(8144)); /* GREEK CAPITAL LETTER IOTA WITH VRACHY */ $config['1f00_1fff'][] = array('upper' => 8153, 'status' => 'C', 'lower' => array(8145)); /* GREEK CAPITAL LETTER IOTA WITH MACRON */ $config['1f00_1fff'][] = array('upper' => 8154, 'status' => 'C', 'lower' => array(8054)); /* GREEK CAPITAL LETTER IOTA WITH VARIA */ $config['1f00_1fff'][] = array('upper' => 8155, 'status' => 'C', 'lower' => array(8055)); /* GREEK CAPITAL LETTER IOTA WITH OXIA */ $config['1f00_1fff'][] = array('upper' => 8162, 'status' => 'F', 'lower' => array(965, 776, 768)); /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA */ $config['1f00_1fff'][] = array('upper' => 8163, 'status' => 'F', 'lower' => array(965, 776, 769)); /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA */ $config['1f00_1fff'][] = array('upper' => 8164, 'status' => 'F', 'lower' => array(961, 787)); /* GREEK SMALL LETTER RHO WITH PSILI */ $config['1f00_1fff'][] = array('upper' => 8166, 'status' => 'F', 'lower' => array(965, 834)); /* GREEK SMALL LETTER UPSILON WITH PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 8167, 'status' => 'F', 'lower' => array(965, 776, 834)); /* GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 8168, 'status' => 'C', 'lower' => array(8160)); /* GREEK CAPITAL LETTER UPSILON WITH VRACHY */ $config['1f00_1fff'][] = array('upper' => 8169, 'status' => 'C', 'lower' => array(8161)); /* GREEK CAPITAL LETTER UPSILON WITH MACRON */ $config['1f00_1fff'][] = array('upper' => 8170, 'status' => 'C', 'lower' => array(8058)); /* GREEK CAPITAL LETTER UPSILON WITH VARIA */ $config['1f00_1fff'][] = array('upper' => 8171, 'status' => 'C', 'lower' => array(8059)); /* GREEK CAPITAL LETTER UPSILON WITH OXIA */ $config['1f00_1fff'][] = array('upper' => 8172, 'status' => 'C', 'lower' => array(8165)); /* GREEK CAPITAL LETTER RHO WITH DASIA */ $config['1f00_1fff'][] = array('upper' => 8178, 'status' => 'F', 'lower' => array(8060, 953)); /* GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8179, 'status' => 'F', 'lower' => array(969, 953)); /* GREEK SMALL LETTER OMEGA WITH YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8180, 'status' => 'F', 'lower' => array(974, 953)); /* GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8182, 'status' => 'F', 'lower' => array(969, 834)); /* GREEK SMALL LETTER OMEGA WITH PERISPOMENI */ $config['1f00_1fff'][] = array('upper' => 8183, 'status' => 'F', 'lower' => array(969, 834, 953)); /* GREEK SMALL LETTER OMEGA WITH PERISPOMENI AND YPOGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8184, 'status' => 'C', 'lower' => array(8056)); /* GREEK CAPITAL LETTER OMICRON WITH VARIA */ $config['1f00_1fff'][] = array('upper' => 8185, 'status' => 'C', 'lower' => array(8057)); /* GREEK CAPITAL LETTER OMICRON WITH OXIA */ $config['1f00_1fff'][] = array('upper' => 8186, 'status' => 'C', 'lower' => array(8060)); /* GREEK CAPITAL LETTER OMEGA WITH VARIA */ $config['1f00_1fff'][] = array('upper' => 8187, 'status' => 'C', 'lower' => array(8061)); /* GREEK CAPITAL LETTER OMEGA WITH OXIA */ $config['1f00_1fff'][] = array('upper' => 8188, 'status' => 'F', 'lower' => array(969, 953)); /* GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI */ $config['1f00_1fff'][] = array('upper' => 8188, 'status' => 'S', 'lower' => array(8179)); /* GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/2100_214f.php000066400000000000000000000044131265552240500235150ustar00rootroot00000000000000 8486, 'status' => 'C', 'lower' => array(969)); /* OHM SIGN */ $config['2100_214f'][] = array('upper' => 8490, 'status' => 'C', 'lower' => array(107)); /* KELVIN SIGN */ $config['2100_214f'][] = array('upper' => 8491, 'status' => 'C', 'lower' => array(229)); /* ANGSTROM SIGN */ $config['2100_214f'][] = array('upper' => 8498, 'status' => 'C', 'lower' => array(8526)); /* TURNED CAPITAL F */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/2150_218f.php000066400000000000000000000074501265552240500235320ustar00rootroot00000000000000 8544, 'status' => 'C', 'lower' => array(8560)); /* ROMAN NUMERAL ONE */ $config['2150_218f'][] = array('upper' => 8545, 'status' => 'C', 'lower' => array(8561)); /* ROMAN NUMERAL TWO */ $config['2150_218f'][] = array('upper' => 8546, 'status' => 'C', 'lower' => array(8562)); /* ROMAN NUMERAL THREE */ $config['2150_218f'][] = array('upper' => 8547, 'status' => 'C', 'lower' => array(8563)); /* ROMAN NUMERAL FOUR */ $config['2150_218f'][] = array('upper' => 8548, 'status' => 'C', 'lower' => array(8564)); /* ROMAN NUMERAL FIVE */ $config['2150_218f'][] = array('upper' => 8549, 'status' => 'C', 'lower' => array(8565)); /* ROMAN NUMERAL SIX */ $config['2150_218f'][] = array('upper' => 8550, 'status' => 'C', 'lower' => array(8566)); /* ROMAN NUMERAL SEVEN */ $config['2150_218f'][] = array('upper' => 8551, 'status' => 'C', 'lower' => array(8567)); /* ROMAN NUMERAL EIGHT */ $config['2150_218f'][] = array('upper' => 8552, 'status' => 'C', 'lower' => array(8568)); /* ROMAN NUMERAL NINE */ $config['2150_218f'][] = array('upper' => 8553, 'status' => 'C', 'lower' => array(8569)); /* ROMAN NUMERAL TEN */ $config['2150_218f'][] = array('upper' => 8554, 'status' => 'C', 'lower' => array(8570)); /* ROMAN NUMERAL ELEVEN */ $config['2150_218f'][] = array('upper' => 8555, 'status' => 'C', 'lower' => array(8571)); /* ROMAN NUMERAL TWELVE */ $config['2150_218f'][] = array('upper' => 8556, 'status' => 'C', 'lower' => array(8572)); /* ROMAN NUMERAL FIFTY */ $config['2150_218f'][] = array('upper' => 8557, 'status' => 'C', 'lower' => array(8573)); /* ROMAN NUMERAL ONE HUNDRED */ $config['2150_218f'][] = array('upper' => 8558, 'status' => 'C', 'lower' => array(8574)); /* ROMAN NUMERAL FIVE HUNDRED */ $config['2150_218f'][] = array('upper' => 8559, 'status' => 'C', 'lower' => array(8575)); /* ROMAN NUMERAL ONE THOUSAND */ $config['2150_218f'][] = array('upper' => 8579, 'status' => 'C', 'lower' => array(8580)); /* ROMAN NUMERAL REVERSED ONE HUNDRED */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/2460_24ff.php000066400000000000000000000121001265552240500236030ustar00rootroot00000000000000 9398, 'status' => 'C', 'lower' => array(9424)); /* CIRCLED LATIN CAPITAL LETTER A */ $config['2460_24ff'][] = array('upper' => 9399, 'status' => 'C', 'lower' => array(9425)); /* CIRCLED LATIN CAPITAL LETTER B */ $config['2460_24ff'][] = array('upper' => 9400, 'status' => 'C', 'lower' => array(9426)); /* CIRCLED LATIN CAPITAL LETTER C */ $config['2460_24ff'][] = array('upper' => 9401, 'status' => 'C', 'lower' => array(9427)); /* CIRCLED LATIN CAPITAL LETTER D */ $config['2460_24ff'][] = array('upper' => 9402, 'status' => 'C', 'lower' => array(9428)); /* CIRCLED LATIN CAPITAL LETTER E */ $config['2460_24ff'][] = array('upper' => 9403, 'status' => 'C', 'lower' => array(9429)); /* CIRCLED LATIN CAPITAL LETTER F */ $config['2460_24ff'][] = array('upper' => 9404, 'status' => 'C', 'lower' => array(9430)); /* CIRCLED LATIN CAPITAL LETTER G */ $config['2460_24ff'][] = array('upper' => 9405, 'status' => 'C', 'lower' => array(9431)); /* CIRCLED LATIN CAPITAL LETTER H */ $config['2460_24ff'][] = array('upper' => 9406, 'status' => 'C', 'lower' => array(9432)); /* CIRCLED LATIN CAPITAL LETTER I */ $config['2460_24ff'][] = array('upper' => 9407, 'status' => 'C', 'lower' => array(9433)); /* CIRCLED LATIN CAPITAL LETTER J */ $config['2460_24ff'][] = array('upper' => 9408, 'status' => 'C', 'lower' => array(9434)); /* CIRCLED LATIN CAPITAL LETTER K */ $config['2460_24ff'][] = array('upper' => 9409, 'status' => 'C', 'lower' => array(9435)); /* CIRCLED LATIN CAPITAL LETTER L */ $config['2460_24ff'][] = array('upper' => 9410, 'status' => 'C', 'lower' => array(9436)); /* CIRCLED LATIN CAPITAL LETTER M */ $config['2460_24ff'][] = array('upper' => 9411, 'status' => 'C', 'lower' => array(9437)); /* CIRCLED LATIN CAPITAL LETTER N */ $config['2460_24ff'][] = array('upper' => 9412, 'status' => 'C', 'lower' => array(9438)); /* CIRCLED LATIN CAPITAL LETTER O */ $config['2460_24ff'][] = array('upper' => 9413, 'status' => 'C', 'lower' => array(9439)); /* CIRCLED LATIN CAPITAL LETTER P */ $config['2460_24ff'][] = array('upper' => 9414, 'status' => 'C', 'lower' => array(9440)); /* CIRCLED LATIN CAPITAL LETTER Q */ $config['2460_24ff'][] = array('upper' => 9415, 'status' => 'C', 'lower' => array(9441)); /* CIRCLED LATIN CAPITAL LETTER R */ $config['2460_24ff'][] = array('upper' => 9416, 'status' => 'C', 'lower' => array(9442)); /* CIRCLED LATIN CAPITAL LETTER S */ $config['2460_24ff'][] = array('upper' => 9417, 'status' => 'C', 'lower' => array(9443)); /* CIRCLED LATIN CAPITAL LETTER T */ $config['2460_24ff'][] = array('upper' => 9418, 'status' => 'C', 'lower' => array(9444)); /* CIRCLED LATIN CAPITAL LETTER U */ $config['2460_24ff'][] = array('upper' => 9419, 'status' => 'C', 'lower' => array(9445)); /* CIRCLED LATIN CAPITAL LETTER V */ $config['2460_24ff'][] = array('upper' => 9420, 'status' => 'C', 'lower' => array(9446)); /* CIRCLED LATIN CAPITAL LETTER W */ $config['2460_24ff'][] = array('upper' => 9421, 'status' => 'C', 'lower' => array(9447)); /* CIRCLED LATIN CAPITAL LETTER X */ $config['2460_24ff'][] = array('upper' => 9422, 'status' => 'C', 'lower' => array(9448)); /* CIRCLED LATIN CAPITAL LETTER Y */ $config['2460_24ff'][] = array('upper' => 9423, 'status' => 'C', 'lower' => array(9449)); /* CIRCLED LATIN CAPITAL LETTER Z */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/2c00_2c5f.php000066400000000000000000000175561265552240500236760ustar00rootroot00000000000000 11264, 'status' => 'C', 'lower' => array(11312)); /* GLAGOLITIC CAPITAL LETTER AZU */ $config['2c00_2c5f'][] = array('upper' => 11265, 'status' => 'C', 'lower' => array(11313)); /* GLAGOLITIC CAPITAL LETTER BUKY */ $config['2c00_2c5f'][] = array('upper' => 11266, 'status' => 'C', 'lower' => array(11314)); /* GLAGOLITIC CAPITAL LETTER VEDE */ $config['2c00_2c5f'][] = array('upper' => 11267, 'status' => 'C', 'lower' => array(11315)); /* GLAGOLITIC CAPITAL LETTER GLAGOLI */ $config['2c00_2c5f'][] = array('upper' => 11268, 'status' => 'C', 'lower' => array(11316)); /* GLAGOLITIC CAPITAL LETTER DOBRO */ $config['2c00_2c5f'][] = array('upper' => 11269, 'status' => 'C', 'lower' => array(11317)); /* GLAGOLITIC CAPITAL LETTER YESTU */ $config['2c00_2c5f'][] = array('upper' => 11270, 'status' => 'C', 'lower' => array(11318)); /* GLAGOLITIC CAPITAL LETTER ZHIVETE */ $config['2c00_2c5f'][] = array('upper' => 11271, 'status' => 'C', 'lower' => array(11319)); /* GLAGOLITIC CAPITAL LETTER DZELO */ $config['2c00_2c5f'][] = array('upper' => 11272, 'status' => 'C', 'lower' => array(11320)); /* GLAGOLITIC CAPITAL LETTER ZEMLJA */ $config['2c00_2c5f'][] = array('upper' => 11273, 'status' => 'C', 'lower' => array(11321)); /* GLAGOLITIC CAPITAL LETTER IZHE */ $config['2c00_2c5f'][] = array('upper' => 11274, 'status' => 'C', 'lower' => array(11322)); /* GLAGOLITIC CAPITAL LETTER INITIAL IZHE */ $config['2c00_2c5f'][] = array('upper' => 11275, 'status' => 'C', 'lower' => array(11323)); /* GLAGOLITIC CAPITAL LETTER I */ $config['2c00_2c5f'][] = array('upper' => 11276, 'status' => 'C', 'lower' => array(11324)); /* GLAGOLITIC CAPITAL LETTER DJERVI */ $config['2c00_2c5f'][] = array('upper' => 11277, 'status' => 'C', 'lower' => array(11325)); /* GLAGOLITIC CAPITAL LETTER KAKO */ $config['2c00_2c5f'][] = array('upper' => 11278, 'status' => 'C', 'lower' => array(11326)); /* GLAGOLITIC CAPITAL LETTER LJUDIJE */ $config['2c00_2c5f'][] = array('upper' => 11279, 'status' => 'C', 'lower' => array(11327)); /* GLAGOLITIC CAPITAL LETTER MYSLITE */ $config['2c00_2c5f'][] = array('upper' => 11280, 'status' => 'C', 'lower' => array(11328)); /* GLAGOLITIC CAPITAL LETTER NASHI */ $config['2c00_2c5f'][] = array('upper' => 11281, 'status' => 'C', 'lower' => array(11329)); /* GLAGOLITIC CAPITAL LETTER ONU */ $config['2c00_2c5f'][] = array('upper' => 11282, 'status' => 'C', 'lower' => array(11330)); /* GLAGOLITIC CAPITAL LETTER POKOJI */ $config['2c00_2c5f'][] = array('upper' => 11283, 'status' => 'C', 'lower' => array(11331)); /* GLAGOLITIC CAPITAL LETTER RITSI */ $config['2c00_2c5f'][] = array('upper' => 11284, 'status' => 'C', 'lower' => array(11332)); /* GLAGOLITIC CAPITAL LETTER SLOVO */ $config['2c00_2c5f'][] = array('upper' => 11285, 'status' => 'C', 'lower' => array(11333)); /* GLAGOLITIC CAPITAL LETTER TVRIDO */ $config['2c00_2c5f'][] = array('upper' => 11286, 'status' => 'C', 'lower' => array(11334)); /* GLAGOLITIC CAPITAL LETTER UKU */ $config['2c00_2c5f'][] = array('upper' => 11287, 'status' => 'C', 'lower' => array(11335)); /* GLAGOLITIC CAPITAL LETTER FRITU */ $config['2c00_2c5f'][] = array('upper' => 11288, 'status' => 'C', 'lower' => array(11336)); /* GLAGOLITIC CAPITAL LETTER HERU */ $config['2c00_2c5f'][] = array('upper' => 11289, 'status' => 'C', 'lower' => array(11337)); /* GLAGOLITIC CAPITAL LETTER OTU */ $config['2c00_2c5f'][] = array('upper' => 11290, 'status' => 'C', 'lower' => array(11338)); /* GLAGOLITIC CAPITAL LETTER PE */ $config['2c00_2c5f'][] = array('upper' => 11291, 'status' => 'C', 'lower' => array(11339)); /* GLAGOLITIC CAPITAL LETTER SHTA */ $config['2c00_2c5f'][] = array('upper' => 11292, 'status' => 'C', 'lower' => array(11340)); /* GLAGOLITIC CAPITAL LETTER TSI */ $config['2c00_2c5f'][] = array('upper' => 11293, 'status' => 'C', 'lower' => array(11341)); /* GLAGOLITIC CAPITAL LETTER CHRIVI */ $config['2c00_2c5f'][] = array('upper' => 11294, 'status' => 'C', 'lower' => array(11342)); /* GLAGOLITIC CAPITAL LETTER SHA */ $config['2c00_2c5f'][] = array('upper' => 11295, 'status' => 'C', 'lower' => array(11343)); /* GLAGOLITIC CAPITAL LETTER YERU */ $config['2c00_2c5f'][] = array('upper' => 11296, 'status' => 'C', 'lower' => array(11344)); /* GLAGOLITIC CAPITAL LETTER YERI */ $config['2c00_2c5f'][] = array('upper' => 11297, 'status' => 'C', 'lower' => array(11345)); /* GLAGOLITIC CAPITAL LETTER YATI */ $config['2c00_2c5f'][] = array('upper' => 11298, 'status' => 'C', 'lower' => array(11346)); /* GLAGOLITIC CAPITAL LETTER SPIDERY HA */ $config['2c00_2c5f'][] = array('upper' => 11299, 'status' => 'C', 'lower' => array(11347)); /* GLAGOLITIC CAPITAL LETTER YU */ $config['2c00_2c5f'][] = array('upper' => 11300, 'status' => 'C', 'lower' => array(11348)); /* GLAGOLITIC CAPITAL LETTER SMALL YUS */ $config['2c00_2c5f'][] = array('upper' => 11301, 'status' => 'C', 'lower' => array(11349)); /* GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL */ $config['2c00_2c5f'][] = array('upper' => 11302, 'status' => 'C', 'lower' => array(11350)); /* GLAGOLITIC CAPITAL LETTER YO */ $config['2c00_2c5f'][] = array('upper' => 11303, 'status' => 'C', 'lower' => array(11351)); /* GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS */ $config['2c00_2c5f'][] = array('upper' => 11304, 'status' => 'C', 'lower' => array(11352)); /* GLAGOLITIC CAPITAL LETTER BIG YUS */ $config['2c00_2c5f'][] = array('upper' => 11305, 'status' => 'C', 'lower' => array(11353)); /* GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS */ $config['2c00_2c5f'][] = array('upper' => 11306, 'status' => 'C', 'lower' => array(11354)); /* GLAGOLITIC CAPITAL LETTER FITA */ $config['2c00_2c5f'][] = array('upper' => 11307, 'status' => 'C', 'lower' => array(11355)); /* GLAGOLITIC CAPITAL LETTER IZHITSA */ $config['2c00_2c5f'][] = array('upper' => 11308, 'status' => 'C', 'lower' => array(11356)); /* GLAGOLITIC CAPITAL LETTER SHTAPIC */ $config['2c00_2c5f'][] = array('upper' => 11309, 'status' => 'C', 'lower' => array(11357)); /* GLAGOLITIC CAPITAL LETTER TROKUTASTI A */ $config['2c00_2c5f'][] = array('upper' => 11310, 'status' => 'C', 'lower' => array(11358)); /* GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/2c60_2c7f.php000066400000000000000000000056071265552240500237000ustar00rootroot00000000000000 11360, 'status' => 'C', 'lower' => array(11361)); /* LATIN CAPITAL LETTER L WITH DOUBLE BAR */ $config['2c60_2c7f'][] = array('upper' => 11362, 'status' => 'C', 'lower' => array(619)); /* LATIN CAPITAL LETTER L WITH MIDDLE TILDE */ $config['2c60_2c7f'][] = array('upper' => 11363, 'status' => 'C', 'lower' => array(7549)); /* LATIN CAPITAL LETTER P WITH STROKE */ $config['2c60_2c7f'][] = array('upper' => 11364, 'status' => 'C', 'lower' => array(637)); /* LATIN CAPITAL LETTER R WITH TAIL */ $config['2c60_2c7f'][] = array('upper' => 11367, 'status' => 'C', 'lower' => array(11368)); /* LATIN CAPITAL LETTER H WITH DESCENDER */ $config['2c60_2c7f'][] = array('upper' => 11369, 'status' => 'C', 'lower' => array(11370)); /* LATIN CAPITAL LETTER K WITH DESCENDER */ $config['2c60_2c7f'][] = array('upper' => 11371, 'status' => 'C', 'lower' => array(11372)); /* LATIN CAPITAL LETTER Z WITH DESCENDER */ $config['2c60_2c7f'][] = array('upper' => 11381, 'status' => 'C', 'lower' => array(11382)); /* LATIN CAPITAL LETTER HALF H */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/2c80_2cff.php000066400000000000000000000202521265552240500237520ustar00rootroot00000000000000 11392, 'status' => 'C', 'lower' => array(11393)); /* COPTIC CAPITAL LETTER ALFA */ $config['2c80_2cff'][] = array('upper' => 11394, 'status' => 'C', 'lower' => array(11395)); /* COPTIC CAPITAL LETTER VIDA */ $config['2c80_2cff'][] = array('upper' => 11396, 'status' => 'C', 'lower' => array(11397)); /* COPTIC CAPITAL LETTER GAMMA */ $config['2c80_2cff'][] = array('upper' => 11398, 'status' => 'C', 'lower' => array(11399)); /* COPTIC CAPITAL LETTER DALDA */ $config['2c80_2cff'][] = array('upper' => 11400, 'status' => 'C', 'lower' => array(11401)); /* COPTIC CAPITAL LETTER EIE */ $config['2c80_2cff'][] = array('upper' => 11402, 'status' => 'C', 'lower' => array(11403)); /* COPTIC CAPITAL LETTER SOU */ $config['2c80_2cff'][] = array('upper' => 11404, 'status' => 'C', 'lower' => array(11405)); /* COPTIC CAPITAL LETTER ZATA */ $config['2c80_2cff'][] = array('upper' => 11406, 'status' => 'C', 'lower' => array(11407)); /* COPTIC CAPITAL LETTER HATE */ $config['2c80_2cff'][] = array('upper' => 11408, 'status' => 'C', 'lower' => array(11409)); /* COPTIC CAPITAL LETTER THETHE */ $config['2c80_2cff'][] = array('upper' => 11410, 'status' => 'C', 'lower' => array(11411)); /* COPTIC CAPITAL LETTER IAUDA */ $config['2c80_2cff'][] = array('upper' => 11412, 'status' => 'C', 'lower' => array(11413)); /* COPTIC CAPITAL LETTER KAPA */ $config['2c80_2cff'][] = array('upper' => 11414, 'status' => 'C', 'lower' => array(11415)); /* COPTIC CAPITAL LETTER LAULA */ $config['2c80_2cff'][] = array('upper' => 11416, 'status' => 'C', 'lower' => array(11417)); /* COPTIC CAPITAL LETTER MI */ $config['2c80_2cff'][] = array('upper' => 11418, 'status' => 'C', 'lower' => array(11419)); /* COPTIC CAPITAL LETTER NI */ $config['2c80_2cff'][] = array('upper' => 11420, 'status' => 'C', 'lower' => array(11421)); /* COPTIC CAPITAL LETTER KSI */ $config['2c80_2cff'][] = array('upper' => 11422, 'status' => 'C', 'lower' => array(11423)); /* COPTIC CAPITAL LETTER O */ $config['2c80_2cff'][] = array('upper' => 11424, 'status' => 'C', 'lower' => array(11425)); /* COPTIC CAPITAL LETTER PI */ $config['2c80_2cff'][] = array('upper' => 11426, 'status' => 'C', 'lower' => array(11427)); /* COPTIC CAPITAL LETTER RO */ $config['2c80_2cff'][] = array('upper' => 11428, 'status' => 'C', 'lower' => array(11429)); /* COPTIC CAPITAL LETTER SIMA */ $config['2c80_2cff'][] = array('upper' => 11430, 'status' => 'C', 'lower' => array(11431)); /* COPTIC CAPITAL LETTER TAU */ $config['2c80_2cff'][] = array('upper' => 11432, 'status' => 'C', 'lower' => array(11433)); /* COPTIC CAPITAL LETTER UA */ $config['2c80_2cff'][] = array('upper' => 11434, 'status' => 'C', 'lower' => array(11435)); /* COPTIC CAPITAL LETTER FI */ $config['2c80_2cff'][] = array('upper' => 11436, 'status' => 'C', 'lower' => array(11437)); /* COPTIC CAPITAL LETTER KHI */ $config['2c80_2cff'][] = array('upper' => 11438, 'status' => 'C', 'lower' => array(11439)); /* COPTIC CAPITAL LETTER PSI */ $config['2c80_2cff'][] = array('upper' => 11440, 'status' => 'C', 'lower' => array(11441)); /* COPTIC CAPITAL LETTER OOU */ $config['2c80_2cff'][] = array('upper' => 11442, 'status' => 'C', 'lower' => array(11443)); /* COPTIC CAPITAL LETTER DIALECT-P ALEF */ $config['2c80_2cff'][] = array('upper' => 11444, 'status' => 'C', 'lower' => array(11445)); /* COPTIC CAPITAL LETTER OLD COPTIC AIN */ $config['2c80_2cff'][] = array('upper' => 11446, 'status' => 'C', 'lower' => array(11447)); /* COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE */ $config['2c80_2cff'][] = array('upper' => 11448, 'status' => 'C', 'lower' => array(11449)); /* COPTIC CAPITAL LETTER DIALECT-P KAPA */ $config['2c80_2cff'][] = array('upper' => 11450, 'status' => 'C', 'lower' => array(11451)); /* COPTIC CAPITAL LETTER DIALECT-P NI */ $config['2c80_2cff'][] = array('upper' => 11452, 'status' => 'C', 'lower' => array(11453)); /* COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI */ $config['2c80_2cff'][] = array('upper' => 11454, 'status' => 'C', 'lower' => array(11455)); /* COPTIC CAPITAL LETTER OLD COPTIC OOU */ $config['2c80_2cff'][] = array('upper' => 11456, 'status' => 'C', 'lower' => array(11457)); /* COPTIC CAPITAL LETTER SAMPI */ $config['2c80_2cff'][] = array('upper' => 11458, 'status' => 'C', 'lower' => array(11459)); /* COPTIC CAPITAL LETTER CROSSED SHEI */ $config['2c80_2cff'][] = array('upper' => 11460, 'status' => 'C', 'lower' => array(11461)); /* COPTIC CAPITAL LETTER OLD COPTIC SHEI */ $config['2c80_2cff'][] = array('upper' => 11462, 'status' => 'C', 'lower' => array(11463)); /* COPTIC CAPITAL LETTER OLD COPTIC ESH */ $config['2c80_2cff'][] = array('upper' => 11464, 'status' => 'C', 'lower' => array(11465)); /* COPTIC CAPITAL LETTER AKHMIMIC KHEI */ $config['2c80_2cff'][] = array('upper' => 11466, 'status' => 'C', 'lower' => array(11467)); /* COPTIC CAPITAL LETTER DIALECT-P HORI */ $config['2c80_2cff'][] = array('upper' => 11468, 'status' => 'C', 'lower' => array(11469)); /* COPTIC CAPITAL LETTER OLD COPTIC HORI */ $config['2c80_2cff'][] = array('upper' => 11470, 'status' => 'C', 'lower' => array(11471)); /* COPTIC CAPITAL LETTER OLD COPTIC HA */ $config['2c80_2cff'][] = array('upper' => 11472, 'status' => 'C', 'lower' => array(11473)); /* COPTIC CAPITAL LETTER L-SHAPED HA */ $config['2c80_2cff'][] = array('upper' => 11474, 'status' => 'C', 'lower' => array(11475)); /* COPTIC CAPITAL LETTER OLD COPTIC HEI */ $config['2c80_2cff'][] = array('upper' => 11476, 'status' => 'C', 'lower' => array(11477)); /* COPTIC CAPITAL LETTER OLD COPTIC HAT */ $config['2c80_2cff'][] = array('upper' => 11478, 'status' => 'C', 'lower' => array(11479)); /* COPTIC CAPITAL LETTER OLD COPTIC GANGIA */ $config['2c80_2cff'][] = array('upper' => 11480, 'status' => 'C', 'lower' => array(11481)); /* COPTIC CAPITAL LETTER OLD COPTIC DJA */ $config['2c80_2cff'][] = array('upper' => 11482, 'status' => 'C', 'lower' => array(11483)); /* COPTIC CAPITAL LETTER OLD COPTIC SHIMA */ $config['2c80_2cff'][] = array('upper' => 11484, 'status' => 'C', 'lower' => array(11485)); /* COPTIC CAPITAL LETTER OLD NUBIAN SHIMA */ $config['2c80_2cff'][] = array('upper' => 11486, 'status' => 'C', 'lower' => array(11487)); /* COPTIC CAPITAL LETTER OLD NUBIAN NGI */ $config['2c80_2cff'][] = array('upper' => 11488, 'status' => 'C', 'lower' => array(11489)); /* COPTIC CAPITAL LETTER OLD NUBIAN NYI */ $config['2c80_2cff'][] = array('upper' => 11490, 'status' => 'C', 'lower' => array(11491)); /* COPTIC CAPITAL LETTER OLD NUBIAN WAU */ cakephp-2.8.0/lib/Cake/Config/unicode/casefolding/ff00_ffef.php000066400000000000000000000122501265552240500241160ustar00rootroot00000000000000 65313, 'status' => 'C', 'lower' => array(65345)); /* FULLWIDTH LATIN CAPITAL LETTER A */ $config['ff00_ffef'][] = array('upper' => 65314, 'status' => 'C', 'lower' => array(65346)); /* FULLWIDTH LATIN CAPITAL LETTER B */ $config['ff00_ffef'][] = array('upper' => 65315, 'status' => 'C', 'lower' => array(65347)); /* FULLWIDTH LATIN CAPITAL LETTER C */ $config['ff00_ffef'][] = array('upper' => 65316, 'status' => 'C', 'lower' => array(65348)); /* FULLWIDTH LATIN CAPITAL LETTER D */ $config['ff00_ffef'][] = array('upper' => 65317, 'status' => 'C', 'lower' => array(65349)); /* FULLWIDTH LATIN CAPITAL LETTER E */ $config['ff00_ffef'][] = array('upper' => 65318, 'status' => 'C', 'lower' => array(65350)); /* FULLWIDTH LATIN CAPITAL LETTER F */ $config['ff00_ffef'][] = array('upper' => 65319, 'status' => 'C', 'lower' => array(65351)); /* FULLWIDTH LATIN CAPITAL LETTER G */ $config['ff00_ffef'][] = array('upper' => 65320, 'status' => 'C', 'lower' => array(65352)); /* FULLWIDTH LATIN CAPITAL LETTER H */ $config['ff00_ffef'][] = array('upper' => 65321, 'status' => 'C', 'lower' => array(65353)); /* FULLWIDTH LATIN CAPITAL LETTER I */ $config['ff00_ffef'][] = array('upper' => 65322, 'status' => 'C', 'lower' => array(65354)); /* FULLWIDTH LATIN CAPITAL LETTER J */ $config['ff00_ffef'][] = array('upper' => 65323, 'status' => 'C', 'lower' => array(65355)); /* FULLWIDTH LATIN CAPITAL LETTER K */ $config['ff00_ffef'][] = array('upper' => 65324, 'status' => 'C', 'lower' => array(65356)); /* FULLWIDTH LATIN CAPITAL LETTER L */ $config['ff00_ffef'][] = array('upper' => 65325, 'status' => 'C', 'lower' => array(65357)); /* FULLWIDTH LATIN CAPITAL LETTER M */ $config['ff00_ffef'][] = array('upper' => 65326, 'status' => 'C', 'lower' => array(65358)); /* FULLWIDTH LATIN CAPITAL LETTER N */ $config['ff00_ffef'][] = array('upper' => 65327, 'status' => 'C', 'lower' => array(65359)); /* FULLWIDTH LATIN CAPITAL LETTER O */ $config['ff00_ffef'][] = array('upper' => 65328, 'status' => 'C', 'lower' => array(65360)); /* FULLWIDTH LATIN CAPITAL LETTER P */ $config['ff00_ffef'][] = array('upper' => 65329, 'status' => 'C', 'lower' => array(65361)); /* FULLWIDTH LATIN CAPITAL LETTER Q */ $config['ff00_ffef'][] = array('upper' => 65330, 'status' => 'C', 'lower' => array(65362)); /* FULLWIDTH LATIN CAPITAL LETTER R */ $config['ff00_ffef'][] = array('upper' => 65331, 'status' => 'C', 'lower' => array(65363)); /* FULLWIDTH LATIN CAPITAL LETTER S */ $config['ff00_ffef'][] = array('upper' => 65332, 'status' => 'C', 'lower' => array(65364)); /* FULLWIDTH LATIN CAPITAL LETTER T */ $config['ff00_ffef'][] = array('upper' => 65333, 'status' => 'C', 'lower' => array(65365)); /* FULLWIDTH LATIN CAPITAL LETTER U */ $config['ff00_ffef'][] = array('upper' => 65334, 'status' => 'C', 'lower' => array(65366)); /* FULLWIDTH LATIN CAPITAL LETTER V */ $config['ff00_ffef'][] = array('upper' => 65335, 'status' => 'C', 'lower' => array(65367)); /* FULLWIDTH LATIN CAPITAL LETTER W */ $config['ff00_ffef'][] = array('upper' => 65336, 'status' => 'C', 'lower' => array(65368)); /* FULLWIDTH LATIN CAPITAL LETTER X */ $config['ff00_ffef'][] = array('upper' => 65337, 'status' => 'C', 'lower' => array(65369)); /* FULLWIDTH LATIN CAPITAL LETTER Y */ $config['ff00_ffef'][] = array('upper' => 65338, 'status' => 'C', 'lower' => array(65370)); /* FULLWIDTH LATIN CAPITAL LETTER Z */ cakephp-2.8.0/lib/Cake/Configure/000077500000000000000000000000001265552240500164745ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Configure/ConfigReaderInterface.php000066400000000000000000000025201265552240500233550ustar00rootroot00000000000000 array('password' => 'secret'))` * * You can nest properties as deeply as needed using `.`'s. In addition to using `.` you * can use standard ini section notation to create nested structures: * * ``` * [section] * key = value * ``` * * Once loaded into Configure, the above would be accessed using: * * `Configure::read('section.key'); * * You can combine `.` separated values with sections to create more deeply * nested structures. * * IniReader also manipulates how the special ini values of * 'yes', 'no', 'on', 'off', 'null' are handled. These values will be * converted to their boolean equivalents. * * @package Cake.Configure * @see http://php.net/parse_ini_file */ class IniReader implements ConfigReaderInterface { /** * The path to read ini files from. * * @var array */ protected $_path; /** * The section to read, if null all sections will be read. * * @var string */ protected $_section; /** * Build and construct a new ini file parser. The parser can be used to read * ini files that are on the filesystem. * * @param string $path Path to load ini config files from. Defaults to APP . 'Config' . DS * @param string $section Only get one section, leave null to parse and fetch * all sections in the ini file. */ public function __construct($path = null, $section = null) { if (!$path) { $path = APP . 'Config' . DS; } $this->_path = $path; $this->_section = $section; } /** * Read an ini file and return the results as an array. * * For backwards compatibility, acl.ini.php will be treated specially until 3.0. * * @param string $key The identifier to read from. If the key has a . it will be treated * as a plugin prefix. The chosen file must be on the reader's path. * @return array Parsed configuration values. * @throws ConfigureException when files don't exist. * Or when files contain '..' as this could lead to abusive reads. */ public function read($key) { if (strpos($key, '..') !== false) { throw new ConfigureException(__d('cake_dev', 'Cannot load configuration files with ../ in them.')); } $file = $this->_getFilePath($key); if (!is_file(realpath($file))) { throw new ConfigureException(__d('cake_dev', 'Could not load configuration file: %s', $file)); } $contents = parse_ini_file($file, true); if (!empty($this->_section) && isset($contents[$this->_section])) { $values = $this->_parseNestedValues($contents[$this->_section]); } else { $values = array(); foreach ($contents as $section => $attribs) { if (is_array($attribs)) { $values[$section] = $this->_parseNestedValues($attribs); } else { $parse = $this->_parseNestedValues(array($attribs)); $values[$section] = array_shift($parse); } } } return $values; } /** * parses nested values out of keys. * * @param array $values Values to be exploded. * @return array Array of values exploded */ protected function _parseNestedValues($values) { foreach ($values as $key => $value) { if ($value === '1') { $value = true; } if ($value === '') { $value = false; } unset($values[$key]); if (strpos($key, '.') !== false) { $values = Hash::insert($values, $key, $value); } else { $values[$key] = $value; } } return $values; } /** * Dumps the state of Configure data into an ini formatted string. * * @param string $key The identifier to write to. If the key has a . it will be treated * as a plugin prefix. * @param array $data The data to convert to ini file. * @return int Bytes saved. */ public function dump($key, $data) { $result = array(); foreach ($data as $k => $value) { $isSection = false; if ($k[0] !== '[') { $result[] = "[$k]"; $isSection = true; } if (is_array($value)) { $kValues = Hash::flatten($value, '.'); foreach ($kValues as $k2 => $v) { $result[] = "$k2 = " . $this->_value($v); } } if ($isSection) { $result[] = ''; } } $contents = trim(implode("\n", $result)); $filename = $this->_getFilePath($key); return file_put_contents($filename, $contents); } /** * Converts a value into the ini equivalent * * @param mixed $val Value to export. * @return string String value for ini file. */ protected function _value($val) { if ($val === null) { return 'null'; } if ($val === true) { return 'true'; } if ($val === false) { return 'false'; } return (string)$val; } /** * Get file path * * @param string $key The identifier to write to. If the key has a . it will be treated * as a plugin prefix. * @return string Full file path */ protected function _getFilePath($key) { if (substr($key, -8) === '.ini.php') { $key = substr($key, 0, -8); list($plugin, $key) = pluginSplit($key); $key .= '.ini.php'; } else { if (substr($key, -4) === '.ini') { $key = substr($key, 0, -4); } list($plugin, $key) = pluginSplit($key); $key .= '.ini'; } if ($plugin) { $file = CakePlugin::path($plugin) . 'Config' . DS . $key; } else { $file = $this->_path . $key; } return $file; } } cakephp-2.8.0/lib/Cake/Configure/PhpReader.php000066400000000000000000000066261265552240500210710ustar00rootroot00000000000000_path = $path; } /** * Read a config file and return its contents. * * Files with `.` in the name will be treated as values in plugins. Instead of reading from * the initialized path, plugin keys will be located using CakePlugin::path(). * * @param string $key The identifier to read from. If the key has a . it will be treated * as a plugin prefix. * @return array Parsed configuration values. * @throws ConfigureException when files don't exist or they don't contain `$config`. * Or when files contain '..' as this could lead to abusive reads. */ public function read($key) { if (strpos($key, '..') !== false) { throw new ConfigureException(__d('cake_dev', 'Cannot load configuration files with ../ in them.')); } $file = $this->_getFilePath($key); if (!is_file(realpath($file))) { throw new ConfigureException(__d('cake_dev', 'Could not load configuration file: %s', $file)); } include $file; if (!isset($config)) { throw new ConfigureException(__d('cake_dev', 'No variable %s found in %s', '$config', $file)); } return $config; } /** * Converts the provided $data into a string of PHP code that can * be used saved into a file and loaded later. * * @param string $key The identifier to write to. If the key has a . it will be treated * as a plugin prefix. * @param array $data Data to dump. * @return int Bytes saved. */ public function dump($key, $data) { $contents = '_getFilePath($key); return file_put_contents($filename, $contents); } /** * Get file path * * @param string $key The identifier to write to. If the key has a . it will be treated * as a plugin prefix. * @return string Full file path */ protected function _getFilePath($key) { if (substr($key, -4) === '.php') { $key = substr($key, 0, -4); } list($plugin, $key) = pluginSplit($key); $key .= '.php'; if ($plugin) { $file = CakePlugin::path($plugin) . 'Config' . DS . $key; } else { $file = $this->_path . $key; } return $file; } } cakephp-2.8.0/lib/Cake/Console/000077500000000000000000000000001265552240500161555ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Command/000077500000000000000000000000001265552240500175335ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Command/AclShell.php000066400000000000000000000461021265552240500217360ustar00rootroot00000000000000params['connection'])) { $this->connection = $this->params['connection']; } $class = Configure::read('Acl.classname'); list($plugin, $class) = pluginSplit($class, true); App::uses($class, $plugin . 'Controller/Component/Acl'); if (!in_array($class, array('DbAcl', 'DB_ACL')) && !is_subclass_of($class, 'DbAcl')) { $out = "--------------------------------------------------\n"; $out .= __d('cake_console', 'Error: Your current CakePHP configuration is set to an ACL implementation other than DB.') . "\n"; $out .= __d('cake_console', 'Please change your core config to reflect your decision to use DbAcl before attempting to use this script') . "\n"; $out .= "--------------------------------------------------\n"; $out .= __d('cake_console', 'Current ACL Classname: %s', $class) . "\n"; $out .= "--------------------------------------------------\n"; $this->err($out); return $this->_stop(); } if ($this->command) { if (!config('database')) { $this->out(__d('cake_console', 'Your database configuration was not found. Take a moment to create one.')); $this->args = null; return $this->DbConfig->execute(); } require_once APP . 'Config' . DS . 'database.php'; if (!in_array($this->command, array('initdb'))) { $collection = new ComponentCollection(); $this->Acl = new AclComponent($collection); $controller = new Controller(); $this->Acl->startup($controller); } } } /** * Override main() for help message hook * * @return void */ public function main() { $this->out($this->OptionParser->help()); } /** * Creates an ARO/ACO node * * @return void */ public function create() { extract($this->_dataVars()); $class = ucfirst($this->args[0]); $parent = $this->parseIdentifier($this->args[1]); if (!empty($parent) && $parent !== '/' && $parent !== 'root') { $parent = $this->_getNodeId($class, $parent); } else { $parent = null; } $data = $this->parseIdentifier($this->args[2]); if (is_string($data) && $data !== '/') { $data = array('alias' => $data); } elseif (is_string($data)) { $this->error(__d('cake_console', '/ can not be used as an alias!') . __d('cake_console', " / is the root, please supply a sub alias")); } $data['parent_id'] = $parent; $this->Acl->{$class}->create(); if ($this->Acl->{$class}->save($data)) { $this->out(__d('cake_console', "New %s '%s' created.", $class, $this->args[2]), 2); } else { $this->err(__d('cake_console', "There was a problem creating a new %s '%s'.", $class, $this->args[2])); } } /** * Delete an ARO/ACO node. Note there may be (as a result of poor configuration) * multiple records with the same logical identifier. All are deleted. * * @return void */ public function delete() { extract($this->_dataVars()); $identifier = $this->parseIdentifier($this->args[1]); if (is_string($identifier)) { $identifier = array('alias' => $identifier); } if ($this->Acl->{$class}->find('all', array('conditions' => $identifier))) { if (!$this->Acl->{$class}->deleteAll($identifier)) { $this->error(__d('cake_console', 'Node Not Deleted. ') . __d('cake_console', 'There was an error deleting the %s.', $class) . "\n"); } $this->out(__d('cake_console', '%s deleted.', $class), 2); } else { $this->error(__d('cake_console', 'Node Not Deleted. ') . __d('cake_console', 'There was an error deleting the %s. Node does not exist.', $class) . "\n"); } } /** * Set parent for an ARO/ACO node. * * @return void */ public function setParent() { extract($this->_dataVars()); $target = $this->parseIdentifier($this->args[1]); $parent = $this->parseIdentifier($this->args[2]); $data = array( $class => array( 'id' => $this->_getNodeId($class, $target), 'parent_id' => $this->_getNodeId($class, $parent) ) ); $this->Acl->{$class}->create(); if (!$this->Acl->{$class}->save($data)) { $this->out(__d('cake_console', 'Error in setting new parent. Please make sure the parent node exists, and is not a descendant of the node specified.')); } else { $this->out(__d('cake_console', 'Node parent set to %s', $this->args[2]) . "\n"); } } /** * Get path to specified ARO/ACO node. * * @return void */ public function getPath() { extract($this->_dataVars()); $identifier = $this->parseIdentifier($this->args[1]); $id = $this->_getNodeId($class, $identifier); $nodes = $this->Acl->{$class}->getPath($id); if (empty($nodes)) { $this->error( __d('cake_console', "Supplied Node '%s' not found", $this->args[1]), __d('cake_console', 'No tree returned.') ); } $this->out(__d('cake_console', 'Path:')); $this->hr(); for ($i = 0, $len = count($nodes); $i < $len; $i++) { $this->_outputNode($class, $nodes[$i], $i); } } /** * Outputs a single node, Either using the alias or Model.key * * @param string $class Class name that is being used. * @param array $node Array of node information. * @param int $indent indent level. * @return void */ protected function _outputNode($class, $node, $indent) { $indent = str_repeat(' ', $indent); $data = $node[$class]; if ($data['alias']) { $this->out($indent . "[" . $data['id'] . "] " . $data['alias']); } else { $this->out($indent . "[" . $data['id'] . "] " . $data['model'] . '.' . $data['foreign_key']); } } /** * Check permission for a given ARO to a given ACO. * * @return void */ public function check() { extract($this->_getParams()); if ($this->Acl->check($aro, $aco, $action)) { $this->out(__d('cake_console', '%s is allowed.', $aroName)); } else { $this->out(__d('cake_console', '%s is not allowed.', $aroName)); } } /** * Grant permission for a given ARO to a given ACO. * * @return void */ public function grant() { extract($this->_getParams()); if ($this->Acl->allow($aro, $aco, $action)) { $this->out(__d('cake_console', 'Permission granted.')); } else { $this->out(__d('cake_console', 'Permission was not granted.')); } } /** * Deny access for an ARO to an ACO. * * @return void */ public function deny() { extract($this->_getParams()); if ($this->Acl->deny($aro, $aco, $action)) { $this->out(__d('cake_console', 'Permission denied.')); } else { $this->out(__d('cake_console', 'Permission was not denied.')); } } /** * Set an ARO to inherit permission to an ACO. * * @return void */ public function inherit() { extract($this->_getParams()); if ($this->Acl->inherit($aro, $aco, $action)) { $this->out(__d('cake_console', 'Permission inherited.')); } else { $this->out(__d('cake_console', 'Permission was not inherited.')); } } /** * Show a specific ARO/ACO node. * * @return void */ public function view() { extract($this->_dataVars()); if (isset($this->args[1])) { $identity = $this->parseIdentifier($this->args[1]); $topNode = $this->Acl->{$class}->find('first', array( 'conditions' => array($class . '.id' => $this->_getNodeId($class, $identity)) )); $nodes = $this->Acl->{$class}->find('all', array( 'conditions' => array( $class . '.lft >=' => $topNode[$class]['lft'], $class . '.lft <=' => $topNode[$class]['rght'] ), 'order' => $class . '.lft ASC' )); } else { $nodes = $this->Acl->{$class}->find('all', array('order' => $class . '.lft ASC')); } if (empty($nodes)) { if (isset($this->args[1])) { $this->error(__d('cake_console', '%s not found', $this->args[1]), __d('cake_console', 'No tree returned.')); } elseif (isset($this->args[0])) { $this->error(__d('cake_console', '%s not found', $this->args[0]), __d('cake_console', 'No tree returned.')); } } $this->out($class . ' tree:'); $this->hr(); $stack = array(); $last = null; foreach ($nodes as $n) { $stack[] = $n; if (!empty($last)) { $end = end($stack); if ($end[$class]['rght'] > $last) { foreach ($stack as $k => $v) { $end = end($stack); if ($v[$class]['rght'] < $end[$class]['rght']) { unset($stack[$k]); } } } } $last = $n[$class]['rght']; $count = count($stack); $this->_outputNode($class, $n, $count); } $this->hr(); } /** * Initialize ACL database. * * @return mixed */ public function initdb() { return $this->dispatchShell('schema create DbAcl'); } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $type = array( 'choices' => array('aro', 'aco'), 'required' => true, 'help' => __d('cake_console', 'Type of node to create.') ); $parser->description( __d('cake_console', 'A console tool for managing the DbAcl') )->addSubcommand('create', array( 'help' => __d('cake_console', 'Create a new ACL node'), 'parser' => array( 'description' => __d('cake_console', 'Creates a new ACL object under the parent'), 'epilog' => __d('cake_console', 'You can use `root` as the parent when creating nodes to create top level nodes.'), 'arguments' => array( 'type' => $type, 'parent' => array( 'help' => __d('cake_console', 'The node selector for the parent.'), 'required' => true ), 'alias' => array( 'help' => __d('cake_console', 'The alias to use for the newly created node.'), 'required' => true ) ) ) ))->addSubcommand('delete', array( 'help' => __d('cake_console', 'Deletes the ACL object with the given reference'), 'parser' => array( 'description' => __d('cake_console', 'Delete an ACL node.'), 'arguments' => array( 'type' => $type, 'node' => array( 'help' => __d('cake_console', 'The node identifier to delete.'), 'required' => true, ) ) ) ))->addSubcommand('setparent', array( 'help' => __d('cake_console', 'Moves the ACL node under a new parent.'), 'parser' => array( 'description' => __d('cake_console', 'Moves the ACL object specified by beneath '), 'arguments' => array( 'type' => $type, 'node' => array( 'help' => __d('cake_console', 'The node to move'), 'required' => true, ), 'parent' => array( 'help' => __d('cake_console', 'The new parent for .'), 'required' => true ) ) ) ))->addSubcommand('getpath', array( 'help' => __d('cake_console', 'Print out the path to an ACL node.'), 'parser' => array( 'description' => array( __d('cake_console', "Returns the path to the ACL object specified by ."), __d('cake_console', "This command is useful in determining the inheritance of permissions for a certain object in the tree.") ), 'arguments' => array( 'type' => $type, 'node' => array( 'help' => __d('cake_console', 'The node to get the path of'), 'required' => true, ) ) ) ))->addSubcommand('check', array( 'help' => __d('cake_console', 'Check the permissions between an ACO and ARO.'), 'parser' => array( 'description' => array( __d('cake_console', 'Use this command to check ACL permissions.') ), 'arguments' => array( 'aro' => array('help' => __d('cake_console', 'ARO to check.'), 'required' => true), 'aco' => array('help' => __d('cake_console', 'ACO to check.'), 'required' => true), 'action' => array('help' => __d('cake_console', 'Action to check'), 'default' => 'all') ) ) ))->addSubcommand('grant', array( 'help' => __d('cake_console', 'Grant an ARO permissions to an ACO.'), 'parser' => array( 'description' => array( __d('cake_console', 'Use this command to grant ACL permissions. Once executed, the ARO specified (and its children, if any) will have ALLOW access to the specified ACO action (and the ACO\'s children, if any).') ), 'arguments' => array( 'aro' => array('help' => __d('cake_console', 'ARO to grant permission to.'), 'required' => true), 'aco' => array('help' => __d('cake_console', 'ACO to grant access to.'), 'required' => true), 'action' => array('help' => __d('cake_console', 'Action to grant'), 'default' => 'all') ) ) ))->addSubcommand('deny', array( 'help' => __d('cake_console', 'Deny an ARO permissions to an ACO.'), 'parser' => array( 'description' => array( __d('cake_console', 'Use this command to deny ACL permissions. Once executed, the ARO specified (and its children, if any) will have DENY access to the specified ACO action (and the ACO\'s children, if any).') ), 'arguments' => array( 'aro' => array('help' => __d('cake_console', 'ARO to deny.'), 'required' => true), 'aco' => array('help' => __d('cake_console', 'ACO to deny.'), 'required' => true), 'action' => array('help' => __d('cake_console', 'Action to deny'), 'default' => 'all') ) ) ))->addSubcommand('inherit', array( 'help' => __d('cake_console', 'Inherit an ARO\'s parent permissions.'), 'parser' => array( 'description' => array( __d('cake_console', "Use this command to force a child ARO object to inherit its permissions settings from its parent.") ), 'arguments' => array( 'aro' => array('help' => __d('cake_console', 'ARO to have permissions inherit.'), 'required' => true), 'aco' => array('help' => __d('cake_console', 'ACO to inherit permissions on.'), 'required' => true), 'action' => array('help' => __d('cake_console', 'Action to inherit'), 'default' => 'all') ) ) ))->addSubcommand('view', array( 'help' => __d('cake_console', 'View a tree or a single node\'s subtree.'), 'parser' => array( 'description' => array( __d('cake_console', "The view command will return the ARO or ACO tree."), __d('cake_console', "The optional node parameter allows you to return"), __d('cake_console', "only a portion of the requested tree.") ), 'arguments' => array( 'type' => $type, 'node' => array('help' => __d('cake_console', 'The optional node to view the subtree of.')) ) ) ))->addSubcommand('initdb', array( 'help' => __d('cake_console', 'Initialize the DbAcl tables. Uses this command : cake schema create DbAcl') ))->epilog(array( 'Node and parent arguments can be in one of the following formats:', '', ' - . - The node will be bound to a specific record of the given model.', '', ' - - The node will be given a string alias (or path, in the case of )', " i.e. 'John'. When used with , this takes the form of an alias path,", " i.e. //.", '', "To add a node at the root level, enter 'root' or '/' as the parameter." )); return $parser; } /** * Checks that given node exists * * @return bool Success */ public function nodeExists() { if (!isset($this->args[0]) || !isset($this->args[1])) { return false; } $dataVars = $this->_dataVars($this->args[0]); extract($dataVars); $key = is_numeric($this->args[1]) ? $dataVars['secondary_id'] : 'alias'; $conditions = array($class . '.' . $key => $this->args[1]); $possibility = $this->Acl->{$class}->find('all', compact('conditions')); if (empty($possibility)) { $this->error(__d('cake_console', '%s not found', $this->args[1]), __d('cake_console', 'No tree returned.')); } return $possibility; } /** * Parse an identifier into Model.foreignKey or an alias. * Takes an identifier determines its type and returns the result as used by other methods. * * @param string $identifier Identifier to parse * @return mixed a string for aliases, and an array for model.foreignKey */ public function parseIdentifier($identifier) { if (preg_match('/^([\w]+)\.(.*)$/', $identifier, $matches)) { return array( 'model' => $matches[1], 'foreign_key' => $matches[2], ); } return $identifier; } /** * Get the node for a given identifier. $identifier can either be a string alias * or an array of properties to use in AcoNode::node() * * @param string $class Class type you want (Aro/Aco) * @param string|array|null $identifier A mixed identifier for finding the node, otherwise null. * @return int Integer of NodeId. Will trigger an error if nothing is found. */ protected function _getNodeId($class, $identifier) { $node = $this->Acl->{$class}->node($identifier); if (empty($node)) { if (is_array($identifier)) { $identifier = var_export($identifier, true); } $this->error(__d('cake_console', 'Could not find node using reference "%s"', $identifier)); return null; } return Hash::get($node, "0.{$class}.id"); } /** * get params for standard Acl methods * * @return array aro, aco, action */ protected function _getParams() { $aro = is_numeric($this->args[0]) ? (int)$this->args[0] : $this->args[0]; $aco = is_numeric($this->args[1]) ? (int)$this->args[1] : $this->args[1]; $aroName = $aro; $acoName = $aco; if (is_string($aro)) { $aro = $this->parseIdentifier($aro); } if (is_string($aco)) { $aco = $this->parseIdentifier($aco); } $action = '*'; if (isset($this->args[2]) && !in_array($this->args[2], array('', 'all'))) { $action = $this->args[2]; } return compact('aro', 'aco', 'action', 'aroName', 'acoName'); } /** * Build data parameters based on node type * * @param string $type Node type (ARO/ACO) * @return array Variables */ protected function _dataVars($type = null) { if (!$type) { $type = $this->args[0]; } $vars = array(); $class = ucwords($type); $vars['secondary_id'] = (strtolower($class) === 'aro') ? 'foreign_key' : 'object_id'; $vars['data_name'] = $type; $vars['table_name'] = $type . 's'; $vars['class'] = $class; return $vars; } } cakephp-2.8.0/lib/Cake/Console/Command/ApiShell.php000066400000000000000000000161051265552240500217500ustar00rootroot00000000000000paths = array_merge($this->paths, array( 'behavior' => CAKE . 'Model' . DS . 'Behavior' . DS, 'cache' => CAKE . 'Cache' . DS, 'controller' => CAKE . 'Controller' . DS, 'component' => CAKE . 'Controller' . DS . 'Component' . DS, 'helper' => CAKE . 'View' . DS . 'Helper' . DS, 'model' => CAKE . 'Model' . DS, 'view' => CAKE . 'View' . DS, 'core' => CAKE )); } /** * Override main() to handle action * * @return void */ public function main() { if (empty($this->args)) { return $this->out($this->OptionParser->help()); } $type = strtolower($this->args[0]); if (isset($this->paths[$type])) { $path = $this->paths[$type]; } else { $path = $this->paths['core']; } $count = count($this->args); if ($count > 1) { $file = Inflector::underscore($this->args[1]); $class = Inflector::camelize($this->args[1]); } elseif ($count) { $file = $type; $class = Inflector::camelize($type); } $objects = App::objects('class', $path); if (in_array($class, $objects)) { if (in_array($type, array('behavior', 'component', 'helper')) && $type !== $file) { if (!preg_match('/' . Inflector::camelize($type) . '$/', $class)) { $class .= Inflector::camelize($type); } } } else { $this->error(__d('cake_console', '%s not found', $class)); } $parsed = $this->_parseClass($path . $class . '.php', $class); if (!empty($parsed)) { if (isset($this->params['method'])) { if (!isset($parsed[$this->params['method']])) { $this->err(__d('cake_console', '%s::%s() could not be found', $class, $this->params['method'])); return $this->_stop(); } $method = $parsed[$this->params['method']]; $this->out($class . '::' . $method['method'] . $method['parameters']); $this->hr(); $this->out($method['comment'], true); } else { $this->out(ucwords($class)); $this->hr(); $i = 0; foreach ($parsed as $method) { $list[] = ++$i . ". " . $method['method'] . $method['parameters']; } $this->out($list); $methods = array_keys($parsed); while ($number = strtolower($this->in(__d('cake_console', 'Select a number to see the more information about a specific method. q to quit. l to list.'), null, 'q'))) { if ($number === 'q') { $this->out(__d('cake_console', 'Done')); return $this->_stop(); } if ($number === 'l') { $this->out($list); } if (isset($methods[--$number])) { $method = $parsed[$methods[$number]]; $this->hr(); $this->out($class . '::' . $method['method'] . $method['parameters']); $this->hr(); $this->out($method['comment'], true); } } } } } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'Lookup doc block comments for classes in CakePHP.') )->addArgument('type', array( 'help' => __d('cake_console', 'Either a full path or type of class (model, behavior, controller, component, view, helper)') ))->addArgument('className', array( 'help' => __d('cake_console', 'A CakePHP core class name (e.g: Component, HtmlHelper).') ))->addOption('method', array( 'short' => 'm', 'help' => __d('cake_console', 'The specific method you want help on.') )); return $parser; } /** * Show help for this shell. * * @return void */ public function help() { $head = "Usage: cake api [] [-m ]\n"; $head .= "-----------------------------------------------\n"; $head .= "Parameters:\n\n"; $commands = array( 'path' => "\t\n" . "\t\tEither a full path or type of class (model, behavior, controller, component, view, helper).\n" . "\t\tAvailable values:\n\n" . "\t\tbehavior\tLook for class in CakePHP behavior path\n" . "\t\tcache\tLook for class in CakePHP cache path\n" . "\t\tcontroller\tLook for class in CakePHP controller path\n" . "\t\tcomponent\tLook for class in CakePHP component path\n" . "\t\thelper\tLook for class in CakePHP helper path\n" . "\t\tmodel\tLook for class in CakePHP model path\n" . "\t\tview\tLook for class in CakePHP view path\n", 'className' => "\t\n" . "\t\tA CakePHP core class name (e.g: Component, HtmlHelper).\n" ); $this->out($head); if (!isset($this->args[1])) { foreach ($commands as $cmd) { $this->out("{$cmd}\n\n"); } } elseif (isset($commands[strtolower($this->args[1])])) { $this->out($commands[strtolower($this->args[1])] . "\n\n"); } else { $this->out(__d('cake_console', 'Command %s not found', $this->args[1])); } } /** * Parse a given class (located on given file) and get public methods and their * signatures. * * @param string $path File path * @param string $class Class name * @return array Methods and signatures indexed by method name */ protected function _parseClass($path, $class) { $parsed = array(); if (!class_exists($class)) { if (!include_once $path) { $this->err(__d('cake_console', '%s could not be found', $path)); } } $reflection = new ReflectionClass($class); foreach ($reflection->getMethods() as $method) { if (!$method->isPublic() || strpos($method->getName(), '_') === 0) { continue; } if ($method->getDeclaringClass()->getName() != $class) { continue; } $args = array(); foreach ($method->getParameters() as $param) { $paramString = '$' . $param->getName(); if ($param->isDefaultValueAvailable()) { $paramString .= ' = ' . str_replace("\n", '', var_export($param->getDefaultValue(), true)); } $args[] = $paramString; } $parsed[$method->getName()] = array( 'comment' => str_replace(array('/*', '*/', '*'), '', $method->getDocComment()), 'method' => $method->getName(), 'parameters' => '(' . implode(', ', $args) . ')' ); } ksort($parsed); return $parsed; } } cakephp-2.8.0/lib/Cake/Console/Command/AppShell.php000066400000000000000000000015261265552240500217600ustar00rootroot00000000000000connection to the active task if a connection param is set. * * @return void */ public function startup() { parent::startup(); Configure::write('debug', 2); Configure::write('Cache.disable', 1); $task = Inflector::classify($this->command); if (isset($this->{$task}) && !in_array($task, array('Project', 'DbConfig'))) { if (isset($this->params['connection'])) { $this->{$task}->connection = $this->params['connection']; } } if (isset($this->params['connection'])) { $this->connection = $this->params['connection']; } } /** * Override main() to handle action * * @return mixed */ public function main() { if (!is_dir($this->DbConfig->path)) { $path = $this->Project->execute(); if (!empty($path)) { $this->DbConfig->path = $path . 'Config' . DS; } else { return false; } } if (!config('database')) { $this->out(__d('cake_console', 'Your database configuration was not found. Take a moment to create one.')); $this->args = null; return $this->DbConfig->execute(); } $this->out(__d('cake_console', 'Interactive Bake Shell')); $this->hr(); $this->out(__d('cake_console', '[D]atabase Configuration')); $this->out(__d('cake_console', '[M]odel')); $this->out(__d('cake_console', '[V]iew')); $this->out(__d('cake_console', '[C]ontroller')); $this->out(__d('cake_console', '[P]roject')); $this->out(__d('cake_console', '[F]ixture')); $this->out(__d('cake_console', '[T]est case')); $this->out(__d('cake_console', '[Q]uit')); $classToBake = strtoupper($this->in(__d('cake_console', 'What would you like to Bake?'), array('D', 'M', 'V', 'C', 'P', 'F', 'T', 'Q'))); switch ($classToBake) { case 'D': $this->DbConfig->execute(); break; case 'M': $this->Model->execute(); break; case 'V': $this->View->execute(); break; case 'C': $this->Controller->execute(); break; case 'P': $this->Project->execute(); break; case 'F': $this->Fixture->execute(); break; case 'T': $this->Test->execute(); break; case 'Q': return $this->_stop(); default: $this->out(__d('cake_console', 'You have made an invalid selection. Please choose a type of class to Bake by entering D, M, V, F, T, or C.')); } $this->hr(); $this->main(); } /** * Quickly bake the MVC * * @return void */ public function all() { $this->out('Bake All'); $this->hr(); if (!isset($this->params['connection']) && empty($this->connection)) { $this->connection = $this->DbConfig->getConfig(); } if (empty($this->args)) { $this->Model->interactive = true; $name = $this->Model->getName($this->connection); } foreach (array('Model', 'Controller', 'View') as $task) { $this->{$task}->connection = $this->connection; $this->{$task}->interactive = false; } if (!empty($this->args[0])) { $name = $this->args[0]; } $modelExists = false; $model = $this->_modelName($name); App::uses('AppModel', 'Model'); App::uses($model, 'Model'); if (class_exists($model)) { $object = new $model(); $modelExists = true; } else { $object = new Model(array('name' => $name, 'ds' => $this->connection)); } $modelBaked = $this->Model->bake($object, false); if ($modelBaked && $modelExists === false) { if ($this->_checkUnitTest()) { $this->Model->bakeFixture($model); $this->Model->bakeTest($model); } $modelExists = true; } if ($modelExists === true) { $controller = $this->_controllerName($name); if ($this->Controller->bake($controller, $this->Controller->bakeActions($controller))) { if ($this->_checkUnitTest()) { $this->Controller->bakeTest($controller); } } App::uses($controller . 'Controller', 'Controller'); if (class_exists($controller . 'Controller')) { $this->View->args = array($name); $this->View->execute(); } $this->out('', 1, Shell::QUIET); $this->out(__d('cake_console', 'Bake All complete'), 1, Shell::QUIET); array_shift($this->args); } else { $this->error(__d('cake_console', 'Bake All could not continue without a valid model')); } return $this->_stop(); } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'The Bake script generates controllers, views and models for your application.' . ' If run with no command line arguments, Bake guides the user through the class creation process.' . ' You can customize the generation process by telling Bake where different parts of your application are using command line arguments.') )->addSubcommand('all', array( 'help' => __d('cake_console', 'Bake a complete MVC. optional of a Model') ))->addSubcommand('project', array( 'help' => __d('cake_console', 'Bake a new app folder in the path supplied or in current directory if no path is specified'), 'parser' => $this->Project->getOptionParser() ))->addSubcommand('plugin', array( 'help' => __d('cake_console', 'Bake a new plugin folder in the path supplied or in current directory if no path is specified.'), 'parser' => $this->Plugin->getOptionParser() ))->addSubcommand('db_config', array( 'help' => __d('cake_console', 'Bake a database.php file in config directory.'), 'parser' => $this->DbConfig->getOptionParser() ))->addSubcommand('model', array( 'help' => __d('cake_console', 'Bake a model.'), 'parser' => $this->Model->getOptionParser() ))->addSubcommand('view', array( 'help' => __d('cake_console', 'Bake views for controllers.'), 'parser' => $this->View->getOptionParser() ))->addSubcommand('controller', array( 'help' => __d('cake_console', 'Bake a controller.'), 'parser' => $this->Controller->getOptionParser() ))->addSubcommand('fixture', array( 'help' => __d('cake_console', 'Bake a fixture.'), 'parser' => $this->Fixture->getOptionParser() ))->addSubcommand('test', array( 'help' => __d('cake_console', 'Bake a unit test.'), 'parser' => $this->Test->getOptionParser() ))->addOption('connection', array( 'help' => __d('cake_console', 'Database connection to use in conjunction with `bake all`.'), 'short' => 'c', 'default' => 'default' ))->addOption('theme', array( 'short' => 't', 'help' => __d('cake_console', 'Theme to use when baking code.') )); return $parser; } } cakephp-2.8.0/lib/Cake/Console/Command/CommandListShell.php000066400000000000000000000077621265552240500234620ustar00rootroot00000000000000params['xml'])) { parent::startup(); } } /** * Main function Prints out the list of shells. * * @return void */ public function main() { if (empty($this->params['xml'])) { $this->out(__d('cake_console', "Current Paths:"), 2); $this->out(" -app: " . APP_DIR); $this->out(" -working: " . rtrim(APP, DS)); $this->out(" -root: " . rtrim(ROOT, DS)); $this->out(" -core: " . rtrim(CORE_PATH, DS)); $this->out(""); $this->out(__d('cake_console', "Changing Paths:"), 2); $this->out(__d('cake_console', "Your working path should be the same as your application path. To change your path use the '-app' param.")); $this->out(__d('cake_console', "Example: %s or %s", '-app relative/path/to/myapp', '-app /absolute/path/to/myapp'), 2); $this->out(__d('cake_console', "Available Shells:"), 2); } $shellList = $this->Command->getShellList(); if (empty($shellList)) { return; } if (empty($this->params['xml'])) { $this->_asText($shellList); } else { $this->_asXml($shellList); } } /** * Output text. * * @param array $shellList The shell list. * @return void */ protected function _asText($shellList) { foreach ($shellList as $plugin => $commands) { sort($commands); $this->out(sprintf('[%s] %s', $plugin, implode(', ', $commands))); $this->out(); } $this->out(__d('cake_console', "To run an app or core command, type cake shell_name [args]")); $this->out(__d('cake_console', "To run a plugin command, type cake Plugin.shell_name [args]")); $this->out(__d('cake_console', "To get help on a specific command, type cake shell_name --help"), 2); } /** * Output as XML * * @param array $shellList The shell list. * @return void */ protected function _asXml($shellList) { $plugins = CakePlugin::loaded(); $shells = new SimpleXmlElement(''); foreach ($shellList as $plugin => $commands) { foreach ($commands as $command) { $callable = $command; if (in_array($plugin, $plugins)) { $callable = Inflector::camelize($plugin) . '.' . $command; } $shell = $shells->addChild('shell'); $shell->addAttribute('name', $command); $shell->addAttribute('call_as', $callable); $shell->addAttribute('provider', $plugin); $shell->addAttribute('help', $callable . ' -h'); } } $this->stdout->outputAs(ConsoleOutput::RAW); $this->out($shells->saveXml()); } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'Get the list of available shells for this CakePHP application.') )->addOption('sort', array( 'help' => __d('cake_console', 'Does nothing (deprecated)'), 'boolean' => true ))->addOption('xml', array( 'help' => __d('cake_console', 'Get the listing as XML.'), 'boolean' => true )); return $parser; } } cakephp-2.8.0/lib/Cake/Console/Command/CompletionShell.php000066400000000000000000000070771265552240500233600ustar00rootroot00000000000000out($this->getOptionParser()->help()); } /** * list commands * * @return void */ public function commands() { $options = $this->Command->commands(); return $this->_output($options); } /** * list options for the named command * * @return void */ public function options() { $commandName = ''; if (!empty($this->args[0])) { $commandName = $this->args[0]; } $options = $this->Command->options($commandName); return $this->_output($options); } /** * list subcommands for the named command * * @return void */ public function subCommands() { if (!$this->args) { return $this->_output(); } $options = $this->Command->subCommands($this->args[0]); return $this->_output($options); } /** * Guess autocomplete from the whole argument string * * @return void */ public function fuzzy() { return $this->_output(); } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'Used by shells like bash to autocomplete command name, options and arguments') )->addSubcommand('commands', array( 'help' => __d('cake_console', 'Output a list of available commands'), 'parser' => array( 'description' => __d('cake_console', 'List all availables'), 'arguments' => array( ) ) ))->addSubcommand('subcommands', array( 'help' => __d('cake_console', 'Output a list of available subcommands'), 'parser' => array( 'description' => __d('cake_console', 'List subcommands for a command'), 'arguments' => array( 'command' => array( 'help' => __d('cake_console', 'The command name'), 'required' => true, ) ) ) ))->addSubcommand('options', array( 'help' => __d('cake_console', 'Output a list of available options'), 'parser' => array( 'description' => __d('cake_console', 'List options'), 'arguments' => array( 'command' => array( 'help' => __d('cake_console', 'The command name'), 'required' => false, ) ) ) ))->epilog( __d('cake_console', 'This command is not intended to be called manually') ); return $parser; } /** * Emit results as a string, space delimited * * @param array $options The options to output * @return void */ protected function _output($options = array()) { if ($options) { return $this->out(implode($options, ' ')); } } } cakephp-2.8.0/lib/Cake/Console/Command/ConsoleShell.php000066400000000000000000000317751265552240500226530ustar00rootroot00000000000000 '/^(help|\?)/', '_exit' => '/^(quit|exit)/', '_models' => '/^models/i', '_bind' => '/^(\w+) bind (\w+) (\w+)/', '_unbind' => '/^(\w+) unbind (\w+) (\w+)/', '_find' => '/.+->find/', '_save' => '/.+->save/', '_columns' => '/^(\w+) columns/', '_routesReload' => '/^routes\s+reload/i', '_routesShow' => '/^routes\s+show/i', '_routeToString' => '/^route\s+(\(.*\))$/i', '_routeToArray' => '/^route\s+(.*)$/i', ); /** * Override startup of the Shell * * @return void */ public function startup() { App::uses('Dispatcher', 'Routing'); $this->Dispatcher = new Dispatcher(); $this->models = App::objects('Model'); foreach ($this->models as $model) { $class = $model; App::uses($class, 'Model'); $this->{$class} = new $class(); } $this->out(__d('cake_console', 'Model classes:')); $this->hr(); foreach ($this->models as $model) { $this->out(" - {$model}"); } if (!$this->_loadRoutes()) { $message = __d( 'cake_console', 'There was an error loading the routes config. Please check that the file exists and contains no errors.' ); $this->err($message); } } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description(array( 'The interactive console is a tool for testing parts of your', 'app before you write code.', '', 'See below for a list of supported commands.' ))->epilog(array( 'Model testing', '', 'To test model results, use the name of your model without a leading $', 'e.g. Foo->find("all")', "", 'To dynamically set associations, you can do the following:', '', "\tModelA bind ModelB", '', "where the supported associations are hasOne, hasMany, belongsTo, hasAndBelongsToMany", "", 'To dynamically remove associations, you can do the following:', '', "\t ModelA unbind ModelB", '', "where the supported associations are the same as above", "", "To save a new field in a model, you can do the following:", '', "\tModelA->save(array('foo' => 'bar', 'baz' => 0))", '', "where you are passing a hash of data to be saved in the format", "of field => value pairs", "", "To get column information for a model, use the following:", '', "\tModelA columns", '', "which returns a list of columns and their type", "", 'Route testing', "", 'To test URLs against your app\'s route configuration, type:', "", "\tRoute ", "", "where url is the path to your your action plus any query parameters,", "minus the application's base path. For example:", "", "\tRoute /posts/view/1", "", "will return something like the following:", "", "\tarray(", "\t [...]", "\t 'controller' => 'posts',", "\t 'action' => 'view',", "\t [...]", "\t)", "", 'Alternatively, you can use simple array syntax to test reverse', 'To reload your routes config (Config/routes.php), do the following:', "", "\tRoutes reload", "", 'To show all connected routes, do the following:', '', "\tRoutes show", )); return $parser; } /** * Prints the help message * * @return void */ public function help() { $optionParser = $this->getOptionParser(); $this->out($optionParser->epilog()); } /** * Override main() to handle action * * @param string $command The command to run. * @return void */ public function main($command = null) { $this->_finished = false; while (!$this->_finished) { if (empty($command)) { $command = trim($this->in('')); } $method = $this->_method($command); if ($method) { $this->$method($command); } else { $this->out(__d('cake_console', "Invalid command")); $this->out(); } $command = ''; } } /** * Determine the method to process the current command * * @param string $command The command to run. * @return string or false */ protected function _method($command) { foreach ($this->_methodPatterns as $method => $pattern) { if (preg_match($pattern, $command)) { return $method; } } return false; } /** * Set the finiished property so that the loop in main method ends * * @return void */ protected function _exit() { $this->_finished = true; } /** * List all models * * @return void */ protected function _models() { $this->out(__d('cake_console', 'Model classes:')); $this->hr(); foreach ($this->models as $model) { $this->out(" - {$model}"); } } /** * Bind an association * * @param mixed $command The command to run. * @return void */ protected function _bind($command) { preg_match($this->_methodPatterns[__FUNCTION__], $command, $tmp); foreach ($tmp as $data) { $data = strip_tags($data); $data = str_replace($this->badCommandChars, "", $data); } $modelA = $tmp[1]; $association = $tmp[2]; $modelB = $tmp[3]; if ($this->_isValidModel($modelA) && $this->_isValidModel($modelB) && in_array($association, $this->associations)) { $this->{$modelA}->bindModel(array($association => array($modelB => array('className' => $modelB))), false); $this->out(__d('cake_console', "Created %s association between %s and %s", $association, $modelA, $modelB)); } else { $this->out(__d('cake_console', "Please verify you are using valid models and association types")); } } /** * Unbind an association * * @param mixed $command The command to run. * @return void */ protected function _unbind($command) { preg_match($this->_methodPatterns[__FUNCTION__], $command, $tmp); foreach ($tmp as $data) { $data = strip_tags($data); $data = str_replace($this->badCommandChars, "", $data); } $modelA = $tmp[1]; $association = $tmp[2]; $modelB = $tmp[3]; // Verify that there is actually an association to unbind $currentAssociations = $this->{$modelA}->getAssociated(); $validCurrentAssociation = false; foreach ($currentAssociations as $model => $currentAssociation) { if ($model === $modelB && $association === $currentAssociation) { $validCurrentAssociation = true; } } if ($this->_isValidModel($modelA) && $this->_isValidModel($modelB) && in_array($association, $this->associations) && $validCurrentAssociation) { $this->{$modelA}->unbindModel(array($association => array($modelB))); $this->out(__d('cake_console', "Removed %s association between %s and %s", $association, $modelA, $modelB)); } else { $this->out(__d('cake_console', "Please verify you are using valid models, valid current association, and valid association types")); } } /** * Perform a find * * @param mixed $command The command to run. * @return void */ protected function _find($command) { $command = strip_tags($command); $command = str_replace($this->badCommandChars, "", $command); // Do we have a valid model? list($modelToCheck) = explode('->', $command); if ($this->_isValidModel($modelToCheck)) { $findCommand = "\$data = \$this->$command;"; //@codingStandardsIgnoreStart @eval($findCommand); //@codingStandardsIgnoreEnd if (is_array($data)) { foreach ($data as $idx => $results) { if (is_numeric($idx)) { // findAll() output foreach ($results as $modelName => $result) { $this->out("$modelName"); foreach ($result as $field => $value) { if (is_array($value)) { foreach ($value as $field2 => $value2) { $this->out("\t$field2: $value2"); } $this->out(); } else { $this->out("\t$field: $value"); } } } } else { // find() output $this->out($idx); foreach ($results as $field => $value) { if (is_array($value)) { foreach ($value as $field2 => $value2) { $this->out("\t$field2: $value2"); } $this->out(); } else { $this->out("\t$field: $value"); } } } } } else { $this->out(); $this->out(__d('cake_console', "No result set found")); } } else { $this->out(__d('cake_console', "%s is not a valid model", $modelToCheck)); } } /** * Save a record * * @param mixed $command The command to run. * @return void */ protected function _save($command) { // Validate the model we're trying to save here $command = strip_tags($command); $command = str_replace($this->badCommandChars, "", $command); list($modelToSave) = explode("->", $command); if ($this->_isValidModel($modelToSave)) { // Extract the array of data we are trying to build list(, $data) = explode("->save", $command); $data = preg_replace('/^\(*(array)?\(*(.+?)\)*$/i', '\\2', $data); $saveCommand = "\$this->{$modelToSave}->save(array('{$modelToSave}' => array({$data})));"; //@codingStandardsIgnoreStart @eval($saveCommand); //@codingStandardsIgnoreEnd $this->out(__d('cake_console', 'Saved record for %s', $modelToSave)); } } /** * Show the columns for a model * * @param mixed $command The command to run. * @return void */ protected function _columns($command) { preg_match($this->_methodPatterns[__FUNCTION__], $command, $tmp); $modelToCheck = strip_tags(str_replace($this->badCommandChars, "", $tmp[1])); if ($this->_isValidModel($modelToCheck)) { // Get the column info for this model $fieldsCommand = "\$data = \$this->{$modelToCheck}->getColumnTypes();"; //@codingStandardsIgnoreStart @eval($fieldsCommand); //@codingStandardsIgnoreEnd if (is_array($data)) { foreach ($data as $field => $type) { $this->out("\t{$field}: {$type}"); } } } else { $this->out(__d('cake_console', "Please verify that you selected a valid model")); } } /** * Reload route definitions * * @return void */ protected function _routesReload() { if (!$this->_loadRoutes()) { return $this->err(__d('cake_console', "There was an error loading the routes config. Please check that the file exists and is free of parse errors.")); } $this->out(__d('cake_console', "Routes configuration reloaded, %d routes connected", count(Router::$routes))); } /** * Show all routes * * @return void */ protected function _routesShow() { $this->out(print_r(Hash::combine(Router::$routes, '{n}.template', '{n}.defaults'), true)); } /** * Parse an array URL and show the equivalent URL as a string * * @param mixed $command The command to run. * @return void */ protected function _routeToString($command) { preg_match($this->_methodPatterns[__FUNCTION__], $command, $tmp); //@codingStandardsIgnoreStart if ($url = eval('return array' . $tmp[1] . ';')) { //@codingStandardsIgnoreEnd $this->out(Router::url($url)); } } /** * Parse a string URL and show as an array * * @param mixed $command The command to run. * @return void */ protected function _routeToArray($command) { preg_match($this->_methodPatterns[__FUNCTION__], $command, $tmp); $this->out(var_export(Router::parse($tmp[1]), true)); } /** * Tells if the specified model is included in the list of available models * * @param string $modelToCheck The model to check. * @return bool true if is an available model, false otherwise */ protected function _isValidModel($modelToCheck) { return in_array($modelToCheck, $this->models); } /** * Reloads the routes configuration from app/Config/routes.php, and compiles * all routes found * * @return bool True if config reload was a success, otherwise false */ protected function _loadRoutes() { Router::reload(); extract(Router::getNamedExpressions()); //@codingStandardsIgnoreStart if (!@include APP . 'Config' . DS . 'routes.php') { //@codingStandardsIgnoreEnd return false; } CakePlugin::routes(); Router::parse('/'); return true; } } cakephp-2.8.0/lib/Cake/Console/Command/I18nShell.php000066400000000000000000000062061265552240500217570ustar00rootroot00000000000000_welcome(); if (isset($this->params['datasource'])) { $this->dataSource = $this->params['datasource']; } if ($this->command && !in_array($this->command, array('help'))) { if (!config('database')) { $this->out(__d('cake_console', 'Your database configuration was not found. Take a moment to create one.')); return $this->DbConfig->execute(); } } } /** * Override main() for help message hook * * @return void */ public function main() { $this->out(__d('cake_console', 'I18n Shell')); $this->hr(); $this->out(__d('cake_console', '[E]xtract POT file from sources')); $this->out(__d('cake_console', '[I]nitialize i18n database table')); $this->out(__d('cake_console', '[H]elp')); $this->out(__d('cake_console', '[Q]uit')); $choice = strtolower($this->in(__d('cake_console', 'What would you like to do?'), array('E', 'I', 'H', 'Q'))); switch ($choice) { case 'e': $this->Extract->execute(); break; case 'i': $this->initdb(); break; case 'h': $this->out($this->OptionParser->help()); break; case 'q': return $this->_stop(); default: $this->out(__d('cake_console', 'You have made an invalid selection. Please choose a command to execute by entering E, I, H, or Q.')); } $this->hr(); $this->main(); } /** * Initialize I18N database. * * @return void */ public function initdb() { $this->dispatchShell('schema create i18n'); } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'I18n Shell initializes i18n database table for your application and generates .pot files(s) with translations.') )->addSubcommand('initdb', array( 'help' => __d('cake_console', 'Initialize the i18n table.') ))->addSubcommand('extract', array( 'help' => __d('cake_console', 'Extract the po translations from your application'), 'parser' => $this->Extract->getOptionParser() )); return $parser; } } cakephp-2.8.0/lib/Cake/Console/Command/SchemaShell.php000066400000000000000000000407241265552240500224430ustar00rootroot00000000000000_welcome(); $this->out('Cake Schema Shell'); $this->hr(); Configure::write('Cache.disable', 1); $name = $path = $connection = $plugin = null; if (!empty($this->params['name'])) { $name = $this->params['name']; } elseif (!empty($this->args[0]) && $this->args[0] !== 'snapshot') { $name = $this->params['name'] = $this->args[0]; } if (strpos($name, '.')) { list($this->params['plugin'], $splitName) = pluginSplit($name); $name = $this->params['name'] = $splitName; } if ($name && empty($this->params['file'])) { $this->params['file'] = Inflector::underscore($name); } elseif (empty($this->params['file'])) { $this->params['file'] = 'schema.php'; } if (strpos($this->params['file'], '.php') === false) { $this->params['file'] .= '.php'; } $file = $this->params['file']; if (!empty($this->params['path'])) { $path = $this->params['path']; } if (!empty($this->params['connection'])) { $connection = $this->params['connection']; } if (!empty($this->params['plugin'])) { $plugin = $this->params['plugin']; if (empty($name)) { $name = $plugin; } } $name = Inflector::camelize($name); $this->Schema = new CakeSchema(compact('name', 'path', 'file', 'connection', 'plugin')); } /** * Read and output contents of schema object * path to read as second arg * * @return void */ public function view() { $File = new File($this->Schema->path . DS . $this->params['file']); if ($File->exists()) { $this->out($File->read()); return $this->_stop(); } $file = $this->Schema->path . DS . $this->params['file']; $this->err(__d('cake_console', 'Schema file (%s) could not be found.', $file)); return $this->_stop(); } /** * Read database and Write schema object * accepts a connection as first arg or path to save as second arg * * @return void */ public function generate() { $this->out(__d('cake_console', 'Generating Schema...')); $options = array(); if ($this->params['force']) { $options['models'] = false; } elseif (!empty($this->params['models'])) { $options['models'] = CakeText::tokenize($this->params['models']); } $snapshot = false; if (isset($this->args[0]) && $this->args[0] === 'snapshot') { $snapshot = true; } if (!$snapshot && file_exists($this->Schema->path . DS . $this->params['file'])) { $snapshot = true; $prompt = __d('cake_console', "Schema file exists.\n [O]verwrite\n [S]napshot\n [Q]uit\nWould you like to do?"); $result = strtolower($this->in($prompt, array('o', 's', 'q'), 's')); if ($result === 'q') { return $this->_stop(); } if ($result === 'o') { $snapshot = false; } } $cacheDisable = Configure::read('Cache.disable'); Configure::write('Cache.disable', true); $content = $this->Schema->read($options); $content['file'] = $this->params['file']; Configure::write('Cache.disable', $cacheDisable); if (!empty($this->params['exclude']) && !empty($content)) { $excluded = CakeText::tokenize($this->params['exclude']); foreach ($excluded as $table) { unset($content['tables'][$table]); } } if ($snapshot === true) { $fileName = basename($this->params['file'], '.php'); $Folder = new Folder($this->Schema->path); $result = $Folder->read(); $numToUse = false; if (isset($this->params['snapshot'])) { $numToUse = $this->params['snapshot']; } $count = 0; if (!empty($result[1])) { foreach ($result[1] as $file) { if (preg_match('/' . preg_quote($fileName) . '(?:[_\d]*)?\.php$/', $file)) { $count++; } } } if ($numToUse !== false) { if ($numToUse > $count) { $count = $numToUse; } } $content['file'] = $fileName . '_' . $count . '.php'; } if ($this->Schema->write($content)) { $this->out(__d('cake_console', 'Schema file: %s generated', $content['file'])); return $this->_stop(); } $this->err(__d('cake_console', 'Schema file: %s generated')); return $this->_stop(); } /** * Dump Schema object to sql file * Use the `write` param to enable and control SQL file output location. * Simply using -write will write the sql file to the same dir as the schema file. * If -write contains a full path name the file will be saved there. If -write only * contains no DS, that will be used as the file name, in the same dir as the schema file. * * @return string */ public function dump() { $write = false; $Schema = $this->Schema->load(); if (!$Schema) { $this->err(__d('cake_console', 'Schema could not be loaded')); return $this->_stop(); } if (!empty($this->params['write'])) { if ($this->params['write'] == 1) { $write = Inflector::underscore($this->Schema->name); } else { $write = $this->params['write']; } } $db = ConnectionManager::getDataSource($this->Schema->connection); $contents = "\n\n" . $db->dropSchema($Schema) . "\n\n" . $db->createSchema($Schema); if ($write) { if (strpos($write, '.sql') === false) { $write .= '.sql'; } if (strpos($write, DS) !== false) { $File = new File($write, true); } else { $File = new File($this->Schema->path . DS . $write, true); } if ($File->write($contents)) { $this->out(__d('cake_console', 'SQL dump file created in %s', $File->pwd())); return $this->_stop(); } $this->err(__d('cake_console', 'SQL dump could not be created')); return $this->_stop(); } $this->out($contents); return $contents; } /** * Run database create commands. Alias for run create. * * @return void */ public function create() { list($Schema, $table) = $this->_loadSchema(); $this->_create($Schema, $table); } /** * Run database create commands. Alias for run create. * * @return void */ public function update() { list($Schema, $table) = $this->_loadSchema(); $this->_update($Schema, $table); } /** * Prepares the Schema objects for database operations. * * @return void */ protected function _loadSchema() { $name = $plugin = null; if (!empty($this->params['name'])) { $name = $this->params['name']; } if (!empty($this->params['plugin'])) { $plugin = $this->params['plugin']; } if (!empty($this->params['dry'])) { $this->_dry = true; $this->out(__d('cake_console', 'Performing a dry run.')); } $options = array( 'name' => $name, 'plugin' => $plugin, 'connection' => $this->params['connection'], ); if (!empty($this->params['snapshot'])) { $fileName = basename($this->Schema->file, '.php'); $options['file'] = $fileName . '_' . $this->params['snapshot'] . '.php'; } $Schema = $this->Schema->load($options); if (!$Schema) { $this->err(__d('cake_console', 'Error: The chosen schema could not be loaded. Attempted to load:')); $this->err(__d('cake_console', '- file: %s', $this->Schema->path . DS . $this->Schema->file)); $this->err(__d('cake_console', '- name: %s', $this->Schema->name)); return $this->_stop(2); } $table = null; if (isset($this->args[1])) { $table = $this->args[1]; } return array(&$Schema, $table); } /** * Create database from Schema object * Should be called via the run method * * @param CakeSchema $Schema The schema instance to create. * @param string $table The table name. * @return void */ protected function _create(CakeSchema $Schema, $table = null) { $db = ConnectionManager::getDataSource($this->Schema->connection); $drop = $create = array(); if (!$table) { foreach ($Schema->tables as $table => $fields) { $drop[$table] = $db->dropSchema($Schema, $table); $create[$table] = $db->createSchema($Schema, $table); } } elseif (isset($Schema->tables[$table])) { $drop[$table] = $db->dropSchema($Schema, $table); $create[$table] = $db->createSchema($Schema, $table); } if (empty($drop) || empty($create)) { $this->out(__d('cake_console', 'Schema is up to date.')); return $this->_stop(); } $this->out("\n" . __d('cake_console', 'The following table(s) will be dropped.')); $this->out(array_keys($drop)); if (!empty($this->params['yes']) || $this->in(__d('cake_console', 'Are you sure you want to drop the table(s)?'), array('y', 'n'), 'n') === 'y' ) { $this->out(__d('cake_console', 'Dropping table(s).')); $this->_run($drop, 'drop', $Schema); } $this->out("\n" . __d('cake_console', 'The following table(s) will be created.')); $this->out(array_keys($create)); if (!empty($this->params['yes']) || $this->in(__d('cake_console', 'Are you sure you want to create the table(s)?'), array('y', 'n'), 'y') === 'y' ) { $this->out(__d('cake_console', 'Creating table(s).')); $this->_run($create, 'create', $Schema); } $this->out(__d('cake_console', 'End create.')); } /** * Update database with Schema object * Should be called via the run method * * @param CakeSchema &$Schema The schema instance * @param string $table The table name. * @return void */ protected function _update(&$Schema, $table = null) { $db = ConnectionManager::getDataSource($this->Schema->connection); $this->out(__d('cake_console', 'Comparing Database to Schema...')); $options = array(); if (isset($this->params['force'])) { $options['models'] = false; } $Old = $this->Schema->read($options); $compare = $this->Schema->compare($Old, $Schema); $contents = array(); if (empty($table)) { foreach ($compare as $table => $changes) { if (isset($compare[$table]['create'])) { $contents[$table] = $db->createSchema($Schema, $table); } else { $contents[$table] = $db->alterSchema(array($table => $compare[$table]), $table); } } } elseif (isset($compare[$table])) { if (isset($compare[$table]['create'])) { $contents[$table] = $db->createSchema($Schema, $table); } else { $contents[$table] = $db->alterSchema(array($table => $compare[$table]), $table); } } if (empty($contents)) { $this->out(__d('cake_console', 'Schema is up to date.')); return $this->_stop(); } $this->out("\n" . __d('cake_console', 'The following statements will run.')); $this->out(array_map('trim', $contents)); if (!empty($this->params['yes']) || $this->in(__d('cake_console', 'Are you sure you want to alter the tables?'), array('y', 'n'), 'n') === 'y' ) { $this->out(); $this->out(__d('cake_console', 'Updating Database...')); $this->_run($contents, 'update', $Schema); Configure::write('Cache.disable', false); Cache::clear(false, '_cake_model_'); } $this->out(__d('cake_console', 'End update.')); } /** * Runs sql from _create() or _update() * * @param array $contents The contents to execute. * @param string $event The event to fire * @param CakeSchema $Schema The schema instance. * @return void */ protected function _run($contents, $event, CakeSchema $Schema) { if (empty($contents)) { $this->err(__d('cake_console', 'Sql could not be run')); return; } Configure::write('debug', 2); $db = ConnectionManager::getDataSource($this->Schema->connection); foreach ($contents as $table => $sql) { if (empty($sql)) { $this->out(__d('cake_console', '%s is up to date.', $table)); } else { if ($this->_dry === true) { $this->out(__d('cake_console', 'Dry run for %s :', $table)); $this->out($sql); } else { if (!$Schema->before(array($event => $table))) { return false; } $error = null; try { $db->execute($sql); } catch (PDOException $e) { $error = $table . ': ' . $e->getMessage(); } $Schema->after(array($event => $table, 'errors' => $error)); if (!empty($error)) { $this->err($error); } else { $this->out(__d('cake_console', '%s updated.', $table)); } } } } } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $plugin = array( 'short' => 'p', 'help' => __d('cake_console', 'The plugin to use.'), ); $connection = array( 'short' => 'c', 'help' => __d('cake_console', 'Set the db config to use.'), 'default' => 'default' ); $path = array( 'help' => __d('cake_console', 'Path to read and write schema.php'), 'default' => APP . 'Config' . DS . 'Schema' ); $file = array( 'help' => __d('cake_console', 'File name to read and write.'), ); $name = array( 'help' => __d('cake_console', 'Classname to use. If its Plugin.class, both name and plugin options will be set.' ) ); $snapshot = array( 'short' => 's', 'help' => __d('cake_console', 'Snapshot number to use/make.') ); $models = array( 'short' => 'm', 'help' => __d('cake_console', 'Specify models as comma separated list.'), ); $dry = array( 'help' => __d('cake_console', 'Perform a dry run on create and update commands. Queries will be output instead of run.' ), 'boolean' => true ); $force = array( 'short' => 'f', 'help' => __d('cake_console', 'Force "generate" to create a new schema'), 'boolean' => true ); $write = array( 'help' => __d('cake_console', 'Write the dumped SQL to a file.') ); $exclude = array( 'help' => __d('cake_console', 'Tables to exclude as comma separated list.') ); $yes = array( 'short' => 'y', 'help' => __d('cake_console', 'Do not prompt for confirmation. Be careful!'), 'boolean' => true ); $parser->description( __d('cake_console', 'The Schema Shell generates a schema object from the database and updates the database from the schema.') )->addSubcommand('view', array( 'help' => __d('cake_console', 'Read and output the contents of a schema file'), 'parser' => array( 'options' => compact('plugin', 'path', 'file', 'name', 'connection'), 'arguments' => compact('name') ) ))->addSubcommand('generate', array( 'help' => __d('cake_console', 'Reads from --connection and writes to --path. Generate snapshots with -s'), 'parser' => array( 'options' => compact('plugin', 'path', 'file', 'name', 'connection', 'snapshot', 'force', 'models', 'exclude'), 'arguments' => array( 'snapshot' => array('help' => __d('cake_console', 'Generate a snapshot.')) ) ) ))->addSubcommand('dump', array( 'help' => __d('cake_console', 'Dump database SQL based on a schema file to stdout.'), 'parser' => array( 'options' => compact('plugin', 'path', 'file', 'name', 'connection', 'write'), 'arguments' => compact('name') ) ))->addSubcommand('create', array( 'help' => __d('cake_console', 'Drop and create tables based on the schema file.'), 'parser' => array( 'options' => compact('plugin', 'path', 'file', 'name', 'connection', 'dry', 'snapshot', 'yes'), 'args' => array( 'name' => array( 'help' => __d('cake_console', 'Name of schema to use.') ), 'table' => array( 'help' => __d('cake_console', 'Only create the specified table.') ) ) ) ))->addSubcommand('update', array( 'help' => __d('cake_console', 'Alter the tables based on the schema file.'), 'parser' => array( 'options' => compact('plugin', 'path', 'file', 'name', 'connection', 'dry', 'snapshot', 'force', 'yes'), 'args' => array( 'name' => array( 'help' => __d('cake_console', 'Name of schema to use.') ), 'table' => array( 'help' => __d('cake_console', 'Only create the specified table.') ) ) ) )); return $parser; } } cakephp-2.8.0/lib/Cake/Console/Command/ServerShell.php000066400000000000000000000100661265552240500225050ustar00rootroot00000000000000_host = static::DEFAULT_HOST; $this->_port = static::DEFAULT_PORT; $this->_documentRoot = WWW_ROOT; } /** * Starts up the Shell and displays the welcome message. * Allows for checking and configuring prior to command or main execution * * Override this method if you want to remove the welcome information, * or otherwise modify the pre-command flow. * * @return void * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::startup */ public function startup() { if (!empty($this->params['host'])) { $this->_host = $this->params['host']; } if (!empty($this->params['port'])) { $this->_port = $this->params['port']; } if (!empty($this->params['document_root'])) { $this->_documentRoot = $this->params['document_root']; } // for Windows if (substr($this->_documentRoot, -1, 1) === DIRECTORY_SEPARATOR) { $this->_documentRoot = substr($this->_documentRoot, 0, strlen($this->_documentRoot) - 1); } if (preg_match("/^([a-z]:)[\\\]+(.+)$/i", $this->_documentRoot, $m)) { $this->_documentRoot = $m[1] . '\\' . $m[2]; } parent::startup(); } /** * Displays a header for the shell * * @return void */ protected function _welcome() { $this->out(); $this->out(__d('cake_console', 'Welcome to CakePHP %s Console', 'v' . Configure::version())); $this->hr(); $this->out(__d('cake_console', 'App : %s', APP_DIR)); $this->out(__d('cake_console', 'Path: %s', APP)); $this->out(__d('cake_console', 'DocumentRoot: %s', $this->_documentRoot)); $this->hr(); } /** * Override main() to handle action * * @return void */ public function main() { if (version_compare(PHP_VERSION, '5.4.0') < 0) { $this->out(__d('cake_console', 'This command is available on %s or above', 'PHP5.4')); return; } $command = sprintf("php -S %s:%d -t %s %s", $this->_host, $this->_port, escapeshellarg($this->_documentRoot), escapeshellarg($this->_documentRoot . '/index.php') ); $port = ($this->_port == static::DEFAULT_PORT) ? '' : ':' . $this->_port; $this->out(__d('cake_console', 'built-in server is running in http://%s%s/', $this->_host, $port)); system($command); } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description(array( __d('cake_console', 'PHP Built-in Server for CakePHP'), __d('cake_console', '[WARN] Don\'t use this at the production environment') ))->addOption('host', array( 'short' => 'H', 'help' => __d('cake_console', 'ServerHost') ))->addOption('port', array( 'short' => 'p', 'help' => __d('cake_console', 'ListenPort') ))->addOption('document_root', array( 'short' => 'd', 'help' => __d('cake_console', 'DocumentRoot') )); return $parser; } } cakephp-2.8.0/lib/Cake/Console/Command/Task/000077500000000000000000000000001265552240500204355ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Command/Task/BakeTask.php000066400000000000000000000040031265552240500226300ustar00rootroot00000000000000path; if (isset($this->plugin)) { $path = $this->_pluginPath($this->plugin) . $this->name . DS; } return $path; } /** * Base execute method parses some parameters and sets some properties on the bake tasks. * call when overriding execute() * * @return void */ public function execute() { foreach ($this->args as $i => $arg) { if (strpos($arg, '.')) { list($this->params['plugin'], $this->args[$i]) = pluginSplit($arg); break; } } if (isset($this->params['plugin'])) { $this->plugin = $this->params['plugin']; } } } cakephp-2.8.0/lib/Cake/Console/Command/Task/CommandTask.php000066400000000000000000000111441265552240500233500ustar00rootroot00000000000000 null, 'app' => null); $corePath = App::core('Console/Command'); $shells = App::objects('file', $corePath[0]); $shells = array_diff($shells, $skipFiles); $this->_appendShells('CORE', $shells, $shellList); $appShells = App::objects('Console/Command', null, false); $appShells = array_diff($appShells, $shells, $skipFiles); $this->_appendShells('app', $appShells, $shellList); foreach ($plugins as $plugin) { $pluginShells = App::objects($plugin . '.Console/Command'); $this->_appendShells($plugin, $pluginShells, $shellList); } return array_filter($shellList); } /** * Scan the provided paths for shells, and append them into $shellList * * @param string $type The type of object. * @param array $shells The shell name. * @param array &$shellList List of shells. * @return void */ protected function _appendShells($type, $shells, &$shellList) { foreach ($shells as $shell) { $shellList[$type][] = Inflector::underscore(str_replace('Shell', '', $shell)); } } /** * Return a list of all commands * * @return array */ public function commands() { $shellList = $this->getShellList(); $options = array(); foreach ($shellList as $type => $commands) { $prefix = ''; if (!in_array(strtolower($type), array('app', 'core'))) { $prefix = $type . '.'; } foreach ($commands as $shell) { $options[] = $prefix . $shell; } } return $options; } /** * Return a list of subcommands for a given command * * @param string $commandName The command you want subcommands from. * @return array */ public function subCommands($commandName) { $Shell = $this->getShell($commandName); if (!$Shell) { return array(); } $taskMap = TaskCollection::normalizeObjectArray((array)$Shell->tasks); $return = array_keys($taskMap); $return = array_map('Inflector::underscore', $return); $ShellReflection = new ReflectionClass('AppShell'); $shellMethods = $ShellReflection->getMethods(ReflectionMethod::IS_PUBLIC); $shellMethodNames = array('main', 'help'); foreach ($shellMethods as $method) { $shellMethodNames[] = $method->getName(); } $Reflection = new ReflectionClass($Shell); $methods = $Reflection->getMethods(ReflectionMethod::IS_PUBLIC); $methodNames = array(); foreach ($methods as $method) { $methodNames[] = $method->getName(); } $return += array_diff($methodNames, $shellMethodNames); sort($return); return $return; } /** * Get Shell instance for the given command * * @param mixed $commandName The command you want. * @return mixed */ public function getShell($commandName) { list($pluginDot, $name) = pluginSplit($commandName, true); if (in_array(strtolower($pluginDot), array('app.', 'core.'))) { $commandName = $name; $pluginDot = ''; } if (!in_array($commandName, $this->commands())) { return false; } $name = Inflector::camelize($name); $pluginDot = Inflector::camelize($pluginDot); $class = $name . 'Shell'; App::uses($class, $pluginDot . 'Console/Command'); $Shell = new $class(); $Shell->plugin = trim($pluginDot, '.'); $Shell->initialize(); return $Shell; } /** * Get Shell instance for the given command * * @param mixed $commandName The command to get options for. * @return array */ public function options($commandName) { $Shell = $this->getShell($commandName); if (!$Shell) { $parser = new ConsoleOptionParser(); } else { $parser = $Shell->getOptionParser(); } $options = array(); $array = $parser->options(); foreach ($array as $name => $obj) { $options[] = "--$name"; $short = $obj->short(); if ($short) { $options[] = "-$short"; } } return $options; } } cakephp-2.8.0/lib/Cake/Console/Command/Task/ControllerTask.php000066400000000000000000000400711265552240500241160ustar00rootroot00000000000000path = current(App::path('Controller')); } /** * Execution method always used for tasks * * @return void */ public function execute() { parent::execute(); if (empty($this->args)) { return $this->_interactive(); } if (isset($this->args[0])) { if (!isset($this->connection)) { $this->connection = 'default'; } if (strtolower($this->args[0]) === 'all') { return $this->all(); } $controller = $this->_controllerName($this->args[0]); $actions = ''; if (!empty($this->params['public'])) { $this->out(__d('cake_console', 'Baking basic crud methods for ') . $controller); $actions .= $this->bakeActions($controller); } if (!empty($this->params['admin'])) { $admin = $this->Project->getPrefix(); if ($admin) { $this->out(__d('cake_console', 'Adding %s methods', $admin)); $actions .= "\n" . $this->bakeActions($controller, $admin); } } if (empty($actions)) { $actions = 'scaffold'; } if ($this->bake($controller, $actions)) { if ($this->_checkUnitTest()) { $this->bakeTest($controller); } } } } /** * Bake All the controllers at once. Will only bake controllers for models that exist. * * @return void */ public function all() { $this->interactive = false; $this->listAll($this->connection, false); ClassRegistry::config('Model', array('ds' => $this->connection)); $unitTestExists = $this->_checkUnitTest(); $admin = false; if (!empty($this->params['admin'])) { $admin = $this->Project->getPrefix(); } $controllersCreated = 0; foreach ($this->__tables as $table) { $model = $this->_modelName($table); $controller = $this->_controllerName($model); App::uses($model, 'Model'); if (class_exists($model)) { $actions = $this->bakeActions($controller); if ($admin) { $this->out(__d('cake_console', 'Adding %s methods', $admin)); $actions .= "\n" . $this->bakeActions($controller, $admin); } if ($this->bake($controller, $actions) && $unitTestExists) { $this->bakeTest($controller); } $controllersCreated++; } } if (!$controllersCreated) { $this->out(__d('cake_console', 'No Controllers were baked, Models need to exist before Controllers can be baked.')); } } /** * Interactive * * @return void */ protected function _interactive() { $this->interactive = true; $this->hr(); $this->out(__d('cake_console', "Bake Controller\nPath: %s", $this->getPath())); $this->hr(); if (empty($this->connection)) { $this->connection = $this->DbConfig->getConfig(); } $controllerName = $this->getName(); $this->hr(); $this->out(__d('cake_console', 'Baking %sController', $controllerName)); $this->hr(); $helpers = $components = array(); $actions = ''; $wannaUseSession = 'y'; $wannaBakeAdminCrud = 'n'; $useDynamicScaffold = 'n'; $wannaBakeCrud = 'y'; $question[] = __d('cake_console', "Would you like to build your controller interactively?"); if (file_exists($this->path . $controllerName . 'Controller.php')) { $question[] = __d('cake_console', "Warning: Choosing no will overwrite the %sController.", $controllerName); } $doItInteractive = $this->in(implode("\n", $question), array('y', 'n'), 'y'); if (strtolower($doItInteractive) === 'y') { $this->interactive = true; $useDynamicScaffold = $this->in( __d('cake_console', "Would you like to use dynamic scaffolding?"), array('y', 'n'), 'n' ); if (strtolower($useDynamicScaffold) === 'y') { $wannaBakeCrud = 'n'; $actions = 'scaffold'; } else { list($wannaBakeCrud, $wannaBakeAdminCrud) = $this->_askAboutMethods(); $helpers = $this->doHelpers(); $components = $this->doComponents(); $wannaUseSession = $this->in( __d('cake_console', "Would you like to use Session flash messages?"), array('y', 'n'), 'y' ); if (strtolower($wannaUseSession) === 'y') { array_push($components, 'Session'); } array_unique($components); } } else { list($wannaBakeCrud, $wannaBakeAdminCrud) = $this->_askAboutMethods(); } if (strtolower($wannaBakeCrud) === 'y') { $actions = $this->bakeActions($controllerName, null, strtolower($wannaUseSession) === 'y'); } if (strtolower($wannaBakeAdminCrud) === 'y') { $admin = $this->Project->getPrefix(); $actions .= $this->bakeActions($controllerName, $admin, strtolower($wannaUseSession) === 'y'); } $baked = false; if ($this->interactive === true) { $this->confirmController($controllerName, $useDynamicScaffold, $helpers, $components); $looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n'), 'y'); if (strtolower($looksGood) === 'y') { $baked = $this->bake($controllerName, $actions, $helpers, $components); if ($baked && $this->_checkUnitTest()) { $this->bakeTest($controllerName); } } } else { $baked = $this->bake($controllerName, $actions, $helpers, $components); if ($baked && $this->_checkUnitTest()) { $this->bakeTest($controllerName); } } return $baked; } /** * Confirm a to be baked controller with the user * * @param string $controllerName The name of the controller. * @param string $useDynamicScaffold Whether or not to use dynamic scaffolds. * @param array $helpers The list of helpers to include. * @param array $components The list of components to include. * @return void */ public function confirmController($controllerName, $useDynamicScaffold, $helpers, $components) { $this->out(); $this->hr(); $this->out(__d('cake_console', 'The following controller will be created:')); $this->hr(); $this->out(__d('cake_console', "Controller Name:\n\t%s", $controllerName)); if (strtolower($useDynamicScaffold) === 'y') { $this->out("public \$scaffold;"); } $properties = array( 'helpers' => __d('cake_console', 'Helpers:'), 'components' => __d('cake_console', 'Components:'), ); foreach ($properties as $var => $title) { if (count(${$var})) { $output = ''; $length = count(${$var}); foreach (${$var} as $i => $propElement) { if ($i != $length - 1) { $output .= ucfirst($propElement) . ', '; } else { $output .= ucfirst($propElement); } } $this->out($title . "\n\t" . $output); } } $this->hr(); } /** * Interact with the user and ask about which methods (admin or regular they want to bake) * * @return array Array containing (bakeRegular, bakeAdmin) answers */ protected function _askAboutMethods() { $wannaBakeCrud = $this->in( __d('cake_console', "Would you like to create some basic class methods \n(index(), add(), view(), edit())?"), array('y', 'n'), 'n' ); $wannaBakeAdminCrud = $this->in( __d('cake_console', "Would you like to create the basic class methods for admin routing?"), array('y', 'n'), 'n' ); return array($wannaBakeCrud, $wannaBakeAdminCrud); } /** * Bake scaffold actions * * @param string $controllerName Controller name * @param string $admin Admin route to use * @param bool $wannaUseSession Set to true to use sessions, false otherwise * @return string Baked actions */ public function bakeActions($controllerName, $admin = null, $wannaUseSession = true) { $currentModelName = $modelImport = $this->_modelName($controllerName); $plugin = $this->plugin; if ($plugin) { $plugin .= '.'; } App::uses($modelImport, $plugin . 'Model'); if (!class_exists($modelImport)) { $this->err(__d('cake_console', 'You must have a model for this class to build basic methods. Please try again.')); return $this->_stop(); } $modelObj = ClassRegistry::init($currentModelName); $controllerPath = $this->_controllerPath($controllerName); $pluralName = $this->_pluralName($currentModelName); $singularName = Inflector::variable($currentModelName); $singularHumanName = $this->_singularHumanName($controllerName); $pluralHumanName = $this->_pluralName($controllerName); $displayField = $modelObj->displayField; $primaryKey = $modelObj->primaryKey; $this->Template->set(compact( 'plugin', 'admin', 'controllerPath', 'pluralName', 'singularName', 'singularHumanName', 'pluralHumanName', 'modelObj', 'wannaUseSession', 'currentModelName', 'displayField', 'primaryKey' )); $actions = $this->Template->generate('actions', 'controller_actions'); return $actions; } /** * Assembles and writes a Controller file * * @param string $controllerName Controller name already pluralized and correctly cased. * @param string $actions Actions to add, or set the whole controller to use $scaffold (set $actions to 'scaffold') * @param array $helpers Helpers to use in controller * @param array $components Components to use in controller * @return string Baked controller */ public function bake($controllerName, $actions = '', $helpers = null, $components = null) { $this->out("\n" . __d('cake_console', 'Baking controller class for %s...', $controllerName), 1, Shell::QUIET); $isScaffold = ($actions === 'scaffold') ? true : false; $this->Template->set(array( 'plugin' => $this->plugin, 'pluginPath' => empty($this->plugin) ? '' : $this->plugin . '.' )); if (!in_array('Paginator', (array)$components)) { $components[] = 'Paginator'; } $this->Template->set(compact('controllerName', 'actions', 'helpers', 'components', 'isScaffold')); $contents = $this->Template->generate('classes', 'controller'); $path = $this->getPath(); $filename = $path . $controllerName . 'Controller.php'; if ($this->createFile($filename, $contents)) { return $contents; } return false; } /** * Assembles and writes a unit test file * * @param string $className Controller class name * @return string Baked test */ public function bakeTest($className) { $this->Test->plugin = $this->plugin; $this->Test->connection = $this->connection; $this->Test->interactive = $this->interactive; return $this->Test->bake('Controller', $className); } /** * Interact with the user and get a list of additional helpers * * @return array Helpers that the user wants to use. */ public function doHelpers() { return $this->_doPropertyChoices( __d('cake_console', "Would you like this controller to use other helpers\nbesides HtmlHelper and FormHelper?"), __d('cake_console', "Please provide a comma separated list of the other\nhelper names you'd like to use.\nExample: 'Text, Js, Time'") ); } /** * Interact with the user and get a list of additional components * * @return array Components the user wants to use. */ public function doComponents() { $components = array('Paginator', 'Flash'); return array_merge($components, $this->_doPropertyChoices( __d('cake_console', "Would you like this controller to use other components\nbesides PaginatorComponent and FlashComponent?"), __d('cake_console', "Please provide a comma separated list of the component names you'd like to use.\nExample: 'Acl, Security, RequestHandler'") )); } /** * Common code for property choice handling. * * @param string $prompt A yes/no question to precede the list * @param string $example A question for a comma separated list, with examples. * @return array Array of values for property. */ protected function _doPropertyChoices($prompt, $example) { $proceed = $this->in($prompt, array('y', 'n'), 'n'); $property = array(); if (strtolower($proceed) === 'y') { $propertyList = $this->in($example); $propertyListTrimmed = str_replace(' ', '', $propertyList); $property = explode(',', $propertyListTrimmed); } return array_filter($property); } /** * Outputs and gets the list of possible controllers from database * * @param string $useDbConfig Database configuration name * @return array Set of controllers */ public function listAll($useDbConfig = null) { if ($useDbConfig === null) { $useDbConfig = $this->connection; } $this->__tables = $this->Model->getAllTables($useDbConfig); if ($this->interactive) { $this->out(__d('cake_console', 'Possible Controllers based on your current database:')); $this->hr(); $this->_controllerNames = array(); $count = count($this->__tables); for ($i = 0; $i < $count; $i++) { $this->_controllerNames[] = $this->_controllerName($this->_modelName($this->__tables[$i])); $this->out(sprintf("%2d. %s", $i + 1, $this->_controllerNames[$i])); } return $this->_controllerNames; } return $this->__tables; } /** * Forces the user to specify the controller he wants to bake, and returns the selected controller name. * * @param string $useDbConfig Connection name to get a controller name for. * @return string Controller name */ public function getName($useDbConfig = null) { $controllers = $this->listAll($useDbConfig); $enteredController = ''; while (!$enteredController) { $enteredController = $this->in(__d('cake_console', "Enter a number from the list above,\ntype in the name of another controller, or 'q' to exit"), null, 'q'); if ($enteredController === 'q') { $this->out(__d('cake_console', 'Exit')); return $this->_stop(); } if (!$enteredController || (int)$enteredController > count($controllers)) { $this->err(__d('cake_console', "The Controller name you supplied was empty,\nor the number you selected was not an option. Please try again.")); $enteredController = ''; } } if ((int)$enteredController > 0 && (int)$enteredController <= count($controllers)) { $controllerName = $controllers[(int)$enteredController - 1]; } else { $controllerName = Inflector::camelize($enteredController); } return $controllerName; } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'Bake a controller for a model. Using options you can bake public, admin or both.' ))->addArgument('name', array( 'help' => __d('cake_console', 'Name of the controller to bake. Can use Plugin.name to bake controllers into plugins.') ))->addOption('public', array( 'help' => __d('cake_console', 'Bake a controller with basic crud actions (index, view, add, edit, delete).'), 'boolean' => true ))->addOption('admin', array( 'help' => __d('cake_console', 'Bake a controller with crud actions for one of the Routing.prefixes.'), 'boolean' => true ))->addOption('plugin', array( 'short' => 'p', 'help' => __d('cake_console', 'Plugin to bake the controller into.') ))->addOption('connection', array( 'short' => 'c', 'help' => __d('cake_console', 'The connection the controller\'s model is on.') ))->addOption('theme', array( 'short' => 't', 'help' => __d('cake_console', 'Theme to use when baking code.') ))->addOption('force', array( 'short' => 'f', 'help' => __d('cake_console', 'Force overwriting existing files without prompting.') ))->addSubcommand('all', array( 'help' => __d('cake_console', 'Bake all controllers with CRUD methods.') ))->epilog( __d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.') ); return $parser; } } cakephp-2.8.0/lib/Cake/Console/Command/Task/DbConfigTask.php000066400000000000000000000225751265552240500234570ustar00rootroot00000000000000 'default', 'datasource' => 'Database/Mysql', 'persistent' => 'false', 'host' => 'localhost', 'login' => 'root', 'password' => 'password', 'database' => 'project_name', 'schema' => null, 'prefix' => null, 'encoding' => null, 'port' => null ); /** * String name of the database config class name. * Used for testing. * * @var string */ public $databaseClassName = 'DATABASE_CONFIG'; /** * initialization callback * * @return void */ public function initialize() { $this->path = APP . 'Config' . DS; } /** * Execution method always used for tasks * * @return void */ public function execute() { if (empty($this->args)) { $this->_interactive(); return $this->_stop(); } } /** * Interactive interface * * @return void */ protected function _interactive() { $this->hr(); $this->out(__d('cake_console', 'Database Configuration:')); $this->hr(); $done = false; $dbConfigs = array(); while (!$done) { $name = ''; while (!$name) { $name = $this->in(__d('cake_console', "Name:"), null, 'default'); if (preg_match('/[^a-z0-9_]/i', $name)) { $name = ''; $this->out(__d('cake_console', 'The name may only contain unaccented latin characters, numbers or underscores')); } elseif (preg_match('/^[^a-z_]/i', $name)) { $name = ''; $this->out(__d('cake_console', 'The name must start with an unaccented latin character or an underscore')); } } $datasource = $this->in(__d('cake_console', 'Datasource:'), array('Mysql', 'Postgres', 'Sqlite', 'Sqlserver'), 'Mysql'); $persistent = $this->in(__d('cake_console', 'Persistent Connection?'), array('y', 'n'), 'n'); if (strtolower($persistent) === 'n') { $persistent = 'false'; } else { $persistent = 'true'; } $host = ''; while (!$host) { $host = $this->in(__d('cake_console', 'Database Host:'), null, 'localhost'); } $port = ''; while (!$port) { $port = $this->in(__d('cake_console', 'Port?'), null, 'n'); } if (strtolower($port) === 'n') { $port = null; } $login = ''; while (!$login) { $login = $this->in(__d('cake_console', 'User:'), null, 'root'); } $password = ''; $blankPassword = false; while (!$password && !$blankPassword) { $password = $this->in(__d('cake_console', 'Password:')); if (!$password) { $blank = $this->in(__d('cake_console', 'The password you supplied was empty. Use an empty password?'), array('y', 'n'), 'n'); if ($blank === 'y') { $blankPassword = true; } } } $database = ''; while (!$database) { $database = $this->in(__d('cake_console', 'Database Name:'), null, 'cake'); } $prefix = ''; while (!$prefix) { $prefix = $this->in(__d('cake_console', 'Table Prefix?'), null, 'n'); } if (strtolower($prefix) === 'n') { $prefix = null; } $encoding = ''; while (!$encoding) { $encoding = $this->in(__d('cake_console', 'Table encoding?'), null, 'n'); } if (strtolower($encoding) === 'n') { $encoding = null; } $schema = ''; if ($datasource === 'postgres') { while (!$schema) { $schema = $this->in(__d('cake_console', 'Table schema?'), null, 'n'); } } if (strtolower($schema) === 'n') { $schema = null; } $config = compact('name', 'datasource', 'persistent', 'host', 'login', 'password', 'database', 'prefix', 'encoding', 'port', 'schema'); while (!$this->_verify($config)) { $this->_interactive(); } $dbConfigs[] = $config; $doneYet = $this->in(__d('cake_console', 'Do you wish to add another database configuration?'), null, 'n'); if (strtolower($doneYet === 'n')) { $done = true; } } $this->bake($dbConfigs); config('database'); return true; } /** * Output verification message and bake if it looks good * * @param array $config The config data. * @return bool True if user says it looks good, false otherwise */ protected function _verify($config) { $config += $this->_defaultConfig; extract($config); $this->out(); $this->hr(); $this->out(__d('cake_console', 'The following database configuration will be created:')); $this->hr(); $this->out(__d('cake_console', "Name: %s", $name)); $this->out(__d('cake_console', "Datasource: %s", $datasource)); $this->out(__d('cake_console', "Persistent: %s", $persistent)); $this->out(__d('cake_console', "Host: %s", $host)); if ($port) { $this->out(__d('cake_console', "Port: %s", $port)); } $this->out(__d('cake_console', "User: %s", $login)); $this->out(__d('cake_console', "Pass: %s", str_repeat('*', strlen($password)))); $this->out(__d('cake_console', "Database: %s", $database)); if ($prefix) { $this->out(__d('cake_console', "Table prefix: %s", $prefix)); } if ($schema) { $this->out(__d('cake_console', "Schema: %s", $schema)); } if ($encoding) { $this->out(__d('cake_console', "Encoding: %s", $encoding)); } $this->hr(); $looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n'), 'y'); if (strtolower($looksGood) === 'y') { return $config; } return false; } /** * Assembles and writes database.php * * @param array $configs Configuration settings to use * @return bool Success */ public function bake($configs) { if (!is_dir($this->path)) { $this->err(__d('cake_console', '%s not found', $this->path)); return false; } $filename = $this->path . 'database.php'; $oldConfigs = array(); if (file_exists($filename)) { config('database'); $db = new $this->databaseClassName; $temp = get_class_vars(get_class($db)); foreach ($temp as $configName => $info) { $info += $this->_defaultConfig; if (!isset($info['schema'])) { $info['schema'] = null; } if (!isset($info['encoding'])) { $info['encoding'] = null; } if (!isset($info['port'])) { $info['port'] = null; } $info['persistent'] = var_export((bool)$info['persistent'], true); $oldConfigs[] = array( 'name' => $configName, 'datasource' => $info['datasource'], 'persistent' => $info['persistent'], 'host' => $info['host'], 'port' => $info['port'], 'login' => $info['login'], 'password' => $info['password'], 'database' => $info['database'], 'prefix' => $info['prefix'], 'schema' => $info['schema'], 'encoding' => $info['encoding'] ); } } foreach ($oldConfigs as $key => $oldConfig) { foreach ($configs as $config) { if ($oldConfig['name'] === $config['name']) { unset($oldConfigs[$key]); } } } $configs = array_merge($oldConfigs, $configs); $out = "_defaultConfig; extract($config); if (strpos($datasource, 'Database/') === false) { $datasource = "Database/{$datasource}"; } $out .= "\tpublic \${$name} = array(\n"; $out .= "\t\t'datasource' => '{$datasource}',\n"; $out .= "\t\t'persistent' => {$persistent},\n"; $out .= "\t\t'host' => '{$host}',\n"; if ($port) { $out .= "\t\t'port' => {$port},\n"; } $out .= "\t\t'login' => '{$login}',\n"; $out .= "\t\t'password' => '{$password}',\n"; $out .= "\t\t'database' => '{$database}',\n"; if ($schema) { $out .= "\t\t'schema' => '{$schema}',\n"; } if ($prefix) { $out .= "\t\t'prefix' => '{$prefix}',\n"; } if ($encoding) { $out .= "\t\t'encoding' => '{$encoding}'\n"; } $out .= "\t);\n"; } $out .= "}\n"; $filename = $this->path . 'database.php'; return $this->createFile($filename, $out); } /** * Get a user specified Connection name * * @return void */ public function getConfig() { App::uses('ConnectionManager', 'Model'); $configs = ConnectionManager::enumConnectionObjects(); $useDbConfig = key($configs); if (!is_array($configs) || empty($configs)) { return $this->execute(); } $connections = array_keys($configs); if (count($connections) > 1) { $useDbConfig = $this->in(__d('cake_console', 'Use Database Config') . ':', $connections, $useDbConfig); } return $useDbConfig; } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'Bake new database configuration settings.') ); return $parser; } } cakephp-2.8.0/lib/Cake/Console/Command/Task/ExtractTask.php000066400000000000000000000623111265552240500234060ustar00rootroot00000000000000_paths) > 0 ? $this->_paths : array('None'); $message = __d( 'cake_console', "Current paths: %s\nWhat is the path you would like to extract?\n[Q]uit [D]one", implode(', ', $currentPaths) ); $response = $this->in($message, null, $defaultPath); if (strtoupper($response) === 'Q') { $this->err(__d('cake_console', 'Extract Aborted')); return $this->_stop(); } elseif (strtoupper($response) === 'D' && count($this->_paths)) { $this->out(); return; } elseif (strtoupper($response) === 'D') { $this->err(__d('cake_console', 'No directories selected. Please choose a directory.')); } elseif (is_dir($response)) { $this->_paths[] = $response; $defaultPath = 'D'; } else { $this->err(__d('cake_console', 'The directory path you supplied was not found. Please try again.')); } $this->out(); } } /** * Execution method always used for tasks * * @return void */ public function execute() { if (!empty($this->params['exclude'])) { $this->_exclude = explode(',', str_replace('/', DS, $this->params['exclude'])); } if (isset($this->params['files']) && !is_array($this->params['files'])) { $this->_files = explode(',', $this->params['files']); } if (isset($this->params['paths'])) { $this->_paths = explode(',', $this->params['paths']); } elseif (isset($this->params['plugin'])) { $plugin = Inflector::camelize($this->params['plugin']); if (!CakePlugin::loaded($plugin)) { CakePlugin::load($plugin); } $this->_paths = array(CakePlugin::path($plugin)); $this->params['plugin'] = $plugin; } else { $this->_getPaths(); } if (isset($this->params['extract-core'])) { $this->_extractCore = !(strtolower($this->params['extract-core']) === 'no'); } else { $response = $this->in(__d('cake_console', 'Would you like to extract the messages from the CakePHP core?'), array('y', 'n'), 'n'); $this->_extractCore = strtolower($response) === 'y'; } if (!empty($this->params['exclude-plugins']) && $this->_isExtractingApp()) { $this->_exclude = array_merge($this->_exclude, App::path('plugins')); } if (!empty($this->params['ignore-model-validation']) || (!$this->_isExtractingApp() && empty($plugin))) { $this->_extractValidation = false; } if (!empty($this->params['validation-domain'])) { $this->_validationDomain = $this->params['validation-domain']; } if ($this->_extractCore) { $this->_paths[] = CAKE; $this->_exclude = array_merge($this->_exclude, array( CAKE . 'Test', CAKE . 'Console' . DS . 'Templates' )); } if (isset($this->params['output'])) { $this->_output = $this->params['output']; } elseif (isset($this->params['plugin'])) { $this->_output = $this->_paths[0] . DS . 'Locale'; } else { $message = __d('cake_console', "What is the path you would like to output?\n[Q]uit", $this->_paths[0] . DS . 'Locale'); while (true) { $response = $this->in($message, null, rtrim($this->_paths[0], DS) . DS . 'Locale'); if (strtoupper($response) === 'Q') { $this->err(__d('cake_console', 'Extract Aborted')); return $this->_stop(); } elseif ($this->_isPathUsable($response)) { $this->_output = $response . DS; break; } else { $this->err(__d('cake_console', 'The directory path you supplied was not found. Please try again.')); } $this->out(); } } if (isset($this->params['merge'])) { $this->_merge = !(strtolower($this->params['merge']) === 'no'); } else { $this->out(); $response = $this->in(__d('cake_console', 'Would you like to merge all domain and category strings into the default.pot file?'), array('y', 'n'), 'n'); $this->_merge = strtolower($response) === 'y'; } if (empty($this->_files)) { $this->_searchFiles(); } $this->_output = rtrim($this->_output, DS) . DS; if (!$this->_isPathUsable($this->_output)) { $this->err(__d('cake_console', 'The output directory %s was not found or writable.', $this->_output)); return $this->_stop(); } $this->_extract(); } /** * Add a translation to the internal translations property * * Takes care of duplicate translations * * @param string $category The category * @param string $domain The domain * @param string $msgid The message string * @param array $details The file and line references * @return void */ protected function _addTranslation($category, $domain, $msgid, $details = array()) { $context = ''; if (isset($details['msgctxt'])) { $context = $details['msgctxt']; } if (empty($this->_translations[$category][$domain][$msgid][$context])) { $this->_translations[$category][$domain][$msgid][$context] = array( 'msgid_plural' => false, ); } if (isset($details['msgid_plural'])) { $this->_translations[$category][$domain][$msgid][$context]['msgid_plural'] = $details['msgid_plural']; } if (isset($details['file'])) { $line = 0; if (isset($details['line'])) { $line = $details['line']; } $this->_translations[$category][$domain][$msgid][$context]['references'][$details['file']][] = $line; } } /** * Extract text * * @return void */ protected function _extract() { $this->out(); $this->out(); $this->out(__d('cake_console', 'Extracting...')); $this->hr(); $this->out(__d('cake_console', 'Paths:')); foreach ($this->_paths as $path) { $this->out(' ' . $path); } $this->out(__d('cake_console', 'Output Directory: ') . $this->_output); $this->hr(); $this->_extractTokens(); $this->_extractValidationMessages(); $this->_buildFiles(); $this->_writeFiles(); $this->_paths = $this->_files = $this->_storage = array(); $this->_translations = $this->_tokens = array(); $this->_extractValidation = true; $this->out(); $this->out(__d('cake_console', 'Done.')); } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'CakePHP Language String Extraction:') )->addOption('app', array( 'help' => __d('cake_console', 'Directory where your application is located.') ))->addOption('paths', array( 'help' => __d('cake_console', 'Comma separated list of paths.') ))->addOption('merge', array( 'help' => __d('cake_console', 'Merge all domain and category strings into the default.po file.'), 'choices' => array('yes', 'no') ))->addOption('no-location', array( 'boolean' => true, 'default' => false, 'help' => __d('cake_console', 'Do not write lines with locations'), ))->addOption('output', array( 'help' => __d('cake_console', 'Full path to output directory.') ))->addOption('files', array( 'help' => __d('cake_console', 'Comma separated list of files.') ))->addOption('exclude-plugins', array( 'boolean' => true, 'default' => true, 'help' => __d('cake_console', 'Ignores all files in plugins if this command is run inside from the same app directory.') ))->addOption('plugin', array( 'help' => __d('cake_console', 'Extracts tokens only from the plugin specified and puts the result in the plugin\'s Locale directory.') ))->addOption('ignore-model-validation', array( 'boolean' => true, 'default' => false, 'help' => __d('cake_console', 'Ignores validation messages in the $validate property.' . ' If this flag is not set and the command is run from the same app directory,' . ' all messages in model validation rules will be extracted as tokens.' ) ))->addOption('validation-domain', array( 'help' => __d('cake_console', 'If set to a value, the localization domain to be used for model validation messages.') ))->addOption('exclude', array( 'help' => __d('cake_console', 'Comma separated list of directories to exclude.' . ' Any path containing a path segment with the provided values will be skipped. E.g. test,vendors' ) ))->addOption('overwrite', array( 'boolean' => true, 'default' => false, 'help' => __d('cake_console', 'Always overwrite existing .pot files.') ))->addOption('extract-core', array( 'help' => __d('cake_console', 'Extract messages from the CakePHP core libs.'), 'choices' => array('yes', 'no') )); return $parser; } /** * Extract tokens out of all files to be processed * * @return void */ protected function _extractTokens() { foreach ($this->_files as $file) { $this->_file = $file; $this->out(__d('cake_console', 'Processing %s...', $file), 1, Shell::VERBOSE); $code = file_get_contents($file); $allTokens = token_get_all($code); $this->_tokens = array(); foreach ($allTokens as $token) { if (!is_array($token) || ($token[0] !== T_WHITESPACE && $token[0] !== T_INLINE_HTML)) { $this->_tokens[] = $token; } } unset($allTokens); $this->_parse('__', array('singular')); $this->_parse('__n', array('singular', 'plural')); $this->_parse('__d', array('domain', 'singular')); $this->_parse('__c', array('singular', 'category')); $this->_parse('__dc', array('domain', 'singular', 'category')); $this->_parse('__dn', array('domain', 'singular', 'plural')); $this->_parse('__dcn', array('domain', 'singular', 'plural', 'count', 'category')); $this->_parse('__x', array('context', 'singular')); $this->_parse('__xn', array('context', 'singular', 'plural')); $this->_parse('__dx', array('domain', 'context', 'singular')); $this->_parse('__dxc', array('domain', 'context', 'singular', 'category')); $this->_parse('__dxn', array('domain', 'context', 'singular', 'plural')); $this->_parse('__dxcn', array('domain', 'context', 'singular', 'plural', 'count', 'category')); $this->_parse('__xc', array('context', 'singular', 'category')); } } /** * Parse tokens * * @param string $functionName Function name that indicates translatable string (e.g: '__') * @param array $map Array containing what variables it will find (e.g: category, domain, singular, plural) * @return void */ protected function _parse($functionName, $map) { $count = 0; $categories = array('LC_ALL', 'LC_COLLATE', 'LC_CTYPE', 'LC_MONETARY', 'LC_NUMERIC', 'LC_TIME', 'LC_MESSAGES'); $tokenCount = count($this->_tokens); while (($tokenCount - $count) > 1) { $countToken = $this->_tokens[$count]; $firstParenthesis = $this->_tokens[$count + 1]; if (!is_array($countToken)) { $count++; continue; } list($type, $string, $line) = $countToken; if (($type == T_STRING) && ($string === $functionName) && ($firstParenthesis === '(')) { $position = $count; $depth = 0; while (!$depth) { if ($this->_tokens[$position] === '(') { $depth++; } elseif ($this->_tokens[$position] === ')') { $depth--; } $position++; } $mapCount = count($map); $strings = $this->_getStrings($position, $mapCount); if ($mapCount === count($strings)) { extract(array_combine($map, $strings)); $category = isset($category) ? $category : 6; $category = (int)$category; $categoryName = $categories[$category]; $domain = isset($domain) ? $domain : 'default'; $details = array( 'file' => $this->_file, 'line' => $line, ); if (isset($plural)) { $details['msgid_plural'] = $plural; } if (isset($context)) { $details['msgctxt'] = $context; } // Skip LC_TIME files as we use a special file format for them. if ($categoryName !== 'LC_TIME') { $this->_addTranslation($categoryName, $domain, $singular, $details); } } elseif (!is_array($this->_tokens[$count - 1]) || $this->_tokens[$count - 1][0] != T_FUNCTION) { $this->_markerError($this->_file, $line, $functionName, $count); } } $count++; } } /** * Looks for models in the application and extracts the validation messages * to be added to the translation map * * @return void */ protected function _extractValidationMessages() { if (!$this->_extractValidation) { return; } $plugins = array(null); if (empty($this->params['exclude-plugins'])) { $plugins = array_merge($plugins, App::objects('plugin', null, false)); } foreach ($plugins as $plugin) { $this->_extractPluginValidationMessages($plugin); } } /** * Extract validation messages from application or plugin models * * @param string $plugin Plugin name or `null` to process application models * @return void */ protected function _extractPluginValidationMessages($plugin = null) { App::uses('AppModel', 'Model'); if (!empty($plugin)) { if (!CakePlugin::loaded($plugin)) { return; } App::uses($plugin . 'AppModel', $plugin . '.Model'); $plugin = $plugin . '.'; } $models = App::objects($plugin . 'Model', null, false); foreach ($models as $model) { App::uses($model, $plugin . 'Model'); $reflection = new ReflectionClass($model); if (!$reflection->isSubClassOf('Model')) { continue; } $properties = $reflection->getDefaultProperties(); $validate = $properties['validate']; if (empty($validate)) { continue; } $file = $reflection->getFileName(); $domain = $this->_validationDomain; if (!empty($properties['validationDomain'])) { $domain = $properties['validationDomain']; } foreach ($validate as $field => $rules) { $this->_processValidationRules($field, $rules, $file, $domain); } } } /** * Process a validation rule for a field and looks for a message to be added * to the translation map * * @param string $field the name of the field that is being processed * @param array $rules the set of validation rules for the field * @param string $file the file name where this validation rule was found * @param string $domain default domain to bind the validations to * @param string $category the translation category * @return void */ protected function _processValidationRules($field, $rules, $file, $domain, $category = 'LC_MESSAGES') { if (!is_array($rules)) { return; } $dims = Hash::dimensions($rules); if ($dims === 1 || ($dims === 2 && isset($rules['message']))) { $rules = array($rules); } foreach ($rules as $rule => $validateProp) { $msgid = null; if (isset($validateProp['message'])) { if (is_array($validateProp['message'])) { $msgid = $validateProp['message'][0]; } else { $msgid = $validateProp['message']; } } elseif (is_string($rule)) { $msgid = $rule; } if ($msgid) { $msgid = $this->_formatString(sprintf("'%s'", $msgid)); $details = array( 'file' => $file, 'line' => 'validation for field ' . $field ); $this->_addTranslation($category, $domain, $msgid, $details); } } } /** * Build the translate template file contents out of obtained strings * * @return void */ protected function _buildFiles() { $paths = $this->_paths; $paths[] = realpath(APP) . DS; usort($paths, function ($a, $b) { return strlen($b) - strlen($a); }); foreach ($this->_translations as $category => $domains) { foreach ($domains as $domain => $translations) { foreach ($translations as $msgid => $contexts) { foreach ($contexts as $context => $details) { $plural = $details['msgid_plural']; $header = ''; if (empty($this->params['no-location'])) { $files = $details['references']; $occurrences = array(); foreach ($files as $file => $lines) { $lines = array_unique($lines); $occurrences[] = $file . ':' . implode(';', $lines); } $occurrences = implode("\n#: ", $occurrences); $header = '#: ' . str_replace(DS, '/', str_replace($paths, '', $occurrences)) . "\n"; } $sentence = ''; if ($context) { $sentence .= "msgctxt \"{$context}\"\n"; } if ($plural === false) { $sentence .= "msgid \"{$msgid}\"\n"; $sentence .= "msgstr \"\"\n\n"; } else { $sentence .= "msgid \"{$msgid}\"\n"; $sentence .= "msgid_plural \"{$plural}\"\n"; $sentence .= "msgstr[0] \"\"\n"; $sentence .= "msgstr[1] \"\"\n\n"; } $this->_store($category, $domain, $header, $sentence); if (($category !== 'LC_MESSAGES' || $domain !== 'default') && $this->_merge) { $this->_store('LC_MESSAGES', 'default', $header, $sentence); } } } } } } /** * Prepare a file to be stored * * @param string $category The category * @param string $domain The domain * @param string $header The header content. * @param string $sentence The sentence to store. * @return void */ protected function _store($category, $domain, $header, $sentence) { if (!isset($this->_storage[$category])) { $this->_storage[$category] = array(); } if (!isset($this->_storage[$category][$domain])) { $this->_storage[$category][$domain] = array(); } if (!isset($this->_storage[$category][$domain][$sentence])) { $this->_storage[$category][$domain][$sentence] = $header; } else { $this->_storage[$category][$domain][$sentence] .= $header; } } /** * Write the files that need to be stored * * @return void */ protected function _writeFiles() { $overwriteAll = false; if (!empty($this->params['overwrite'])) { $overwriteAll = true; } foreach ($this->_storage as $category => $domains) { foreach ($domains as $domain => $sentences) { $output = $this->_writeHeader(); foreach ($sentences as $sentence => $header) { $output .= $header . $sentence; } $filename = $domain . '.pot'; if ($category === 'LC_MESSAGES') { $File = new File($this->_output . $filename); } else { new Folder($this->_output . $category, true); $File = new File($this->_output . $category . DS . $filename); } $response = ''; while ($overwriteAll === false && $File->exists() && strtoupper($response) !== 'Y') { $this->out(); $response = $this->in( __d('cake_console', 'Error: %s already exists in this location. Overwrite? [Y]es, [N]o, [A]ll', $filename), array('y', 'n', 'a'), 'y' ); if (strtoupper($response) === 'N') { $response = ''; while (!$response) { $response = $this->in(__d('cake_console', "What would you like to name this file?"), null, 'new_' . $filename); $File = new File($this->_output . $response); $filename = $response; } } elseif (strtoupper($response) === 'A') { $overwriteAll = true; } } $File->write($output); $File->close(); } } } /** * Build the translation template header * * @return string Translation template header */ protected function _writeHeader() { $output = "# LANGUAGE translation of CakePHP Application\n"; $output .= "# Copyright YEAR NAME \n"; $output .= "#\n"; $output .= "#, fuzzy\n"; $output .= "msgid \"\"\n"; $output .= "msgstr \"\"\n"; $output .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n"; $output .= "\"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\\n\"\n"; $output .= "\"Last-Translator: NAME \\n\"\n"; $output .= "\"Language-Team: LANGUAGE \\n\"\n"; $output .= "\"MIME-Version: 1.0\\n\"\n"; $output .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n"; $output .= "\"Content-Transfer-Encoding: 8bit\\n\"\n"; $output .= "\"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n\"\n\n"; return $output; } /** * Get the strings from the position forward * * @param int &$position Actual position on tokens array * @param int $target Number of strings to extract * @return array Strings extracted */ protected function _getStrings(&$position, $target) { $strings = array(); $count = count($strings); while ($count < $target && ($this->_tokens[$position] === ',' || $this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING || $this->_tokens[$position][0] == T_LNUMBER)) { $count = count($strings); if ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING && $this->_tokens[$position + 1] === '.') { $string = ''; while ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING || $this->_tokens[$position] === '.') { if ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING) { $string .= $this->_formatString($this->_tokens[$position][1]); } $position++; } $strings[] = $string; } elseif ($this->_tokens[$position][0] == T_CONSTANT_ENCAPSED_STRING) { $strings[] = $this->_formatString($this->_tokens[$position][1]); } elseif ($this->_tokens[$position][0] == T_LNUMBER) { $strings[] = $this->_tokens[$position][1]; } $position++; } return $strings; } /** * Format a string to be added as a translatable string * * @param string $string String to format * @return string Formatted string */ protected function _formatString($string) { $quote = substr($string, 0, 1); $string = substr($string, 1, -1); if ($quote === '"') { $string = stripcslashes($string); } else { $string = strtr($string, array("\\'" => "'", "\\\\" => "\\")); } $string = str_replace("\r\n", "\n", $string); return addcslashes($string, "\0..\37\\\""); } /** * Indicate an invalid marker on a processed file * * @param string $file File where invalid marker resides * @param int $line Line number * @param string $marker Marker found * @param int $count Count * @return void */ protected function _markerError($file, $line, $marker, $count) { $this->err(__d('cake_console', "Invalid marker content in %s:%s\n* %s(", $file, $line, $marker)); $count += 2; $tokenCount = count($this->_tokens); $parenthesis = 1; while ((($tokenCount - $count) > 0) && $parenthesis) { if (is_array($this->_tokens[$count])) { $this->err($this->_tokens[$count][1], false); } else { $this->err($this->_tokens[$count], false); if ($this->_tokens[$count] === '(') { $parenthesis++; } if ($this->_tokens[$count] === ')') { $parenthesis--; } } $count++; } $this->err("\n", true); } /** * Search files that may contain translatable strings * * @return void */ protected function _searchFiles() { $pattern = false; if (!empty($this->_exclude)) { $exclude = array(); foreach ($this->_exclude as $e) { if (DS !== '\\' && $e[0] !== DS) { $e = DS . $e; } $exclude[] = preg_quote($e, '/'); } $pattern = '/' . implode('|', $exclude) . '/'; } foreach ($this->_paths as $i => $path) { $this->_paths[$i] = realpath($path) . DS; $Folder = new Folder($this->_paths[$i]); $files = $Folder->findRecursive('.*\.(php|ctp|thtml|inc|tpl)', true); if (!empty($pattern)) { $files = preg_grep($pattern, $files, PREG_GREP_INVERT); $files = array_values($files); } $this->_files = array_merge($this->_files, $files); } $this->_files = array_unique($this->_files); } /** * Returns whether this execution is meant to extract string only from directories in folder represented by the * APP constant, i.e. this task is extracting strings from same application. * * @return bool */ protected function _isExtractingApp() { return $this->_paths === array(APP); } /** * Checks whether or not a given path is usable for writing. * * @param string $path Path to folder * @return bool true if it exists and is writable, false otherwise */ protected function _isPathUsable($path) { return is_dir($path) && is_writable($path); } } cakephp-2.8.0/lib/Cake/Console/Command/Task/FixtureTask.php000066400000000000000000000331131265552240500234200ustar00rootroot00000000000000path = APP . 'Test' . DS . 'Fixture' . DS; } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'Generate fixtures for use with the test suite. You can use `bake fixture all` to bake all fixtures.') )->addArgument('name', array( 'help' => __d('cake_console', 'Name of the fixture to bake. Can use Plugin.name to bake plugin fixtures.') ))->addOption('count', array( 'help' => __d('cake_console', 'When using generated data, the number of records to include in the fixture(s).'), 'short' => 'n', 'default' => 1 ))->addOption('connection', array( 'help' => __d('cake_console', 'Which database configuration to use for baking.'), 'short' => 'c', 'default' => 'default' ))->addOption('plugin', array( 'help' => __d('cake_console', 'CamelCased name of the plugin to bake fixtures for.'), 'short' => 'p' ))->addOption('schema', array( 'help' => __d('cake_console', 'Importing schema for fixtures rather than hardcoding it.'), 'short' => 's', 'boolean' => true ))->addOption('theme', array( 'short' => 't', 'help' => __d('cake_console', 'Theme to use when baking code.') ))->addOption('force', array( 'short' => 'f', 'help' => __d('cake_console', 'Force overwriting existing files without prompting.') ))->addOption('records', array( 'help' => __d('cake_console', 'Used with --count and /all commands to pull [n] records from the live tables, ' . 'where [n] is either --count or the default of 10.'), 'short' => 'r', 'boolean' => true ))->epilog( __d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.') ); return $parser; } /** * Execution method always used for tasks * Handles dispatching to interactive, named, or all processes. * * @return void */ public function execute() { parent::execute(); if (empty($this->args)) { $this->_interactive(); } if (isset($this->args[0])) { $this->interactive = false; if (!isset($this->connection)) { $this->connection = 'default'; } if (strtolower($this->args[0]) === 'all') { return $this->all(); } $model = $this->_modelName($this->args[0]); $this->bake($model); } } /** * Bake All the Fixtures at once. Will only bake fixtures for models that exist. * * @return void */ public function all() { $this->interactive = false; $this->Model->interactive = false; $tables = $this->Model->listAll($this->connection, false); foreach ($tables as $table) { $model = $this->_modelName($table); $importOptions = array(); if (!empty($this->params['schema'])) { $importOptions['schema'] = $model; } $this->bake($model, false, $importOptions); } } /** * Interactive baking function * * @return void */ protected function _interactive() { $this->DbConfig->interactive = $this->Model->interactive = $this->interactive = true; $this->hr(); $this->out(__d('cake_console', "Bake Fixture\nPath: %s", $this->getPath())); $this->hr(); if (!isset($this->connection)) { $this->connection = $this->DbConfig->getConfig(); } $modelName = $this->Model->getName($this->connection); $useTable = $this->Model->getTable($modelName, $this->connection); $importOptions = $this->importOptions($modelName); $this->bake($modelName, $useTable, $importOptions); } /** * Interacts with the User to setup an array of import options. For a fixture. * * @param string $modelName Name of model you are dealing with. * @return array Array of import options. */ public function importOptions($modelName) { $options = array(); if (!empty($this->params['schema'])) { $options['schema'] = $modelName; } else { $doSchema = $this->in(__d('cake_console', 'Would you like to import schema for this fixture?'), array('y', 'n'), 'n'); if ($doSchema === 'y') { $options['schema'] = $modelName; } } if (!empty($this->params['records'])) { $doRecords = 'y'; } else { $doRecords = $this->in(__d('cake_console', 'Would you like to use record importing for this fixture?'), array('y', 'n'), 'n'); } if ($doRecords === 'y') { $options['records'] = true; } if ($doRecords === 'n') { $prompt = __d('cake_console', "Would you like to build this fixture with data from %s's table?", $modelName); $fromTable = $this->in($prompt, array('y', 'n'), 'n'); if (strtolower($fromTable) === 'y') { $options['fromTable'] = true; } } return $options; } /** * Assembles and writes a Fixture file * * @param string $model Name of model to bake. * @param string $useTable Name of table to use. * @param array $importOptions Options for public $import * @return string|null Baked fixture content, otherwise null. */ public function bake($model, $useTable = false, $importOptions = array()) { App::uses('CakeSchema', 'Model'); $table = $schema = $records = $import = $modelImport = null; $importBits = array(); if (!$useTable) { $useTable = Inflector::tableize($model); } elseif ($useTable != Inflector::tableize($model)) { $table = $useTable; } if (!empty($importOptions)) { if (isset($importOptions['schema'])) { $modelImport = true; $importBits[] = "'model' => '{$importOptions['schema']}'"; } if (isset($importOptions['records'])) { $importBits[] = "'records' => true"; } if ($this->connection !== 'default') { $importBits[] .= "'connection' => '{$this->connection}'"; } if (!empty($importBits)) { $import = sprintf("array(%s)", implode(', ', $importBits)); } } $this->_Schema = new CakeSchema(); $data = $this->_Schema->read(array('models' => false, 'connection' => $this->connection)); if (!isset($data['tables'][$useTable])) { $this->err("Warning: Could not find the '${useTable}' table for ${model}."); return null; } $tableInfo = $data['tables'][$useTable]; if ($modelImport === null) { $schema = $this->_generateSchema($tableInfo); } if (empty($importOptions['records']) && !isset($importOptions['fromTable'])) { $recordCount = 1; if (isset($this->params['count'])) { $recordCount = $this->params['count']; } $records = $this->_makeRecordString($this->_generateRecords($tableInfo, $recordCount)); } if (!empty($this->params['records']) || isset($importOptions['fromTable'])) { $records = $this->_makeRecordString($this->_getRecordsFromTable($model, $useTable)); } $out = $this->generateFixtureFile($model, compact('records', 'table', 'schema', 'import')); return $out; } /** * Generate the fixture file, and write to disk * * @param string $model name of the model being generated * @param string $otherVars Contents of the fixture file. * @return string Content saved into fixture file. */ public function generateFixtureFile($model, $otherVars) { $defaults = array('table' => null, 'schema' => null, 'records' => null, 'import' => null, 'fields' => null); $vars = array_merge($defaults, $otherVars); $path = $this->getPath(); $filename = Inflector::camelize($model) . 'Fixture.php'; $this->Template->set('model', $model); $this->Template->set($vars); $content = $this->Template->generate('classes', 'fixture'); $this->out("\n" . __d('cake_console', 'Baking test fixture for %s...', $model), 1, Shell::QUIET); $this->createFile($path . $filename, $content); return $content; } /** * Get the path to the fixtures. * * @return string Path for the fixtures */ public function getPath() { $path = $this->path; if (isset($this->plugin)) { $path = $this->_pluginPath($this->plugin) . 'Test' . DS . 'Fixture' . DS; } return $path; } /** * Generates a string representation of a schema. * * @param array $tableInfo Table schema array * @return string fields definitions */ protected function _generateSchema($tableInfo) { $schema = trim($this->_Schema->generateTable('f', $tableInfo), "\n"); return substr($schema, 13, -1); } /** * Generate String representation of Records * * @param array $tableInfo Table schema array * @param int $recordCount The number of records to generate. * @return array Array of records to use in the fixture. */ protected function _generateRecords($tableInfo, $recordCount = 1) { $records = array(); for ($i = 0; $i < $recordCount; $i++) { $record = array(); foreach ($tableInfo as $field => $fieldInfo) { if (empty($fieldInfo['type'])) { continue; } $insert = ''; switch ($fieldInfo['type']) { case 'integer': case 'float': $insert = $i + 1; break; case 'string': case 'binary': $isPrimaryUuid = ( isset($fieldInfo['key']) && strtolower($fieldInfo['key']) === 'primary' && isset($fieldInfo['length']) && $fieldInfo['length'] == 36 ); if ($isPrimaryUuid) { $insert = CakeText::uuid(); } else { $insert = "Lorem ipsum dolor sit amet"; if (!empty($fieldInfo['length'])) { $insert = substr($insert, 0, (int)$fieldInfo['length'] - 2); } } break; case 'timestamp': $insert = time(); break; case 'datetime': $insert = date('Y-m-d H:i:s'); break; case 'date': $insert = date('Y-m-d'); break; case 'time': $insert = date('H:i:s'); break; case 'boolean': $insert = 1; break; case 'text': $insert = "Lorem ipsum dolor sit amet, aliquet feugiat."; $insert .= " Convallis morbi fringilla gravida,"; $insert .= " phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin"; $insert .= " venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla"; $insert .= " vestibulum massa neque ut et, id hendrerit sit,"; $insert .= " feugiat in taciti enim proin nibh, tempor dignissim, rhoncus"; $insert .= " duis vestibulum nunc mattis convallis."; break; } $record[$field] = $insert; } $records[] = $record; } return $records; } /** * Convert a $records array into a string. * * @param array $records Array of records to be converted to string * @return string A string value of the $records array. */ protected function _makeRecordString($records) { $out = "array(\n"; foreach ($records as $record) { $values = array(); foreach ($record as $field => $value) { $val = var_export($value, true); if ($val === 'NULL') { $val = 'null'; } $values[] = "\t\t\t'$field' => $val"; } $out .= "\t\tarray(\n"; $out .= implode(",\n", $values); $out .= "\n\t\t),\n"; } $out .= "\t)"; return $out; } /** * Interact with the user to get a custom SQL condition and use that to extract data * to build a fixture. * * @param string $modelName name of the model to take records from. * @param string $useTable Name of table to use. * @return array Array of records. */ protected function _getRecordsFromTable($modelName, $useTable = null) { $modelObject = new Model(array('name' => $modelName, 'table' => $useTable, 'ds' => $this->connection)); if ($this->interactive) { $condition = null; $prompt = __d('cake_console', "Please provide a SQL fragment to use as conditions\nExample: WHERE 1=1"); while (!$condition) { $condition = $this->in($prompt, null, 'WHERE 1=1'); } $recordsFound = $modelObject->find('count', array( 'conditions' => $condition, 'recursive' => -1, )); $prompt = __d('cake_console', "How many records do you want to import?"); $recordCount = $this->in($prompt, null, ($recordsFound < 10 ) ? $recordsFound : 10); } else { $condition = 'WHERE 1=1'; $recordCount = (isset($this->params['count']) ? $this->params['count'] : 10); } $records = $modelObject->find('all', array( 'conditions' => $condition, 'recursive' => -1, 'limit' => $recordCount )); $schema = $modelObject->schema(true); $out = array(); foreach ($records as $record) { $row = array(); foreach ($record[$modelObject->alias] as $field => $value) { if ($schema[$field]['type'] === 'boolean') { $value = (int)(bool)$value; } $row[$field] = $value; } $out[] = $row; } return $out; } } cakephp-2.8.0/lib/Cake/Console/Command/Task/ModelTask.php000066400000000000000000001003041265552240500230270ustar00rootroot00000000000000path = current(App::path('Model')); } /** * Execution method always used for tasks * * @return void */ public function execute() { parent::execute(); if (empty($this->args)) { $this->_interactive(); } if (!empty($this->args[0])) { $this->interactive = false; if (!isset($this->connection)) { $this->connection = 'default'; } if (strtolower($this->args[0]) === 'all') { return $this->all(); } $model = $this->_modelName($this->args[0]); $this->listAll($this->connection); $useTable = $this->getTable($model); $object = $this->_getModelObject($model, $useTable); if ($this->bake($object, false)) { if ($this->_checkUnitTest()) { $this->bakeFixture($model, $useTable); $this->bakeTest($model); } } } } /** * Bake all models at once. * * @return void */ public function all() { $this->listAll($this->connection, false); $unitTestExists = $this->_checkUnitTest(); foreach ($this->_tables as $table) { if (in_array($table, $this->skipTables)) { continue; } $modelClass = Inflector::classify($table); $this->out(__d('cake_console', 'Baking %s', $modelClass)); $object = $this->_getModelObject($modelClass, $table); if ($this->bake($object, false) && $unitTestExists) { $this->bakeFixture($modelClass, $table); $this->bakeTest($modelClass); } } } /** * Get a model object for a class name. * * @param string $className Name of class you want model to be. * @param string $table Table name * @return Model Model instance */ protected function _getModelObject($className, $table = null) { if (!$table) { $table = Inflector::tableize($className); } $object = new Model(array('name' => $className, 'table' => $table, 'ds' => $this->connection)); $fields = $object->schema(true); foreach ($fields as $name => $field) { if (isset($field['key']) && $field['key'] === 'primary') { $object->primaryKey = $name; break; } } return $object; } /** * Generate a key value list of options and a prompt. * * @param array $options Array of options to use for the selections. indexes must start at 0 * @param string $prompt Prompt to use for options list. * @param int $default The default option for the given prompt. * @return int Result of user choice. */ public function inOptions($options, $prompt = null, $default = null) { $valid = false; $max = count($options); while (!$valid) { $len = strlen(count($options) + 1); foreach ($options as $i => $option) { $this->out(sprintf("%${len}d. %s", $i + 1, $option)); } if (empty($prompt)) { $prompt = __d('cake_console', 'Make a selection from the choices above'); } $choice = $this->in($prompt, null, $default); if ((int)$choice > 0 && (int)$choice <= $max) { $valid = true; } } return $choice - 1; } /** * Handles interactive baking * * @return bool */ protected function _interactive() { $this->hr(); $this->out(__d('cake_console', "Bake Model\nPath: %s", $this->getPath())); $this->hr(); $this->interactive = true; $primaryKey = 'id'; $validate = $associations = array(); if (empty($this->connection)) { $this->connection = $this->DbConfig->getConfig(); } $currentModelName = $this->getName(); $useTable = $this->getTable($currentModelName); $db = ConnectionManager::getDataSource($this->connection); $fullTableName = $db->fullTableName($useTable); if (!in_array($useTable, $this->_tables)) { $prompt = __d('cake_console', "The table %s doesn't exist or could not be automatically detected\ncontinue anyway?", $useTable); $continue = $this->in($prompt, array('y', 'n')); if (strtolower($continue) === 'n') { return false; } } $tempModel = new Model(array('name' => $currentModelName, 'table' => $useTable, 'ds' => $this->connection)); $knownToExist = false; try { $fields = $tempModel->schema(true); $knownToExist = true; } catch (Exception $e) { $fields = array($tempModel->primaryKey); } if (!array_key_exists('id', $fields)) { $primaryKey = $this->findPrimaryKey($fields); } if ($knownToExist) { $displayField = $tempModel->hasField(array('name', 'title')); if (!$displayField) { $displayField = $this->findDisplayField($tempModel->schema()); } $prompt = __d('cake_console', "Would you like to supply validation criteria \nfor the fields in your model?"); $wannaDoValidation = $this->in($prompt, array('y', 'n'), 'y'); if (array_search($useTable, $this->_tables) !== false && strtolower($wannaDoValidation) === 'y') { $validate = $this->doValidation($tempModel); } $prompt = __d('cake_console', "Would you like to define model associations\n(hasMany, hasOne, belongsTo, etc.)?"); $wannaDoAssoc = $this->in($prompt, array('y', 'n'), 'y'); if (strtolower($wannaDoAssoc) === 'y') { $associations = $this->doAssociations($tempModel); } } $this->out(); $this->hr(); $this->out(__d('cake_console', 'The following Model will be created:')); $this->hr(); $this->out(__d('cake_console', "Name: %s", $currentModelName)); if ($this->connection !== 'default') { $this->out(__d('cake_console', "DB Config: %s", $this->connection)); } if ($fullTableName !== Inflector::tableize($currentModelName)) { $this->out(__d('cake_console', 'DB Table: %s', $fullTableName)); } if ($primaryKey !== 'id') { $this->out(__d('cake_console', 'Primary Key: %s', $primaryKey)); } if (!empty($validate)) { $this->out(__d('cake_console', 'Validation: %s', print_r($validate, true))); } if (!empty($associations)) { $this->out(__d('cake_console', 'Associations:')); $assocKeys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'); foreach ($assocKeys as $assocKey) { $this->_printAssociation($currentModelName, $assocKey, $associations); } } $this->hr(); $looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n'), 'y'); if (strtolower($looksGood) === 'y') { $vars = compact('associations', 'validate', 'primaryKey', 'useTable', 'displayField'); $vars['useDbConfig'] = $this->connection; if ($this->bake($currentModelName, $vars)) { if ($this->_checkUnitTest()) { $this->bakeFixture($currentModelName, $useTable); $this->bakeTest($currentModelName, $useTable, $associations); } } } else { return false; } } /** * Print out all the associations of a particular type * * @param string $modelName Name of the model relations belong to. * @param string $type Name of association you want to see. i.e. 'belongsTo' * @param string $associations Collection of associations. * @return void */ protected function _printAssociation($modelName, $type, $associations) { if (!empty($associations[$type])) { for ($i = 0, $len = count($associations[$type]); $i < $len; $i++) { $out = "\t" . $modelName . ' ' . $type . ' ' . $associations[$type][$i]['alias']; $this->out($out); } } } /** * Finds a primary Key in a list of fields. * * @param array $fields Array of fields that might have a primary key. * @return string Name of field that is a primary key. */ public function findPrimaryKey($fields) { $name = 'id'; foreach ($fields as $name => $field) { if (isset($field['key']) && $field['key'] === 'primary') { break; } } return $this->in(__d('cake_console', 'What is the primaryKey?'), null, $name); } /** * interact with the user to find the displayField value for a model. * * @param array $fields Array of fields to look for and choose as a displayField * @return mixed Name of field to use for displayField or false if the user declines to choose */ public function findDisplayField($fields) { $fieldNames = array_keys($fields); $prompt = __d('cake_console', "A displayField could not be automatically detected\nwould you like to choose one?"); $continue = $this->in($prompt, array('y', 'n')); if (strtolower($continue) === 'n') { return false; } $prompt = __d('cake_console', 'Choose a field from the options above:'); $choice = $this->inOptions($fieldNames, $prompt); return $fieldNames[$choice]; } /** * Handles Generation and user interaction for creating validation. * * @param Model $model Model to have validations generated for. * @return array validate Array of user selected validations. */ public function doValidation($model) { if (!$model instanceof Model) { return false; } $fields = $model->schema(); if (empty($fields)) { return false; } $skipFields = false; $validate = array(); $this->initValidations(); foreach ($fields as $fieldName => $field) { $validation = $this->fieldValidation($fieldName, $field, $model->primaryKey); if (isset($validation['_skipFields'])) { unset($validation['_skipFields']); $skipFields = true; } if (!empty($validation)) { $validate[$fieldName] = $validation; } if ($skipFields) { return $validate; } } return $validate; } /** * Populate the _validations array * * @return void */ public function initValidations() { $options = $choices = array(); if (class_exists('Validation')) { $options = get_class_methods('Validation'); } $deprecatedOptions = array('notEmpty', 'between', 'ssn'); $options = array_diff($options, $deprecatedOptions); sort($options); $default = 1; foreach ($options as $option) { if ($option{0} !== '_') { $choices[$default] = $option; $default++; } } $choices[$default] = 'none'; // Needed since index starts at 1 $this->_validations = $choices; return $choices; } /** * Does individual field validation handling. * * @param string $fieldName Name of field to be validated. * @param array $metaData metadata for field * @param string $primaryKey The primary key field. * @return array Array of validation for the field. */ public function fieldValidation($fieldName, $metaData, $primaryKey = 'id') { $defaultChoice = count($this->_validations); $validate = $alreadyChosen = array(); $prompt = __d('cake_console', "or enter in a valid regex validation string.\nAlternatively [s] skip the rest of the fields.\n" ); $methods = array_flip($this->_validations); $anotherValidator = 'y'; while ($anotherValidator === 'y') { if ($this->interactive) { $this->out(); $this->out(__d('cake_console', 'Field: %s', $fieldName)); $this->out(__d('cake_console', 'Type: %s', $metaData['type'])); $this->hr(); $this->out(__d('cake_console', 'Please select one of the following validation options:')); $this->hr(); $optionText = ''; for ($i = 1, $m = $defaultChoice / 2; $i <= $m; $i++) { $line = sprintf("%2d. %s", $i, $this->_validations[$i]); $optionText .= $line . str_repeat(" ", 31 - strlen($line)); if ($m + $i !== $defaultChoice) { $optionText .= sprintf("%2d. %s\n", $m + $i, $this->_validations[$m + $i]); } } $this->out($optionText); $this->out(__d('cake_console', "%s - Do not do any validation on this field.", $defaultChoice)); $this->hr(); } $guess = $defaultChoice; if ($metaData['null'] != 1 && !in_array($fieldName, array($primaryKey, 'created', 'modified', 'updated'))) { if ($fieldName === 'email') { $guess = $methods['email']; } elseif ($metaData['type'] === 'string' && $metaData['length'] == 36) { $guess = $methods['uuid']; } elseif ($metaData['type'] === 'string') { $guess = $methods['notBlank']; } elseif ($metaData['type'] === 'text') { $guess = $methods['notBlank']; } elseif ($metaData['type'] === 'integer') { $guess = $methods['numeric']; } elseif ($metaData['type'] === 'float') { $guess = $methods['numeric']; } elseif ($metaData['type'] === 'boolean') { $guess = $methods['boolean']; } elseif ($metaData['type'] === 'date') { $guess = $methods['date']; } elseif ($metaData['type'] === 'time') { $guess = $methods['time']; } elseif ($metaData['type'] === 'datetime') { $guess = $methods['datetime']; } elseif ($metaData['type'] === 'inet') { $guess = $methods['ip']; } elseif ($metaData['type'] === 'decimal') { $guess = $methods['decimal']; } } if ($this->interactive === true) { $choice = $this->in($prompt, null, $guess); if ($choice === 's') { $validate['_skipFields'] = true; return $validate; } if (in_array($choice, $alreadyChosen)) { $this->out(__d('cake_console', "You have already chosen that validation rule,\nplease choose again")); continue; } if (!isset($this->_validations[$choice]) && is_numeric($choice)) { $this->out(__d('cake_console', 'Please make a valid selection.')); continue; } $alreadyChosen[] = $choice; } else { $choice = $guess; } if (isset($this->_validations[$choice])) { $validatorName = $this->_validations[$choice]; } else { $validatorName = Inflector::slug($choice); } if ($choice != $defaultChoice) { $validate[$validatorName] = $choice; if (is_numeric($choice) && isset($this->_validations[$choice])) { $validate[$validatorName] = $this->_validations[$choice]; } } $anotherValidator = 'n'; if ($this->interactive && $choice != $defaultChoice) { $anotherValidator = $this->in(__d('cake_console', "Would you like to add another validation rule\n" . "or skip the rest of the fields?"), array('y', 'n', 's'), 'n'); if ($anotherValidator === 's') { $validate['_skipFields'] = true; return $validate; } } } return $validate; } /** * Handles associations * * @param Model $model The model object * @return array Associations */ public function doAssociations($model) { if (!$model instanceof Model) { return false; } if ($this->interactive === true) { $this->out(__d('cake_console', 'One moment while the associations are detected.')); } $fields = $model->schema(true); if (empty($fields)) { return array(); } if (empty($this->_tables)) { $this->_tables = (array)$this->getAllTables(); } $associations = array( 'belongsTo' => array(), 'hasMany' => array(), 'hasOne' => array(), 'hasAndBelongsToMany' => array() ); $associations = $this->findBelongsTo($model, $associations); $associations = $this->findHasOneAndMany($model, $associations); $associations = $this->findHasAndBelongsToMany($model, $associations); if ($this->interactive !== true) { unset($associations['hasOne']); } if ($this->interactive === true) { $this->hr(); if (empty($associations)) { $this->out(__d('cake_console', 'None found.')); } else { $this->out(__d('cake_console', 'Please confirm the following associations:')); $this->hr(); $associations = $this->confirmAssociations($model, $associations); } $associations = $this->doMoreAssociations($model, $associations); } return $associations; } /** * Handles behaviors * * @param Model $model The model object. * @return array Behaviors */ public function doActsAs($model) { if (!$model instanceof Model) { return false; } $behaviors = array(); $fields = $model->schema(true); if (empty($fields)) { return array(); } if (isset($fields['lft']) && $fields['lft']['type'] === 'integer' && isset($fields['rght']) && $fields['rght']['type'] === 'integer' && isset($fields['parent_id'])) { $behaviors[] = 'Tree'; } return $behaviors; } /** * Find belongsTo relations and add them to the associations list. * * @param Model $model Model instance of model being generated. * @param array $associations Array of in progress associations * @return array Associations with belongsTo added in. */ public function findBelongsTo(Model $model, $associations) { $fieldNames = array_keys($model->schema(true)); foreach ($fieldNames as $fieldName) { $offset = substr($fieldName, -3) === '_id'; if ($fieldName != $model->primaryKey && $fieldName !== 'parent_id' && $offset !== false) { $tmpModelName = $this->_modelNameFromKey($fieldName); $associations['belongsTo'][] = array( 'alias' => $tmpModelName, 'className' => $tmpModelName, 'foreignKey' => $fieldName, ); } elseif ($fieldName === 'parent_id') { $associations['belongsTo'][] = array( 'alias' => 'Parent' . $model->name, 'className' => $model->name, 'foreignKey' => $fieldName, ); } } return $associations; } /** * Find the hasOne and hasMany relations and add them to associations list * * @param Model $model Model instance being generated * @param array $associations Array of in progress associations * @return array Associations with hasOne and hasMany added in. */ public function findHasOneAndMany(Model $model, $associations) { $foreignKey = $this->_modelKey($model->name); foreach ($this->_tables as $otherTable) { $tempOtherModel = $this->_getModelObject($this->_modelName($otherTable), $otherTable); $tempFieldNames = array_keys($tempOtherModel->schema(true)); $pattern = '/_' . preg_quote($model->table, '/') . '|' . preg_quote($model->table, '/') . '_/'; $possibleJoinTable = preg_match($pattern, $otherTable); if ($possibleJoinTable) { continue; } foreach ($tempFieldNames as $fieldName) { $assoc = false; if ($fieldName !== $model->primaryKey && $fieldName === $foreignKey) { $assoc = array( 'alias' => $tempOtherModel->name, 'className' => $tempOtherModel->name, 'foreignKey' => $fieldName ); } elseif ($otherTable === $model->table && $fieldName === 'parent_id') { $assoc = array( 'alias' => 'Child' . $model->name, 'className' => $model->name, 'foreignKey' => $fieldName ); } if ($assoc) { $associations['hasOne'][] = $assoc; $associations['hasMany'][] = $assoc; } } } return $associations; } /** * Find the hasAndBelongsToMany relations and add them to associations list * * @param Model $model Model instance being generated * @param array $associations Array of in-progress associations * @return array Associations with hasAndBelongsToMany added in. */ public function findHasAndBelongsToMany(Model $model, $associations) { $foreignKey = $this->_modelKey($model->name); foreach ($this->_tables as $otherTable) { $tableName = null; $offset = strpos($otherTable, $model->table . '_'); $otherOffset = strpos($otherTable, '_' . $model->table); if ($offset !== false) { $tableName = substr($otherTable, strlen($model->table . '_')); } elseif ($otherOffset !== false) { $tableName = substr($otherTable, 0, $otherOffset); } if ($tableName && in_array($tableName, $this->_tables)) { $habtmName = $this->_modelName($tableName); $associations['hasAndBelongsToMany'][] = array( 'alias' => $habtmName, 'className' => $habtmName, 'foreignKey' => $foreignKey, 'associationForeignKey' => $this->_modelKey($habtmName), 'joinTable' => $otherTable ); } } return $associations; } /** * Interact with the user and confirm associations. * * @param array $model Temporary Model instance. * @param array $associations Array of associations to be confirmed. * @return array Array of confirmed associations */ public function confirmAssociations(Model $model, $associations) { foreach ($associations as $type => $settings) { if (!empty($associations[$type])) { foreach ($associations[$type] as $i => $assoc) { $prompt = "{$model->name} {$type} {$assoc['alias']}?"; $response = $this->in($prompt, array('y', 'n'), 'y'); if (strtolower($response) === 'n') { unset($associations[$type][$i]); } elseif ($type === 'hasMany') { unset($associations['hasOne'][$i]); } } $associations[$type] = array_merge($associations[$type]); } } return $associations; } /** * Interact with the user and generate additional non-conventional associations * * @param Model $model Temporary model instance * @param array $associations Array of associations. * @return array Array of associations. */ public function doMoreAssociations(Model $model, $associations) { $prompt = __d('cake_console', 'Would you like to define some additional model associations?'); $wannaDoMoreAssoc = $this->in($prompt, array('y', 'n'), 'n'); $possibleKeys = $this->_generatePossibleKeys(); while (strtolower($wannaDoMoreAssoc) === 'y') { $assocs = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'); $this->out(__d('cake_console', 'What is the association type?')); $assocType = (int)$this->inOptions($assocs, __d('cake_console', 'Enter a number')); $this->out(__d('cake_console', "For the following options be very careful to match your setup exactly.\n" . "Any spelling mistakes will cause errors.")); $this->hr(); $alias = $this->in(__d('cake_console', 'What is the alias for this association?')); $className = $this->in(__d('cake_console', 'What className will %s use?', $alias), null, $alias); if ($assocType === 0) { if (!empty($possibleKeys[$model->table])) { $showKeys = $possibleKeys[$model->table]; } else { $showKeys = null; } $suggestedForeignKey = $this->_modelKey($alias); } else { $otherTable = Inflector::tableize($className); if (in_array($otherTable, $this->_tables)) { if ($assocType < 3) { if (!empty($possibleKeys[$otherTable])) { $showKeys = $possibleKeys[$otherTable]; } else { $showKeys = null; } } else { $showKeys = null; } } else { $otherTable = $this->in(__d('cake_console', 'What is the table for this model?')); $showKeys = $possibleKeys[$otherTable]; } $suggestedForeignKey = $this->_modelKey($model->name); } if (!empty($showKeys)) { $this->out(__d('cake_console', 'A helpful List of possible keys')); $foreignKey = $this->inOptions($showKeys, __d('cake_console', 'What is the foreignKey?')); $foreignKey = $showKeys[(int)$foreignKey]; } if (!isset($foreignKey)) { $foreignKey = $this->in(__d('cake_console', 'What is the foreignKey? Specify your own.'), null, $suggestedForeignKey); } if ($assocType === 3) { $associationForeignKey = $this->in(__d('cake_console', 'What is the associationForeignKey?'), null, $this->_modelKey($model->name)); $joinTable = $this->in(__d('cake_console', 'What is the joinTable?')); } $associations[$assocs[$assocType]] = array_values((array)$associations[$assocs[$assocType]]); $count = count($associations[$assocs[$assocType]]); $i = ($count > 0) ? $count : 0; $associations[$assocs[$assocType]][$i]['alias'] = $alias; $associations[$assocs[$assocType]][$i]['className'] = $className; $associations[$assocs[$assocType]][$i]['foreignKey'] = $foreignKey; if ($assocType === 3) { $associations[$assocs[$assocType]][$i]['associationForeignKey'] = $associationForeignKey; $associations[$assocs[$assocType]][$i]['joinTable'] = $joinTable; } $wannaDoMoreAssoc = $this->in(__d('cake_console', 'Define another association?'), array('y', 'n'), 'y'); } return $associations; } /** * Finds all possible keys to use on custom associations. * * @return array Array of tables and possible keys */ protected function _generatePossibleKeys() { $possible = array(); foreach ($this->_tables as $otherTable) { $tempOtherModel = new Model(array('table' => $otherTable, 'ds' => $this->connection)); $modelFieldsTemp = $tempOtherModel->schema(true); foreach ($modelFieldsTemp as $fieldName => $field) { if ($field['type'] === 'integer' || $field['type'] === 'string') { $possible[$otherTable][] = $fieldName; } } } return $possible; } /** * Assembles and writes a Model file. * * @param string|object $name Model name or object * @param array|bool $data if array and $name is not an object assume bake data, otherwise boolean. * @return string */ public function bake($name, $data = array()) { if ($name instanceof Model) { if (!$data) { $data = array(); $data['associations'] = $this->doAssociations($name); $data['validate'] = $this->doValidation($name); $data['actsAs'] = $this->doActsAs($name); } $data['primaryKey'] = $name->primaryKey; $data['useTable'] = $name->table; $data['useDbConfig'] = $name->useDbConfig; $data['name'] = $name = $name->name; } else { $data['name'] = $name; } $defaults = array( 'associations' => array(), 'actsAs' => array(), 'validate' => array(), 'primaryKey' => 'id', 'useTable' => null, 'useDbConfig' => 'default', 'displayField' => null ); $data = array_merge($defaults, $data); $pluginPath = ''; if ($this->plugin) { $pluginPath = $this->plugin . '.'; } $this->Template->set($data); $this->Template->set(array( 'plugin' => $this->plugin, 'pluginPath' => $pluginPath )); $out = $this->Template->generate('classes', 'model'); $path = $this->getPath(); $filename = $path . $name . '.php'; $this->out("\n" . __d('cake_console', 'Baking model class for %s...', $name), 1, Shell::QUIET); $this->createFile($filename, $out); ClassRegistry::flush(); return $out; } /** * Assembles and writes a unit test file * * @param string $className Model class name * @return string */ public function bakeTest($className) { $this->Test->interactive = $this->interactive; $this->Test->plugin = $this->plugin; $this->Test->connection = $this->connection; return $this->Test->bake('Model', $className); } /** * outputs the a list of possible models or controllers from database * * @param string $useDbConfig Database configuration name * @return array */ public function listAll($useDbConfig = null) { $this->_tables = $this->getAllTables($useDbConfig); $this->_modelNames = array(); $count = count($this->_tables); for ($i = 0; $i < $count; $i++) { $this->_modelNames[] = $this->_modelName($this->_tables[$i]); } if ($this->interactive === true) { $this->out(__d('cake_console', 'Possible Models based on your current database:')); $len = strlen($count + 1); for ($i = 0; $i < $count; $i++) { $this->out(sprintf("%${len}d. %s", $i + 1, $this->_modelNames[$i])); } } return $this->_tables; } /** * Interact with the user to determine the table name of a particular model * * @param string $modelName Name of the model you want a table for. * @param string $useDbConfig Name of the database config you want to get tables from. * @return string Table name */ public function getTable($modelName, $useDbConfig = null) { $useTable = Inflector::tableize($modelName); if (in_array($modelName, $this->_modelNames)) { $modelNames = array_flip($this->_modelNames); $useTable = $this->_tables[$modelNames[$modelName]]; } if ($this->interactive === true) { if (!isset($useDbConfig)) { $useDbConfig = $this->connection; } $db = ConnectionManager::getDataSource($useDbConfig); $fullTableName = $db->fullTableName($useTable, false); $tableIsGood = false; if (array_search($useTable, $this->_tables) === false) { $this->out(); $this->out(__d('cake_console', "Given your model named '%s',\nCake would expect a database table named '%s'", $modelName, $fullTableName)); $tableIsGood = $this->in(__d('cake_console', 'Do you want to use this table?'), array('y', 'n'), 'y'); } if (strtolower($tableIsGood) === 'n') { $useTable = $this->in(__d('cake_console', 'What is the name of the table (without prefix)?')); } } return $useTable; } /** * Get an Array of all the tables in the supplied connection * will halt the script if no tables are found. * * @param string $useDbConfig Connection name to scan. * @return array Array of tables in the database. */ public function getAllTables($useDbConfig = null) { if (!isset($useDbConfig)) { $useDbConfig = $this->connection; } $tables = array(); $db = ConnectionManager::getDataSource($useDbConfig); $db->cacheSources = false; $usePrefix = empty($db->config['prefix']) ? '' : $db->config['prefix']; if ($usePrefix) { foreach ($db->listSources() as $table) { if (!strncmp($table, $usePrefix, strlen($usePrefix))) { $tables[] = substr($table, strlen($usePrefix)); } } } else { $tables = $db->listSources(); } if (empty($tables)) { $this->err(__d('cake_console', 'Your database does not have any tables.')); return $this->_stop(); } sort($tables); return $tables; } /** * Forces the user to specify the model he wants to bake, and returns the selected model name. * * @param string $useDbConfig Database config name * @return string The model name */ public function getName($useDbConfig = null) { $this->listAll($useDbConfig); $enteredModel = ''; while (!$enteredModel) { $enteredModel = $this->in(__d('cake_console', "Enter a number from the list above,\n" . "type in the name of another model, or 'q' to exit"), null, 'q'); if ($enteredModel === 'q') { $this->out(__d('cake_console', 'Exit')); return $this->_stop(); } if (!$enteredModel || (int)$enteredModel > count($this->_modelNames)) { $this->err(__d('cake_console', "The model name you supplied was empty,\n" . "or the number you selected was not an option. Please try again.")); $enteredModel = ''; } } if ((int)$enteredModel > 0 && (int)$enteredModel <= count($this->_modelNames)) { return $this->_modelNames[(int)$enteredModel - 1]; } return $enteredModel; } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'Bake models.') )->addArgument('name', array( 'help' => __d('cake_console', 'Name of the model to bake. Can use Plugin.name to bake plugin models.') ))->addSubcommand('all', array( 'help' => __d('cake_console', 'Bake all model files with associations and validation.') ))->addOption('plugin', array( 'short' => 'p', 'help' => __d('cake_console', 'Plugin to bake the model into.') ))->addOption('theme', array( 'short' => 't', 'help' => __d('cake_console', 'Theme to use when baking code.') ))->addOption('connection', array( 'short' => 'c', 'help' => __d('cake_console', 'The connection the model table is on.') ))->addOption('force', array( 'short' => 'f', 'help' => __d('cake_console', 'Force overwriting existing files without prompting.') ))->epilog( __d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.') ); return $parser; } /** * Interact with FixtureTask to automatically bake fixtures when baking models. * * @param string $className Name of class to bake fixture for * @param string $useTable Optional table name for fixture to use. * @return void * @see FixtureTask::bake */ public function bakeFixture($className, $useTable = null) { $this->Fixture->interactive = $this->interactive; $this->Fixture->connection = $this->connection; $this->Fixture->plugin = $this->plugin; $this->Fixture->bake($className, $useTable); } } cakephp-2.8.0/lib/Cake/Console/Command/Task/PluginTask.php000066400000000000000000000147331265552240500232370ustar00rootroot00000000000000path = current(App::path('plugins')); $this->bootstrap = APP . 'Config' . DS . 'bootstrap.php'; } /** * Execution method always used for tasks * * @return void */ public function execute() { if (isset($this->args[0])) { $plugin = Inflector::camelize($this->args[0]); $pluginPath = $this->_pluginPath($plugin); if (is_dir($pluginPath)) { $this->out(__d('cake_console', 'Plugin: %s already exists, no action taken', $plugin)); $this->out(__d('cake_console', 'Path: %s', $pluginPath)); return false; } $this->_interactive($plugin); } else { return $this->_interactive(); } } /** * Interactive interface * * @param string $plugin The plugin name. * @return void */ protected function _interactive($plugin = null) { while ($plugin === null) { $plugin = $this->in(__d('cake_console', 'Enter the name of the plugin in CamelCase format')); } if (!$this->bake($plugin)) { $this->error(__d('cake_console', "An error occurred trying to bake: %s in %s", $plugin, $this->path . $plugin)); } } /** * Bake the plugin, create directories and files * * @param string $plugin Name of the plugin in CamelCased format * @return bool */ public function bake($plugin) { $pathOptions = App::path('plugins'); if (count($pathOptions) > 1) { $this->findPath($pathOptions); } $this->hr(); $this->out(__d('cake_console', "Plugin Name: %s", $plugin)); $this->out(__d('cake_console', "Plugin Directory: %s", $this->path . $plugin)); $this->hr(); $looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n', 'q'), 'y'); if (strtolower($looksGood) === 'y') { $Folder = new Folder($this->path . $plugin); $directories = array( 'Config' . DS . 'Schema', 'Console' . DS . 'Command' . DS . 'Task', 'Console' . DS . 'Templates', 'Controller' . DS . 'Component', 'Lib', 'Locale' . DS . 'eng' . DS . 'LC_MESSAGES', 'Model' . DS . 'Behavior', 'Model' . DS . 'Datasource', 'Test' . DS . 'Case' . DS . 'Controller' . DS . 'Component', 'Test' . DS . 'Case' . DS . 'Lib', 'Test' . DS . 'Case' . DS . 'Model' . DS . 'Behavior', 'Test' . DS . 'Case' . DS . 'Model' . DS . 'Datasource', 'Test' . DS . 'Case' . DS . 'View' . DS . 'Helper', 'Test' . DS . 'Fixture', 'View' . DS . 'Elements', 'View' . DS . 'Helper', 'View' . DS . 'Layouts', 'webroot' . DS . 'css', 'webroot' . DS . 'js', 'webroot' . DS . 'img', ); foreach ($directories as $directory) { $dirPath = $this->path . $plugin . DS . $directory; $Folder->create($dirPath); new File($dirPath . DS . 'empty', true); } foreach ($Folder->messages() as $message) { $this->out($message, 1, Shell::VERBOSE); } $errors = $Folder->errors(); if (!empty($errors)) { foreach ($errors as $message) { $this->error($message); } return false; } $controllerFileName = $plugin . 'AppController.php'; $out = "createFile($this->path . $plugin . DS . 'Controller' . DS . $controllerFileName, $out); $modelFileName = $plugin . 'AppModel.php'; $out = "createFile($this->path . $plugin . DS . 'Model' . DS . $modelFileName, $out); $this->_modifyBootstrap($plugin); $this->hr(); $this->out(__d('cake_console', 'Created: %s in %s', $plugin, $this->path . $plugin), 2); } return true; } /** * Update the app's bootstrap.php file. * * @param string $plugin Name of plugin * @return void */ protected function _modifyBootstrap($plugin) { $bootstrap = new File($this->bootstrap, false); $contents = $bootstrap->read(); if (!preg_match("@\n\s*CakePlugin::loadAll@", $contents)) { $bootstrap->append("\nCakePlugin::load('$plugin', array('bootstrap' => false, 'routes' => false));\n"); $this->out(''); $this->out(__d('cake_dev', '%s modified', $this->bootstrap)); } } /** * find and change $this->path to the user selection * * @param array $pathOptions The list of paths to look in. * @return void */ public function findPath($pathOptions) { $valid = false; foreach ($pathOptions as $i => $path) { if (!is_dir($path)) { unset($pathOptions[$i]); } } $pathOptions = array_values($pathOptions); $max = count($pathOptions); while (!$valid) { foreach ($pathOptions as $i => $option) { $this->out($i + 1 . '. ' . $option); } $prompt = __d('cake_console', 'Choose a plugin path from the paths above.'); $choice = $this->in($prompt, null, 1); if ((int)$choice > 0 && (int)$choice <= $max) { $valid = true; } } $this->path = $pathOptions[$choice - 1]; } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'Create the directory structure, AppModel and AppController classes for a new plugin. ' . 'Can create plugins in any of your bootstrapped plugin paths.') )->addArgument('name', array( 'help' => __d('cake_console', 'CamelCased name of the plugin to create.') )); return $parser; } } cakephp-2.8.0/lib/Cake/Console/Command/Task/ProjectTask.php000066400000000000000000000354701265552240500234100ustar00rootroot00000000000000args[0])) { $project = $this->args[0]; } else { $appContents = array_diff(scandir(APP), array('.', '..')); if (empty($appContents)) { $suggestedPath = rtrim(APP, DS); } else { $suggestedPath = APP . 'myapp'; } } while (!$project) { $prompt = __d('cake_console', "What is the path to the project you want to bake?"); $project = $this->in($prompt, null, $suggestedPath); } if ($project && !Folder::isAbsolute($project) && isset($_SERVER['PWD'])) { $project = $_SERVER['PWD'] . DS . $project; } $response = false; while (!$response && is_dir($project) === true && file_exists($project . 'Config' . 'core.php')) { $prompt = __d('cake_console', 'A project already exists in this location: %s Overwrite?', $project); $response = $this->in($prompt, array('y', 'n'), 'n'); if (strtolower($response) === 'n') { $response = $project = false; } } $success = true; if ($this->bake($project)) { $path = Folder::slashTerm($project); if ($this->securitySalt($path) === true) { $this->out(__d('cake_console', ' * Random hash key created for \'Security.salt\'')); } else { $this->err(__d('cake_console', 'Unable to generate random hash for \'Security.salt\', you should change it in %s', APP . 'Config' . DS . 'core.php')); $success = false; } if ($this->securityCipherSeed($path) === true) { $this->out(__d('cake_console', ' * Random seed created for \'Security.cipherSeed\'')); } else { $this->err(__d('cake_console', 'Unable to generate random seed for \'Security.cipherSeed\', you should change it in %s', APP . 'Config' . DS . 'core.php')); $success = false; } if ($this->cachePrefix($path)) { $this->out(__d('cake_console', ' * Cache prefix set')); } else { $this->err(__d('cake_console', 'The cache prefix was NOT set')); $success = false; } if ($this->consolePath($path) === true) { $this->out(__d('cake_console', ' * app/Console/cake.php path set.')); } else { $this->err(__d('cake_console', 'Unable to set console path for app/Console.')); $success = false; } $hardCode = false; if ($this->cakeOnIncludePath()) { $this->out(__d('cake_console', 'CakePHP is on your `include_path`. CAKE_CORE_INCLUDE_PATH will be set, but commented out.')); } else { $this->out(__d('cake_console', 'CakePHP is not on your `include_path`, CAKE_CORE_INCLUDE_PATH will be hard coded.')); $this->out(__d('cake_console', 'You can fix this by adding CakePHP to your `include_path`.')); $hardCode = true; } $success = $this->corePath($path, $hardCode) === true; if ($success) { $this->out(__d('cake_console', ' * CAKE_CORE_INCLUDE_PATH set to %s in %s', CAKE_CORE_INCLUDE_PATH, 'webroot/index.php')); $this->out(__d('cake_console', ' * CAKE_CORE_INCLUDE_PATH set to %s in %s', CAKE_CORE_INCLUDE_PATH, 'webroot/test.php')); } else { $this->err(__d('cake_console', 'Unable to set CAKE_CORE_INCLUDE_PATH, you should change it in %s', $path . 'webroot' . DS . 'index.php')); $success = false; } if ($success && $hardCode) { $this->out(__d('cake_console', ' * Remember to check these values after moving to production server')); } $Folder = new Folder($path); if (!$Folder->chmod($path . 'tmp', 0777)) { $this->err(__d('cake_console', 'Could not set permissions on %s', $path . DS . 'tmp')); $this->out('chmod -R 0777 ' . $path . DS . 'tmp'); $success = false; } if ($success) { $this->out(__d('cake_console', 'Project baked successfully!')); } else { $this->out(__d('cake_console', 'Project baked but with some issues..')); } return $path; } } /** * Checks PHP's include_path for CakePHP. * * @return bool Indicates whether or not CakePHP exists on include_path */ public function cakeOnIncludePath() { $paths = explode(PATH_SEPARATOR, ini_get('include_path')); foreach ($paths as $path) { if (file_exists($path . DS . 'Cake' . DS . 'bootstrap.php')) { return true; } } return false; } /** * Looks for a skeleton template of a Cake application, * and if not found asks the user for a path. When there is a path * this method will make a deep copy of the skeleton to the project directory. * * @param string $path Project path * @param string $skel Path to copy from * @param string $skip array of directories to skip when copying * @return mixed */ public function bake($path, $skel = null, $skip = array('empty')) { if (!$skel && !empty($this->params['skel'])) { $skel = $this->params['skel']; } while (!$skel) { $skel = $this->in( __d('cake_console', "What is the path to the directory layout you wish to copy?"), null, CAKE . 'Console' . DS . 'Templates' . DS . 'skel' ); if (!$skel) { $this->err(__d('cake_console', 'The directory path you supplied was empty. Please try again.')); } else { while (is_dir($skel) === false) { $skel = $this->in( __d('cake_console', 'Directory path does not exist please choose another:'), null, CAKE . 'Console' . DS . 'Templates' . DS . 'skel' ); } } } $app = basename($path); $this->out(__d('cake_console', 'Skel Directory: ') . $skel); $this->out(__d('cake_console', 'Will be copied to: ') . $path); $this->hr(); $looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n', 'q'), 'y'); switch (strtolower($looksGood)) { case 'y': $Folder = new Folder($skel); if (!empty($this->params['empty'])) { $skip = array(); } if ($Folder->copy(array('to' => $path, 'skip' => $skip))) { $this->hr(); $this->out(__d('cake_console', 'Created: %s in %s', $app, $path)); $this->hr(); } else { $this->err(__d('cake_console', "Could not create '%s' properly.", $app)); return false; } foreach ($Folder->messages() as $message) { $this->out(CakeText::wrap(' * ' . $message), 1, Shell::VERBOSE); } return true; case 'n': unset($this->args[0]); $this->execute(); return false; case 'q': $this->out(__d('cake_console', 'Bake Aborted.')); return false; } } /** * Generates the correct path to the CakePHP libs that are generating the project * and points app/console/cake.php to the right place * * @param string $path Project path. * @return bool success */ public function consolePath($path) { $File = new File($path . 'Console' . DS . 'cake.php'); $contents = $File->read(); if (preg_match('/(__CAKE_PATH__)/', $contents, $match)) { $root = strpos(CAKE_CORE_INCLUDE_PATH, '/') === 0 ? " DS . '" : "'"; $replacement = $root . str_replace(DS, "' . DS . '", trim(CAKE_CORE_INCLUDE_PATH, DS)) . "'"; $result = str_replace($match[0], $replacement, $contents); if ($File->write($result)) { return true; } return false; } return false; } /** * Generates and writes 'Security.salt' * * @param string $path Project path * @return bool Success */ public function securitySalt($path) { $File = new File($path . 'Config' . DS . 'core.php'); $contents = $File->read(); if (preg_match('/([\s]*Configure::write\(\'Security.salt\',[\s\'A-z0-9]*\);)/', $contents, $match)) { $string = Security::generateAuthKey(); $result = str_replace($match[0], "\t" . 'Configure::write(\'Security.salt\', \'' . $string . '\');', $contents); if ($File->write($result)) { return true; } return false; } return false; } /** * Generates and writes 'Security.cipherSeed' * * @param string $path Project path * @return bool Success */ public function securityCipherSeed($path) { $File = new File($path . 'Config' . DS . 'core.php'); $contents = $File->read(); if (preg_match('/([\s]*Configure::write\(\'Security.cipherSeed\',[\s\'A-z0-9]*\);)/', $contents, $match)) { App::uses('Security', 'Utility'); $string = substr(bin2hex(Security::generateAuthKey()), 0, 30); $result = str_replace($match[0], "\t" . 'Configure::write(\'Security.cipherSeed\', \'' . $string . '\');', $contents); if ($File->write($result)) { return true; } return false; } return false; } /** * Writes cache prefix using app's name * * @param string $dir Path to project * @return bool Success */ public function cachePrefix($dir) { $app = basename($dir); $File = new File($dir . 'Config' . DS . 'core.php'); $contents = $File->read(); if (preg_match('/(\$prefix = \'myapp_\';)/', $contents, $match)) { $result = str_replace($match[0], '$prefix = \'' . $app . '_\';', $contents); return $File->write($result); } return false; } /** * Generates and writes CAKE_CORE_INCLUDE_PATH * * @param string $path Project path * @param bool $hardCode Whether or not define calls should be hardcoded. * @return bool Success */ public function corePath($path, $hardCode = true) { if (dirname($path) !== CAKE_CORE_INCLUDE_PATH) { $filename = $path . 'webroot' . DS . 'index.php'; if (!$this->_replaceCorePath($filename, $hardCode)) { return false; } $filename = $path . 'webroot' . DS . 'test.php'; if (!$this->_replaceCorePath($filename, $hardCode)) { return false; } return true; } } /** * Replaces the __CAKE_PATH__ placeholder in the template files. * * @param string $filename The filename to operate on. * @param bool $hardCode Whether or not the define should be uncommented. * @return bool Success */ protected function _replaceCorePath($filename, $hardCode) { $contents = file_get_contents($filename); $root = strpos(CAKE_CORE_INCLUDE_PATH, '/') === 0 ? " DS . '" : "'"; $corePath = $root . str_replace(DS, "' . DS . '", trim(CAKE_CORE_INCLUDE_PATH, DS)) . "'"; $composer = ROOT . DS . APP_DIR . DS . 'Vendor' . DS . 'cakephp' . DS . 'cakephp' . DS . 'lib'; if (file_exists($composer)) { $corePath = " ROOT . DS . APP_DIR . DS . 'Vendor' . DS . 'cakephp' . DS . 'cakephp' . DS . 'lib'"; } $result = str_replace('__CAKE_PATH__', $corePath, $contents, $count); if ($hardCode) { $result = str_replace('//define(\'CAKE_CORE', 'define(\'CAKE_CORE', $result); } if (!file_put_contents($filename, $result)) { return false; } return (bool)$count; } /** * Enables Configure::read('Routing.prefixes') in /app/Config/core.php * * @param string $name Name to use as admin routing * @return bool Success */ public function cakeAdmin($name) { $path = (empty($this->configPath)) ? APP . 'Config' . DS : $this->configPath; $File = new File($path . 'core.php'); $contents = $File->read(); if (preg_match('%(\s*[/]*Configure::write\(\'Routing.prefixes\',[\s\'a-z,\)\(]*\);)%', $contents, $match)) { $result = str_replace($match[0], "\n" . 'Configure::write(\'Routing.prefixes\', array(\'' . $name . '\'));', $contents); if ($File->write($result)) { Configure::write('Routing.prefixes', array($name)); return true; } } return false; } /** * Checks for Configure::read('Routing.prefixes') and forces user to input it if not enabled * * @return string Admin route to use */ public function getPrefix() { $admin = ''; $prefixes = Configure::read('Routing.prefixes'); if (!empty($prefixes)) { if (count($prefixes) === 1) { return $prefixes[0] . '_'; } if ($this->interactive) { $this->out(); $this->out(__d('cake_console', 'You have more than one routing prefix configured')); } $options = array(); foreach ($prefixes as $i => $prefix) { $options[] = $i + 1; if ($this->interactive) { $this->out($i + 1 . '. ' . $prefix); } } $selection = $this->in(__d('cake_console', 'Please choose a prefix to bake with.'), $options, 1); return $prefixes[$selection - 1] . '_'; } if ($this->interactive) { $this->hr(); $this->out(__d('cake_console', 'You need to enable %s in %s to use prefix routing.', 'Configure::write(\'Routing.prefixes\', array(\'admin\'))', '/app/Config/core.php')); $this->out(__d('cake_console', 'What would you like the prefix route to be?')); $this->out(__d('cake_console', 'Example: %s', 'www.example.com/admin/controller')); while (!$admin) { $admin = $this->in(__d('cake_console', 'Enter a routing prefix:'), null, 'admin'); } if ($this->cakeAdmin($admin) !== true) { $this->out(__d('cake_console', 'Unable to write to %s.', '/app/Config/core.php')); $this->out(__d('cake_console', 'You need to enable %s in %s to use prefix routing.', 'Configure::write(\'Routing.prefixes\', array(\'admin\'))', '/app/Config/core.php')); return $this->_stop(); } return $admin . '_'; } return ''; } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'Generate a new CakePHP project skeleton.') )->addArgument('name', array( 'help' => __d('cake_console', 'Application directory to make, if it starts with "/" the path is absolute.') ))->addOption('empty', array( 'boolean' => true, 'help' => __d('cake_console', 'Create empty files in each of the directories. Good if you are using git') ))->addOption('theme', array( 'short' => 't', 'help' => __d('cake_console', 'Theme to use when baking code.') ))->addOption('skel', array( 'default' => current(App::core('Console')) . 'Templates' . DS . 'skel', 'help' => __d('cake_console', 'The directory layout to use for the new application skeleton.' . ' Defaults to cake/Console/Templates/skel of CakePHP used to create the project.') )); return $parser; } } cakephp-2.8.0/lib/Cake/Console/Command/Task/TemplateTask.php000066400000000000000000000143071265552240500235510ustar00rootroot00000000000000 $path * * @var array */ public $templatePaths = array(); /** * Initialize callback. Setup paths for the template task. * * @return void */ public function initialize() { $this->templatePaths = $this->_findThemes(); } /** * Find the paths to all the installed shell themes in the app. * * Bake themes are directories not named `skel` inside a `Console/Templates` path. * They are listed in this order: app -> plugin -> default * * @return array Array of bake themes that are installed. */ protected function _findThemes() { $paths = App::path('Console'); $plugins = App::objects('plugin'); foreach ($plugins as $plugin) { $paths[] = $this->_pluginPath($plugin) . 'Console' . DS; } $core = current(App::core('Console')); $separator = DS === '/' ? '/' : '\\\\'; $core = preg_replace('#shells' . $separator . '$#', '', $core); $Folder = new Folder($core . 'Templates' . DS . 'default'); $contents = $Folder->read(); $themeFolders = $contents[0]; $paths[] = $core; foreach ($paths as $i => $path) { $paths[$i] = rtrim($path, DS) . DS; } $themes = array(); foreach ($paths as $path) { $Folder = new Folder($path . 'Templates', false); $contents = $Folder->read(); $subDirs = $contents[0]; foreach ($subDirs as $dir) { if (empty($dir) || preg_match('@^skel$|_skel$@', $dir)) { continue; } $Folder = new Folder($path . 'Templates' . DS . $dir); $contents = $Folder->read(); $subDirs = $contents[0]; if (array_intersect($contents[0], $themeFolders)) { $templateDir = $path . 'Templates' . DS . $dir . DS; $themes[$dir] = $templateDir; } } } return $themes; } /** * Set variable values to the template scope * * @param string|array $one A string or an array of data. * @param string|array $two Value in case $one is a string (which then works as the key). * Unused if $one is an associative array, otherwise serves as the values to $one's keys. * @return void */ public function set($one, $two = null) { if (is_array($one)) { if (is_array($two)) { $data = array_combine($one, $two); } else { $data = $one; } } else { $data = array($one => $two); } if (!$data) { return false; } $this->templateVars = $data + $this->templateVars; } /** * Runs the template * * @param string $directory directory / type of thing you want * @param string $filename template name * @param array $vars Additional vars to set to template scope. * @return string contents of generated code template */ public function generate($directory, $filename, $vars = null) { if ($vars !== null) { $this->set($vars); } if (empty($this->templatePaths)) { $this->initialize(); } $themePath = $this->getThemePath(); $templateFile = $this->_findTemplate($themePath, $directory, $filename); if ($templateFile) { extract($this->templateVars); ob_start(); ob_implicit_flush(0); include $templateFile; $content = ob_get_clean(); return $content; } return ''; } /** * Find the theme name for the current operation. * If there is only one theme in $templatePaths it will be used. * If there is a -theme param in the cli args, it will be used. * If there is more than one installed theme user interaction will happen * * @return string returns the path to the selected theme. */ public function getThemePath() { if (count($this->templatePaths) === 1) { $paths = array_values($this->templatePaths); return $paths[0]; } if (!empty($this->params['theme']) && isset($this->templatePaths[$this->params['theme']])) { return $this->templatePaths[$this->params['theme']]; } $this->hr(); $this->out(__d('cake_console', 'You have more than one set of templates installed.')); $this->out(__d('cake_console', 'Please choose the template set you wish to use:')); $this->hr(); $i = 1; $indexedPaths = array(); foreach ($this->templatePaths as $key => $path) { $this->out($i . '. ' . $key); $indexedPaths[$i] = $path; $i++; } $index = $this->in(__d('cake_console', 'Which bake theme would you like to use?'), range(1, $i - 1), 1); $themeNames = array_keys($this->templatePaths); $this->params['theme'] = $themeNames[$index - 1]; return $indexedPaths[$index]; } /** * Find a template inside a directory inside a path. * Will scan all other theme dirs if the template is not found in the first directory. * * @param string $path The initial path to look for the file on. If it is not found fallbacks will be used. * @param string $directory Subdirectory to look for ie. 'views', 'objects' * @param string $filename lower_case_underscored filename you want. * @return string filename will exit program if template is not found. */ protected function _findTemplate($path, $directory, $filename) { $themeFile = $path . $directory . DS . $filename . '.ctp'; if (file_exists($themeFile)) { return $themeFile; } foreach ($this->templatePaths as $path) { $templatePath = $path . $directory . DS . $filename . '.ctp'; if (file_exists($templatePath)) { return $templatePath; } } $this->err(__d('cake_console', 'Could not find template for %s', $filename)); return false; } } cakephp-2.8.0/lib/Cake/Console/Command/Task/TestTask.php000066400000000000000000000430011265552240500227060ustar00rootroot00000000000000 'Model', 'Controller' => 'Controller', 'Component' => 'Controller/Component', 'Behavior' => 'Model/Behavior', 'Helper' => 'View/Helper' ); /** * Mapping between packages, and their baseclass + package. * This is used to generate App::uses() call to autoload base * classes if a developer has forgotten to do so. * * @var array */ public $baseTypes = array( 'Model' => array('Model', 'Model'), 'Behavior' => array('ModelBehavior', 'Model'), 'Controller' => array('Controller', 'Controller'), 'Component' => array('Component', 'Controller'), 'Helper' => array('Helper', 'View') ); /** * Internal list of fixtures that have been added so far. * * @var array */ protected $_fixtures = array(); /** * Execution method always used for tasks * * @return void */ public function execute() { parent::execute(); $count = count($this->args); if (!$count) { $this->_interactive(); } if ($count === 1) { $this->_interactive($this->args[0]); } if ($count > 1) { $type = Inflector::classify($this->args[0]); if ($this->bake($type, $this->args[1])) { $this->out('Done'); } } } /** * Handles interactive baking * * @param string $type The type of object to bake a test for. * @return string|bool */ protected function _interactive($type = null) { $this->interactive = true; $this->hr(); $this->out(__d('cake_console', 'Bake Tests')); $this->out(__d('cake_console', 'Path: %s', $this->getPath())); $this->hr(); if ($type) { $type = Inflector::camelize($type); if (!isset($this->classTypes[$type])) { $this->error(__d('cake_console', 'Incorrect type provided. Please choose one of %s', implode(', ', array_keys($this->classTypes)))); } } else { $type = $this->getObjectType(); } $className = $this->getClassName($type); return $this->bake($type, $className); } /** * Completes final steps for generating data to create test case. * * @param string $type Type of object to bake test case for ie. Model, Controller * @param string $className the 'cake name' for the class ie. Posts for the PostsController * @return string|bool */ public function bake($type, $className) { $plugin = null; if ($this->plugin) { $plugin = $this->plugin . '.'; } $realType = $this->mapType($type, $plugin); $fullClassName = $this->getRealClassName($type, $className); if ($this->typeCanDetectFixtures($type) && $this->isLoadableClass($realType, $fullClassName)) { $this->out(__d('cake_console', 'Bake is detecting possible fixtures...')); $testSubject = $this->buildTestSubject($type, $className); $this->generateFixtureList($testSubject); } elseif ($this->interactive) { $this->getUserFixtures(); } list($baseClass, $baseType) = $this->getBaseType($type); App::uses($baseClass, $baseType); App::uses($fullClassName, $realType); $methods = array(); if (class_exists($fullClassName)) { $methods = $this->getTestableMethods($fullClassName); } $mock = $this->hasMockClass($type, $fullClassName); list($preConstruct, $construction, $postConstruct) = $this->generateConstructor($type, $fullClassName, $plugin); $uses = $this->generateUses($type, $realType, $fullClassName); $this->out("\n" . __d('cake_console', 'Baking test case for %s %s ...', $className, $type), 1, Shell::QUIET); $this->Template->set('fixtures', $this->_fixtures); $this->Template->set('plugin', $plugin); $this->Template->set(compact( 'className', 'methods', 'type', 'fullClassName', 'mock', 'realType', 'preConstruct', 'postConstruct', 'construction', 'uses' )); $out = $this->Template->generate('classes', 'test'); $filename = $this->testCaseFileName($type, $className); $made = $this->createFile($filename, $out); if ($made) { return $out; } return false; } /** * Interact with the user and get their chosen type. Can exit the script. * * @return string Users chosen type. */ public function getObjectType() { $this->hr(); $this->out(__d('cake_console', 'Select an object type:')); $this->hr(); $keys = array(); $i = 0; foreach ($this->classTypes as $option => $package) { $this->out(++$i . '. ' . $option); $keys[] = $i; } $keys[] = 'q'; $selection = $this->in(__d('cake_console', 'Enter the type of object to bake a test for or (q)uit'), $keys, 'q'); if ($selection === 'q') { return $this->_stop(); } $types = array_keys($this->classTypes); return $types[$selection - 1]; } /** * Get the user chosen Class name for the chosen type * * @param string $objectType Type of object to list classes for i.e. Model, Controller. * @return string Class name the user chose. */ public function getClassName($objectType) { $type = ucfirst(strtolower($objectType)); $typeLength = strlen($type); $type = $this->classTypes[$type]; if ($this->plugin) { $plugin = $this->plugin . '.'; $options = App::objects($plugin . $type); } else { $options = App::objects($type); } $this->out(__d('cake_console', 'Choose a %s class', $objectType)); $keys = array(); foreach ($options as $key => $option) { $this->out(++$key . '. ' . $option); $keys[] = $key; } while (empty($selection)) { $selection = $this->in(__d('cake_console', 'Choose an existing class, or enter the name of a class that does not exist')); if (is_numeric($selection) && isset($options[$selection - 1])) { $selection = $options[$selection - 1]; } if ($type !== 'Model') { $selection = substr($selection, 0, $typeLength * - 1); } } return $selection; } /** * Checks whether the chosen type can find its own fixtures. * Currently only model, and controller are supported * * @param string $type The Type of object you are generating tests for eg. controller * @return bool */ public function typeCanDetectFixtures($type) { $type = strtolower($type); return in_array($type, array('controller', 'model')); } /** * Check if a class with the given package is loaded or can be loaded. * * @param string $package The package of object you are generating tests for eg. controller * @param string $class the Classname of the class the test is being generated for. * @return bool */ public function isLoadableClass($package, $class) { App::uses($class, $package); list($plugin, $ns) = pluginSplit($package); if ($plugin) { App::uses("{$plugin}AppController", $package); App::uses("{$plugin}AppModel", $package); App::uses("{$plugin}AppHelper", $package); } return class_exists($class); } /** * Construct an instance of the class to be tested. * So that fixtures can be detected * * @param string $type The Type of object you are generating tests for eg. controller * @param string $class the Classname of the class the test is being generated for. * @return object And instance of the class that is going to be tested. */ public function buildTestSubject($type, $class) { ClassRegistry::flush(); App::uses($class, $type); $class = $this->getRealClassName($type, $class); if (strtolower($type) === 'model') { $instance = ClassRegistry::init($class); } else { $instance = new $class(); } return $instance; } /** * Gets the real class name from the cake short form. If the class name is already * suffixed with the type, the type will not be duplicated. * * @param string $type The Type of object you are generating tests for eg. controller * @param string $class the Classname of the class the test is being generated for. * @return string Real class name */ public function getRealClassName($type, $class) { if (strtolower($type) === 'model' || empty($this->classTypes[$type])) { return $class; } $position = strpos($class, $type); if ($position !== false && (strlen($class) - $position) === strlen($type)) { return $class; } return $class . $type; } /** * Map the types that TestTask uses to concrete types that App::uses can use. * * @param string $type The type of thing having a test generated. * @param string $plugin The plugin name. * @return string * @throws CakeException When invalid object types are requested. */ public function mapType($type, $plugin) { $type = ucfirst($type); if (empty($this->classTypes[$type])) { throw new CakeException(__d('cake_dev', 'Invalid object type.')); } $real = $this->classTypes[$type]; if ($plugin) { $real = trim($plugin, '.') . '.' . $real; } return $real; } /** * Get the base class and package name for a given type. * * @param string $type The type the class having a test * generated for is in. * @return array Array of (class, type) * @throws CakeException on invalid types. */ public function getBaseType($type) { if (empty($this->baseTypes[$type])) { throw new CakeException(__d('cake_dev', 'Invalid type name')); } return $this->baseTypes[$type]; } /** * Get methods declared in the class given. * No parent methods will be returned * * @param string $className Name of class to look at. * @return array Array of method names. */ public function getTestableMethods($className) { $classMethods = get_class_methods($className); $parentMethods = get_class_methods(get_parent_class($className)); $thisMethods = array_diff($classMethods, $parentMethods); $out = array(); foreach ($thisMethods as $method) { if (substr($method, 0, 1) !== '_' && $method != strtolower($className)) { $out[] = $method; } } return $out; } /** * Generate the list of fixtures that will be required to run this test based on * loaded models. * * @param object $subject The object you want to generate fixtures for. * @return array Array of fixtures to be included in the test. */ public function generateFixtureList($subject) { $this->_fixtures = array(); if ($subject instanceof Model) { $this->_processModel($subject); } elseif ($subject instanceof Controller) { $this->_processController($subject); } return array_values($this->_fixtures); } /** * Process a model recursively and pull out all the * model names converting them to fixture names. * * @param Model $subject A Model class to scan for associations and pull fixtures off of. * @return void */ protected function _processModel($subject) { $this->_addFixture($subject->name); $associated = $subject->getAssociated(); foreach ($associated as $alias => $type) { $className = $subject->{$alias}->name; if (!isset($this->_fixtures[$className])) { $this->_processModel($subject->{$alias}); } if ($type === 'hasAndBelongsToMany') { if (!empty($subject->hasAndBelongsToMany[$alias]['with'])) { list(, $joinModel) = pluginSplit($subject->hasAndBelongsToMany[$alias]['with']); } else { $joinModel = Inflector::classify($subject->hasAndBelongsToMany[$alias]['joinTable']); } if (!isset($this->_fixtures[$joinModel])) { $this->_processModel($subject->{$joinModel}); } } } } /** * Process all the models attached to a controller * and generate a fixture list. * * @param Controller $subject A controller to pull model names off of. * @return void */ protected function _processController($subject) { $subject->constructClasses(); $models = array(Inflector::classify($subject->name)); if (!empty($subject->uses)) { $models = $subject->uses; } foreach ($models as $model) { list(, $model) = pluginSplit($model); $this->_processModel($subject->{$model}); } } /** * Add class name to the fixture list. * Sets the app. or plugin.plugin_name. prefix. * * @param string $name Name of the Model class that a fixture might be required for. * @return void */ protected function _addFixture($name) { if ($this->plugin) { $prefix = 'plugin.' . Inflector::underscore($this->plugin) . '.'; } else { $prefix = 'app.'; } $fixture = $prefix . Inflector::underscore($name); $this->_fixtures[$name] = $fixture; } /** * Interact with the user to get additional fixtures they want to use. * * @return array Array of fixtures the user wants to add. */ public function getUserFixtures() { $proceed = $this->in(__d('cake_console', 'Bake could not detect fixtures, would you like to add some?'), array('y', 'n'), 'n'); $fixtures = array(); if (strtolower($proceed) === 'y') { $fixtureList = $this->in(__d('cake_console', "Please provide a comma separated list of the fixtures names you'd like to use.\nExample: 'app.comment, app.post, plugin.forums.post'")); $fixtureListTrimmed = str_replace(' ', '', $fixtureList); $fixtures = explode(',', $fixtureListTrimmed); } $this->_fixtures = array_merge($this->_fixtures, $fixtures); return $fixtures; } /** * Is a mock class required for this type of test? * Controllers require a mock class. * * @param string $type The type of object tests are being generated for eg. controller. * @return bool */ public function hasMockClass($type) { $type = strtolower($type); return $type === 'controller'; } /** * Generate a constructor code snippet for the type and class name * * @param string $type The Type of object you are generating tests for eg. controller * @param string $fullClassName The Classname of the class the test is being generated for. * @param string $plugin The plugin name. * @return array Constructor snippets for the thing you are building. */ public function generateConstructor($type, $fullClassName, $plugin) { $type = strtolower($type); $pre = $construct = $post = ''; if ($type === 'model') { $construct = "ClassRegistry::init('{$plugin}$fullClassName');\n"; } if ($type === 'behavior') { $construct = "new $fullClassName();\n"; } if ($type === 'helper') { $pre = "\$View = new View();\n"; $construct = "new {$fullClassName}(\$View);\n"; } if ($type === 'component') { $pre = "\$Collection = new ComponentCollection();\n"; $construct = "new {$fullClassName}(\$Collection);\n"; } return array($pre, $construct, $post); } /** * Generate the uses() calls for a type & class name * * @param string $type The Type of object you are generating tests for eg. controller * @param string $realType The package name for the class. * @param string $className The Classname of the class the test is being generated for. * @return array An array containing used classes */ public function generateUses($type, $realType, $className) { $uses = array(); $type = strtolower($type); if ($type === 'component') { $uses[] = array('ComponentCollection', 'Controller'); $uses[] = array('Component', 'Controller'); } if ($type === 'helper') { $uses[] = array('View', 'View'); $uses[] = array('Helper', 'View'); } $uses[] = array($className, $realType); return $uses; } /** * Make the filename for the test case. resolve the suffixes for controllers * and get the plugin path if needed. * * @param string $type The Type of object you are generating tests for eg. controller * @param string $className the Classname of the class the test is being generated for. * @return string filename the test should be created on. */ public function testCaseFileName($type, $className) { $path = $this->getPath() . 'Case' . DS; $type = Inflector::camelize($type); if (isset($this->classTypes[$type])) { $path .= $this->classTypes[$type] . DS; } $className = $this->getRealClassName($type, $className); return str_replace('/', DS, $path) . Inflector::camelize($className) . 'Test.php'; } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'Bake test case skeletons for classes.') )->addArgument('type', array( 'help' => __d('cake_console', 'Type of class to bake, can be any of the following: controller, model, helper, component or behavior.'), 'choices' => array( 'Controller', 'controller', 'Model', 'model', 'Helper', 'helper', 'Component', 'component', 'Behavior', 'behavior' ) ))->addArgument('name', array( 'help' => __d('cake_console', 'An existing class to bake tests for.') ))->addOption('theme', array( 'short' => 't', 'help' => __d('cake_console', 'Theme to use when baking code.') ))->addOption('plugin', array( 'short' => 'p', 'help' => __d('cake_console', 'CamelCased name of the plugin to bake tests for.') ))->addOption('force', array( 'short' => 'f', 'help' => __d('cake_console', 'Force overwriting existing files without prompting.') ))->epilog( __d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.') ); return $parser; } } cakephp-2.8.0/lib/Cake/Console/Command/Task/ViewTask.php000066400000000000000000000344521265552240500227130ustar00rootroot00000000000000path = current(App::path('View')); } /** * Execution method always used for tasks * * @return mixed */ public function execute() { parent::execute(); if (empty($this->args)) { $this->_interactive(); } if (empty($this->args[0])) { return null; } if (!isset($this->connection)) { $this->connection = 'default'; } $action = null; $this->controllerName = $this->_controllerName($this->args[0]); $this->Project->interactive = false; if (strtolower($this->args[0]) === 'all') { return $this->all(); } if (isset($this->args[1])) { $this->template = $this->args[1]; } if (isset($this->args[2])) { $action = $this->args[2]; } if (!$action) { $action = $this->template; } if ($action) { return $this->bake($action, true); } $vars = $this->_loadController(); $methods = $this->_methodsToBake(); foreach ($methods as $method) { $content = $this->getContent($method, $vars); if ($content) { $this->bake($method, $content); } } } /** * Get a list of actions that can / should have views baked for them. * * @return array Array of action names that should be baked */ protected function _methodsToBake() { $methods = array_diff( array_map('strtolower', get_class_methods($this->controllerName . 'Controller')), array_map('strtolower', get_class_methods('AppController')) ); $scaffoldActions = false; if (empty($methods)) { $scaffoldActions = true; $methods = $this->scaffoldActions; } $adminRoute = $this->Project->getPrefix(); foreach ($methods as $i => $method) { if ($adminRoute && !empty($this->params['admin'])) { if ($scaffoldActions) { $methods[$i] = $adminRoute . $method; continue; } elseif (strpos($method, $adminRoute) === false) { unset($methods[$i]); } } if ($method[0] === '_' || $method === strtolower($this->controllerName . 'Controller')) { unset($methods[$i]); } } return $methods; } /** * Bake All views for All controllers. * * @return void */ public function all() { $this->Controller->interactive = false; $tables = $this->Controller->listAll($this->connection, false); $actions = null; if (isset($this->args[1])) { $actions = array($this->args[1]); } $this->interactive = false; foreach ($tables as $table) { $model = $this->_modelName($table); $this->controllerName = $this->_controllerName($model); App::uses($model, 'Model'); if (class_exists($model)) { $vars = $this->_loadController(); if (!$actions) { $actions = $this->_methodsToBake(); } $this->bakeActions($actions, $vars); $actions = null; } } } /** * Handles interactive baking * * @return void */ protected function _interactive() { $this->hr(); $this->out(sprintf("Bake View\nPath: %s", $this->getPath())); $this->hr(); $this->DbConfig->interactive = $this->Controller->interactive = $this->interactive = true; if (empty($this->connection)) { $this->connection = $this->DbConfig->getConfig(); } $this->Controller->connection = $this->connection; $this->controllerName = $this->Controller->getName(); $prompt = __d('cake_console', "Would you like bake to build your views interactively?\nWarning: Choosing no will overwrite %s views if they exist.", $this->controllerName); $interactive = $this->in($prompt, array('y', 'n'), 'n'); if (strtolower($interactive) === 'n') { $this->interactive = false; } $prompt = __d('cake_console', "Would you like to create some CRUD views\n(index, add, view, edit) for this controller?\nNOTE: Before doing so, you'll need to create your controller\nand model classes (including associated models)."); $wannaDoScaffold = $this->in($prompt, array('y', 'n'), 'y'); $wannaDoAdmin = $this->in(__d('cake_console', "Would you like to create the views for admin routing?"), array('y', 'n'), 'n'); if (strtolower($wannaDoScaffold) === 'y' || strtolower($wannaDoAdmin) === 'y') { $vars = $this->_loadController(); if (strtolower($wannaDoScaffold) === 'y') { $actions = $this->scaffoldActions; $this->bakeActions($actions, $vars); } if (strtolower($wannaDoAdmin) === 'y') { $admin = $this->Project->getPrefix(); $regularActions = $this->scaffoldActions; $adminActions = array(); foreach ($regularActions as $action) { $adminActions[] = $admin . $action; } $this->bakeActions($adminActions, $vars); } $this->hr(); $this->out(); $this->out(__d('cake_console', "View Scaffolding Complete.\n")); } else { $this->customAction(); } } /** * Loads Controller and sets variables for the template * Available template variables * 'modelClass', 'primaryKey', 'displayField', 'singularVar', 'pluralVar', * 'singularHumanName', 'pluralHumanName', 'fields', 'foreignKeys', * 'belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany' * * @return array Returns a variables to be made available to a view template */ protected function _loadController() { if (!$this->controllerName) { $this->err(__d('cake_console', 'Controller not found')); } $plugin = null; if ($this->plugin) { $plugin = $this->plugin . '.'; } $controllerClassName = $this->controllerName . 'Controller'; App::uses($controllerClassName, $plugin . 'Controller'); if (!class_exists($controllerClassName)) { $file = $controllerClassName . '.php'; $this->err(__d('cake_console', "The file '%s' could not be found.\nIn order to bake a view, you'll need to first create the controller.", $file)); return $this->_stop(); } $controllerObj = new $controllerClassName(); $controllerObj->plugin = $this->plugin; $controllerObj->constructClasses(); $modelClass = $controllerObj->modelClass; $modelObj = $controllerObj->{$controllerObj->modelClass}; if ($modelObj) { $primaryKey = $modelObj->primaryKey; $displayField = $modelObj->displayField; $singularVar = Inflector::variable($modelClass); $singularHumanName = $this->_singularHumanName($this->controllerName); $schema = $modelObj->schema(true); $fields = array_keys($schema); $associations = $this->_associations($modelObj); } else { $primaryKey = $displayField = null; $singularVar = Inflector::variable(Inflector::singularize($this->controllerName)); $singularHumanName = $this->_singularHumanName($this->controllerName); $fields = $schema = $associations = array(); } $pluralVar = Inflector::variable($this->controllerName); $pluralHumanName = $this->_pluralHumanName($this->controllerName); return compact('modelClass', 'schema', 'primaryKey', 'displayField', 'singularVar', 'pluralVar', 'singularHumanName', 'pluralHumanName', 'fields', 'associations'); } /** * Bake a view file for each of the supplied actions * * @param array $actions Array of actions to make files for. * @param array $vars The template variables. * @return void */ public function bakeActions($actions, $vars) { foreach ($actions as $action) { $content = $this->getContent($action, $vars); $this->bake($action, $content); } } /** * handle creation of baking a custom action view file * * @return void */ public function customAction() { $action = ''; while (!$action) { $action = $this->in(__d('cake_console', 'Action Name? (use lowercase_underscored function name)')); if (!$action) { $this->out(__d('cake_console', 'The action name you supplied was empty. Please try again.')); } } $this->out(); $this->hr(); $this->out(__d('cake_console', 'The following view will be created:')); $this->hr(); $this->out(__d('cake_console', 'Controller Name: %s', $this->controllerName)); $this->out(__d('cake_console', 'Action Name: %s', $action)); $this->out(__d('cake_console', 'Path: %s', $this->getPath() . $this->controllerName . DS . Inflector::underscore($action) . ".ctp")); $this->hr(); $looksGood = $this->in(__d('cake_console', 'Look okay?'), array('y', 'n'), 'y'); if (strtolower($looksGood) === 'y') { $this->bake($action, ' '); return $this->_stop(); } $this->out(__d('cake_console', 'Bake Aborted.')); } /** * Assembles and writes bakes the view file. * * @param string $action Action to bake * @param string $content Content to write * @return bool Success */ public function bake($action, $content = '') { if ($content === true) { $content = $this->getContent($action); } if (empty($content)) { return false; } $this->out("\n" . __d('cake_console', 'Baking `%s` view file...', $action), 1, Shell::QUIET); $path = $this->getPath(); $filename = $path . $this->controllerName . DS . Inflector::underscore($action) . '.ctp'; return $this->createFile($filename, $content); } /** * Builds content from template and variables * * @param string $action name to generate content to * @param array $vars passed for use in templates * @return string content from template */ public function getContent($action, $vars = null) { if (!$vars) { $vars = $this->_loadController(); } $this->Template->set('action', $action); $this->Template->set('plugin', $this->plugin); $this->Template->set($vars); $template = $this->getTemplate($action); if ($template) { return $this->Template->generate('views', $template); } return false; } /** * Gets the template name based on the action name * * @param string $action name * @return string template name */ public function getTemplate($action) { if ($action != $this->template && in_array($action, $this->noTemplateActions)) { return false; } if (!empty($this->template) && $action != $this->template) { return $this->template; } $themePath = $this->Template->getThemePath(); if (file_exists($themePath . 'views' . DS . $action . '.ctp')) { return $action; } $template = $action; $prefixes = Configure::read('Routing.prefixes'); foreach ((array)$prefixes as $prefix) { if (strpos($template, $prefix) !== false) { $template = str_replace($prefix . '_', '', $template); } } if (in_array($template, array('add', 'edit'))) { $template = 'form'; } elseif (preg_match('@(_add|_edit)$@', $template)) { $template = str_replace(array('_add', '_edit'), '_form', $template); } return $template; } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description( __d('cake_console', 'Bake views for a controller, using built-in or custom templates.') )->addArgument('controller', array( 'help' => __d('cake_console', 'Name of the controller views to bake. Can be Plugin.name as a shortcut for plugin baking.') ))->addArgument('action', array( 'help' => __d('cake_console', "Will bake a single action's file. core templates are (index, add, edit, view)") ))->addArgument('alias', array( 'help' => __d('cake_console', 'Will bake the template in but create the filename after .') ))->addOption('plugin', array( 'short' => 'p', 'help' => __d('cake_console', 'Plugin to bake the view into.') ))->addOption('admin', array( 'help' => __d('cake_console', 'Set to only bake views for a prefix in Routing.prefixes'), 'boolean' => true ))->addOption('theme', array( 'short' => 't', 'help' => __d('cake_console', 'Theme to use when baking code.') ))->addOption('connection', array( 'short' => 'c', 'help' => __d('cake_console', 'The connection the connected model is on.') ))->addOption('force', array( 'short' => 'f', 'help' => __d('cake_console', 'Force overwriting existing files without prompting.') ))->addSubcommand('all', array( 'help' => __d('cake_console', 'Bake all CRUD action views for all controllers. Requires models and controllers to exist.') ))->epilog( __d('cake_console', 'Omitting all arguments and options will enter into an interactive mode.') ); return $parser; } /** * Returns associations for controllers models. * * @param Model $model The Model instance. * @return array associations */ protected function _associations(Model $model) { $keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'); $associations = array(); foreach ($keys as $type) { foreach ($model->{$type} as $assocKey => $assocData) { list(, $modelClass) = pluginSplit($assocData['className']); $associations[$type][$assocKey]['primaryKey'] = $model->{$assocKey}->primaryKey; $associations[$type][$assocKey]['displayField'] = $model->{$assocKey}->displayField; $associations[$type][$assocKey]['foreignKey'] = $assocData['foreignKey']; $associations[$type][$assocKey]['controller'] = Inflector::pluralize(Inflector::underscore($modelClass)); $associations[$type][$assocKey]['fields'] = array_keys($model->{$assocKey}->schema(true)); } } return $associations; } } cakephp-2.8.0/lib/Cake/Console/Command/TestShell.php000066400000000000000000000317531265552240500221640ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html * @since CakePHP(tm) v 1.2.0.4433 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Shell', 'Console'); App::uses('CakeTestSuiteDispatcher', 'TestSuite'); App::uses('CakeTestSuiteCommand', 'TestSuite'); App::uses('CakeTestLoader', 'TestSuite'); /** * Provides a CakePHP wrapper around PHPUnit. * Adds in CakePHP's fixtures and gives access to plugin, app and core test cases * * @package Cake.Console.Command */ class TestShell extends Shell { /** * Dispatcher object for the run. * * @var CakeTestDispatcher */ protected $_dispatcher = null; /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = new ConsoleOptionParser($this->name); $parser->description( __d('cake_console', 'The CakePHP Testsuite allows you to run test cases from the command line') )->addArgument('category', array( 'help' => __d('cake_console', 'The category for the test, or test file, to test.'), 'required' => false ))->addArgument('file', array( 'help' => __d('cake_console', 'The path to the file, or test file, to test.'), 'required' => false ))->addOption('log-junit', array( 'help' => __d('cake_console', ' Log test execution in JUnit XML format to file.'), 'default' => false ))->addOption('log-json', array( 'help' => __d('cake_console', ' Log test execution in JSON format to file.'), 'default' => false ))->addOption('log-tap', array( 'help' => __d('cake_console', ' Log test execution in TAP format to file.'), 'default' => false ))->addOption('log-dbus', array( 'help' => __d('cake_console', 'Log test execution to DBUS.'), 'default' => false ))->addOption('coverage-html', array( 'help' => __d('cake_console', ' Generate code coverage report in HTML format.'), 'default' => false ))->addOption('coverage-clover', array( 'help' => __d('cake_console', ' Write code coverage data in Clover XML format.'), 'default' => false ))->addOption('testdox-html', array( 'help' => __d('cake_console', ' Write agile documentation in HTML format to file.'), 'default' => false ))->addOption('testdox-text', array( 'help' => __d('cake_console', ' Write agile documentation in Text format to file.'), 'default' => false ))->addOption('filter', array( 'help' => __d('cake_console', ' Filter which tests to run.'), 'default' => false ))->addOption('group', array( 'help' => __d('cake_console', ' Only runs tests from the specified group(s).'), 'default' => false ))->addOption('exclude-group', array( 'help' => __d('cake_console', ' Exclude tests from the specified group(s).'), 'default' => false ))->addOption('list-groups', array( 'help' => __d('cake_console', 'List available test groups.'), 'boolean' => true ))->addOption('loader', array( 'help' => __d('cake_console', 'TestSuiteLoader implementation to use.'), 'default' => false ))->addOption('repeat', array( 'help' => __d('cake_console', ' Runs the test(s) repeatedly.'), 'default' => false ))->addOption('tap', array( 'help' => __d('cake_console', 'Report test execution progress in TAP format.'), 'boolean' => true ))->addOption('testdox', array( 'help' => __d('cake_console', 'Report test execution progress in TestDox format.'), 'default' => false, 'boolean' => true ))->addOption('no-colors', array( 'help' => __d('cake_console', 'Do not use colors in output.'), 'boolean' => true ))->addOption('stderr', array( 'help' => __d('cake_console', 'Write to STDERR instead of STDOUT.'), 'boolean' => true ))->addOption('stop-on-error', array( 'help' => __d('cake_console', 'Stop execution upon first error or failure.'), 'boolean' => true ))->addOption('stop-on-failure', array( 'help' => __d('cake_console', 'Stop execution upon first failure.'), 'boolean' => true ))->addOption('stop-on-skipped', array( 'help' => __d('cake_console', 'Stop execution upon first skipped test.'), 'boolean' => true ))->addOption('stop-on-incomplete', array( 'help' => __d('cake_console', 'Stop execution upon first incomplete test.'), 'boolean' => true ))->addOption('strict', array( 'help' => __d('cake_console', 'Mark a test as incomplete if no assertions are made.'), 'boolean' => true ))->addOption('wait', array( 'help' => __d('cake_console', 'Waits for a keystroke after each test.'), 'boolean' => true ))->addOption('process-isolation', array( 'help' => __d('cake_console', 'Run each test in a separate PHP process.'), 'boolean' => true ))->addOption('no-globals-backup', array( 'help' => __d('cake_console', 'Do not backup and restore $GLOBALS for each test.'), 'boolean' => true ))->addOption('static-backup', array( 'help' => __d('cake_console', 'Backup and restore static attributes for each test.'), 'boolean' => true ))->addOption('syntax-check', array( 'help' => __d('cake_console', 'Try to check source files for syntax errors.'), 'boolean' => true ))->addOption('bootstrap', array( 'help' => __d('cake_console', ' A "bootstrap" PHP file that is run before the tests.'), 'default' => false ))->addOption('configuration', array( 'help' => __d('cake_console', ' Read configuration from XML file.'), 'default' => false ))->addOption('no-configuration', array( 'help' => __d('cake_console', 'Ignore default configuration file (phpunit.xml).'), 'boolean' => true ))->addOption('include-path', array( 'help' => __d('cake_console', ' Prepend PHP include_path with given path(s).'), 'default' => false ))->addOption('directive', array( 'help' => __d('cake_console', 'key[=value] Sets a php.ini value.'), 'default' => false ))->addOption('fixture', array( 'help' => __d('cake_console', 'Choose a custom fixture manager.') ))->addOption('debug', array( 'help' => __d('cake_console', 'More verbose output.') )); return $parser; } /** * Initialization method installs PHPUnit and loads all plugins * * @return void * @throws Exception */ public function initialize() { $this->_dispatcher = new CakeTestSuiteDispatcher(); $success = $this->_dispatcher->loadTestFramework(); if (!$success) { throw new Exception(__d('cake_dev', 'Please install PHPUnit framework v3.7 (http://www.phpunit.de)')); } } /** * Parse the CLI options into an array CakeTestDispatcher can use. * * @return array|null Array of params for CakeTestDispatcher or null. */ protected function _parseArgs() { if (empty($this->args)) { return null; } $params = array( 'core' => false, 'app' => false, 'plugin' => null, 'output' => 'text', ); if (strpos($this->args[0], '.php')) { $category = $this->_mapFileToCategory($this->args[0]); $params['case'] = $this->_mapFileToCase($this->args[0], $category); } else { $category = $this->args[0]; if (isset($this->args[1])) { $params['case'] = $this->args[1]; } } if ($category === 'core') { $params['core'] = true; } elseif ($category === 'app') { $params['app'] = true; } else { $params['plugin'] = $category; } return $params; } /** * Converts the options passed to the shell as options for the PHPUnit cli runner * * @return array Array of params for CakeTestDispatcher */ protected function _runnerOptions() { $options = array(); $params = $this->params; unset($params['help']); unset($params['quiet']); if (!empty($params['no-colors'])) { unset($params['no-colors'], $params['colors']); } else { $params['colors'] = true; } foreach ($params as $param => $value) { if ($value === false) { continue; } $options[] = '--' . $param; if (is_string($value)) { $options[] = $value; } } return $options; } /** * Main entry point to this shell * * @return void */ public function main() { $this->out(__d('cake_console', 'CakePHP Test Shell')); $this->hr(); $args = $this->_parseArgs(); if (empty($args['case'])) { return $this->available(); } $this->_run($args, $this->_runnerOptions()); } /** * Runs the test case from $runnerArgs * * @param array $runnerArgs list of arguments as obtained from _parseArgs() * @param array $options list of options as constructed by _runnerOptions() * @return void */ protected function _run($runnerArgs, $options = array()) { restore_error_handler(); restore_error_handler(); $testCli = new CakeTestSuiteCommand('CakeTestLoader', $runnerArgs); $testCli->run($options); } /** * Shows a list of available test cases and gives the option to run one of them * * @return void */ public function available() { $params = $this->_parseArgs(); $testCases = CakeTestLoader::generateTestList($params); $app = $params['app']; $plugin = $params['plugin']; $title = "Core Test Cases:"; $category = 'core'; if ($app) { $title = "App Test Cases:"; $category = 'app'; } elseif ($plugin) { $title = Inflector::humanize($plugin) . " Test Cases:"; $category = $plugin; } if (empty($testCases)) { $this->out(__d('cake_console', "No test cases available \n\n")); return $this->out($this->OptionParser->help()); } $this->out($title); $i = 1; $cases = array(); foreach ($testCases as $testCase) { $case = str_replace('Test.php', '', $testCase); $this->out("[$i] $case"); $cases[$i] = $case; $i++; } while ($choice = $this->in(__d('cake_console', 'What test case would you like to run?'), null, 'q')) { if (is_numeric($choice) && isset($cases[$choice])) { $this->args[0] = $category; $this->args[1] = $cases[$choice]; $this->_run($this->_parseArgs(), $this->_runnerOptions()); break; } if (is_string($choice) && in_array($choice, $cases)) { $this->args[0] = $category; $this->args[1] = $choice; $this->_run($this->_parseArgs(), $this->_runnerOptions()); break; } if ($choice === 'q') { break; } } } /** * Find the test case for the passed file. The file could itself be a test. * * @param string $file The file to map. * @param string $category The test file category. * @param bool $throwOnMissingFile Whether or not to throw an exception. * @return array array(type, case) * @throws Exception */ protected function _mapFileToCase($file, $category, $throwOnMissingFile = true) { if (!$category || (substr($file, -4) !== '.php')) { return false; } $_file = realpath($file); if ($_file) { $file = $_file; } $testFile = $testCase = null; if (preg_match('@Test[\\\/]@', $file)) { if (substr($file, -8) === 'Test.php') { $testCase = substr($file, 0, -8); $testCase = str_replace(DS, '/', $testCase); if ($testCase = preg_replace('@.*Test\/Case\/@', '', $testCase)) { if ($category === 'core') { $testCase = str_replace('lib/Cake', '', $testCase); } return $testCase; } throw new Exception(__d('cake_dev', 'Test case %s cannot be run via this shell', $testFile)); } } $file = substr($file, 0, -4); if ($category === 'core') { $testCase = str_replace(DS, '/', $file); $testCase = preg_replace('@.*lib/Cake/@', '', $file); $testCase[0] = strtoupper($testCase[0]); $testFile = CAKE . 'Test/Case/' . $testCase . 'Test.php'; if (!file_exists($testFile) && $throwOnMissingFile) { throw new Exception(__d('cake_dev', 'Test case %s not found', $testFile)); } return $testCase; } if ($category === 'app') { $testFile = str_replace(APP, APP . 'Test/Case/', $file) . 'Test.php'; } else { $testFile = preg_replace( "@((?:plugins|Plugin)[\\/]{$category}[\\/])(.*)$@", '\1Test/Case/\2Test.php', $file ); } if (!file_exists($testFile) && $throwOnMissingFile) { throw new Exception(__d('cake_dev', 'Test case %s not found', $testFile)); } $testCase = substr($testFile, 0, -8); $testCase = str_replace(DS, '/', $testCase); $testCase = preg_replace('@.*Test/Case/@', '', $testCase); return $testCase; } /** * For the given file, what category of test is it? returns app, core or the name of the plugin * * @param string $file The file to map. * @return string */ protected function _mapFileToCategory($file) { $_file = realpath($file); if ($_file) { $file = $_file; } $file = str_replace(DS, '/', $file); if (strpos($file, 'lib/Cake/') !== false) { return 'core'; } elseif (preg_match('@(?:plugins|Plugin)/([^/]*)@', $file, $match)) { return $match[1]; } return 'app'; } } cakephp-2.8.0/lib/Cake/Console/Command/TestsuiteShell.php000066400000000000000000000050021265552240500232220ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html * @since CakePHP(tm) v 1.2.0.4433 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('TestShell', 'Console/Command'); App::uses('AppShell', 'Console/Command'); App::uses('CakeTestSuiteDispatcher', 'TestSuite'); App::uses('CakeTestSuiteCommand', 'TestSuite'); App::uses('CakeTestLoader', 'TestSuite'); /** * Provides a CakePHP wrapper around PHPUnit. * Adds in CakePHP's fixtures and gives access to plugin, app and core test cases * * @package Cake.Console.Command */ class TestsuiteShell extends TestShell { /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $parser->description(array( __d('cake_console', 'The CakePHP Testsuite allows you to run test cases from the command line'), __d('cake_console', "This shell is for backwards-compatibility only\nuse the test shell instead") )); return $parser; } /** * Parse the CLI options into an array CakeTestDispatcher can use. * * @return array Array of params for CakeTestDispatcher */ protected function _parseArgs() { if (empty($this->args)) { return; } $params = array( 'core' => false, 'app' => false, 'plugin' => null, 'output' => 'text', ); $category = $this->args[0]; if ($category === 'core') { $params['core'] = true; } elseif ($category === 'app') { $params['app'] = true; } elseif ($category !== 'core') { $params['plugin'] = $category; } if (isset($this->args[1])) { $params['case'] = $this->args[1]; } return $params; } /** * Main entry point to this shell * * @return void */ public function main() { $this->out(__d('cake_console', 'CakePHP Test Shell')); $this->hr(); $args = $this->_parseArgs(); if (empty($args['case'])) { return $this->available(); } $this->_run($args, $this->_runnerOptions()); } } cakephp-2.8.0/lib/Cake/Console/Command/UpgradeShell.php000066400000000000000000000554201265552240500226310ustar00rootroot00000000000000 'Controller', 'Component' => 'Controller/Component', 'Model' => 'Model', 'Behavior' => 'Model/Behavior', 'Datasource' => 'Model/Datasource', 'Dbo' => 'Model/Datasource/Database', 'View' => 'View', 'Helper' => 'View/Helper', 'Shell' => 'Console/Command', 'Task' => 'Console/Command/Task', 'Case' => 'Test/Case', 'Fixture' => 'Test/Fixture', 'Error' => 'Lib/Error', ); /** * Shell startup, prints info message about dry run. * * @return void */ public function startup() { parent::startup(); if ($this->params['dry-run']) { $this->out(__d('cake_console', 'Dry-run mode enabled!'), 1, Shell::QUIET); } if ($this->params['git'] && !is_dir('.git')) { $this->out(__d('cake_console', 'No git repository detected!'), 1, Shell::QUIET); } } /** * Run all upgrade steps one at a time * * @return void */ public function all() { foreach ($this->OptionParser->subcommands() as $command) { $name = $command->name(); if ($name === 'all') { continue; } $this->out(__d('cake_console', 'Running %s', $name)); $this->$name(); } } /** * Update tests. * * - Update tests class names to FooTest rather than FooTestCase. * * @return void */ public function tests() { $this->_paths = array(APP . 'tests' . DS); if (!empty($this->params['plugin'])) { $this->_paths = array(CakePlugin::path($this->params['plugin']) . 'tests' . DS); } $patterns = array( array( '*TestCase extends CakeTestCase to *Test extends CakeTestCase', '/([a-zA-Z]*Test)Case extends CakeTestCase/', '\1 extends CakeTestCase' ), ); $this->_filesRegexpUpdate($patterns); } /** * Move files and folders to their new homes * * Moves folders containing files which cannot necessarily be auto-detected (libs and templates) * and then looks for all php files except vendors, and moves them to where Cake 2.0 expects * to find them. * * @return void */ public function locations() { $cwd = getcwd(); if (!empty($this->params['plugin'])) { chdir(CakePlugin::path($this->params['plugin'])); } if (is_dir('plugins')) { $Folder = new Folder('plugins'); list($plugins) = $Folder->read(); foreach ($plugins as $plugin) { chdir($cwd . DS . 'plugins' . DS . $plugin); $this->out(__d('cake_console', 'Upgrading locations for plugin %s', $plugin)); $this->locations(); } $this->_files = array(); chdir($cwd); $this->out(__d('cake_console', 'Upgrading locations for app directory')); } $moves = array( 'config' => 'Config', 'Config' . DS . 'schema' => 'Config' . DS . 'Schema', 'libs' => 'Lib', 'tests' => 'Test', 'views' => 'View', 'models' => 'Model', 'Model' . DS . 'behaviors' => 'Model' . DS . 'Behavior', 'Model' . DS . 'datasources' => 'Model' . DS . 'Datasource', 'Test' . DS . 'cases' => 'Test' . DS . 'Case', 'Test' . DS . 'fixtures' => 'Test' . DS . 'Fixture', 'vendors' . DS . 'shells' . DS . 'templates' => 'Console' . DS . 'Templates', ); foreach ($moves as $old => $new) { if (is_dir($old)) { $this->out(__d('cake_console', 'Moving %s to %s', $old, $new)); if (!$this->params['dry-run']) { if ($this->params['git']) { exec('git mv -f ' . escapeshellarg($old) . ' ' . escapeshellarg($old . '__')); exec('git mv -f ' . escapeshellarg($old . '__') . ' ' . escapeshellarg($new)); } else { $Folder = new Folder($old); $Folder->move($new); } } } } $this->_moveViewFiles(); $this->_moveAppClasses(); $sourceDirs = array( '.' => array('recursive' => false), 'Console', 'controllers', 'Controller', 'Lib' => array('checkFolder' => false), 'models', 'Model', 'tests', 'Test' => array('regex' => '@class (\S*Test) extends CakeTestCase@'), 'views', 'View', 'vendors/shells', ); $defaultOptions = array( 'recursive' => true, 'checkFolder' => true, 'regex' => '@class (\S*) .*(\s|\v)*{@i' ); foreach ($sourceDirs as $dir => $options) { if (is_numeric($dir)) { $dir = $options; $options = array(); } $options += $defaultOptions; $this->_movePhpFiles($dir, $options); } } /** * Update helpers. * * - Converts helpers usage to new format. * * @return void */ public function helpers() { $this->_paths = array_diff(App::path('views'), App::core('views')); if (!empty($this->params['plugin'])) { $this->_paths = array(CakePlugin::path($this->params['plugin']) . 'views' . DS); } $patterns = array(); App::build(array( 'View/Helper' => App::core('View/Helper'), ), App::APPEND); $helpers = App::objects('helper'); $plugins = App::objects('plugin'); $pluginHelpers = array(); foreach ($plugins as $plugin) { CakePlugin::load($plugin); $pluginHelpers = array_merge( $pluginHelpers, App::objects('helper', CakePlugin::path($plugin) . DS . 'views' . DS . 'helpers' . DS, false) ); } $helpers = array_merge($pluginHelpers, $helpers); foreach ($helpers as $helper) { $helper = preg_replace('/Helper$/', '', $helper); $oldHelper = $helper; $oldHelper{0} = strtolower($oldHelper{0}); $patterns[] = array( "\${$oldHelper} to \$this->{$helper}", "/\\\${$oldHelper}->/", "\\\$this->{$helper}->" ); } $this->_filesRegexpUpdate($patterns); } /** * Update i18n. * * - Removes extra true param. * - Add the echo to __*() calls that didn't need them before. * * @return void */ public function i18n() { $this->_paths = array( APP ); if (!empty($this->params['plugin'])) { $this->_paths = array(CakePlugin::path($this->params['plugin'])); } $patterns = array( array( '_filesRegexpUpdate($patterns); } /** * Upgrade the removed basics functions. * * - a(*) -> array(*) * - e(*) -> echo * * - ife(*, *, *) -> !empty(*) ? * : * * - a(*) -> array(*) * - r(*, *, *) -> str_replace(*, *, *) * - up(*) -> strtoupper(*) * - low(*, *, *) -> strtolower(*) * - getMicrotime() -> microtime(true) * * @return void */ public function basics() { $this->_paths = array( APP ); if (!empty($this->params['plugin'])) { $this->_paths = array(CakePlugin::path($this->params['plugin'])); } $patterns = array( array( 'a(*) -> array(*)', '/\ba\((.*)\)/', 'array(\1)' ), array( 'e(*) -> echo *', '/\be\((.*)\)/', 'echo \1' ), array( 'ife(*, *, *) -> !empty(*) ? * : *', '/ife\((.*), (.*), (.*)\)/', '!empty(\1) ? \2 : \3' ), array( 'r(*, *, *) -> str_replace(*, *, *)', '/\br\(/', 'str_replace(' ), array( 'up(*) -> strtoupper(*)', '/\bup\(/', 'strtoupper(' ), array( 'low(*) -> strtolower(*)', '/\blow\(/', 'strtolower(' ), array( 'getMicrotime() -> microtime(true)', '/getMicrotime\(\)/', 'microtime(true)' ), ); $this->_filesRegexpUpdate($patterns); } /** * Update the properties moved to CakeRequest. * * @return void */ public function request() { $views = array_diff(App::path('views'), App::core('views')); $controllers = array_diff(App::path('controllers'), App::core('controllers'), array(APP)); $components = array_diff(App::path('components'), App::core('components')); $this->_paths = array_merge($views, $controllers, $components); if (!empty($this->params['plugin'])) { $pluginPath = CakePlugin::path($this->params['plugin']); $this->_paths = array( $pluginPath . 'controllers' . DS, $pluginPath . 'controllers' . DS . 'components' . DS, $pluginPath . 'views' . DS, ); } $patterns = array( array( '$this->data -> $this->request->data', '/(\$this->data\b(?!\())/', '$this->request->data' ), array( '$this->params -> $this->request->params', '/(\$this->params\b(?!\())/', '$this->request->params' ), array( '$this->webroot -> $this->request->webroot', '/(\$this->webroot\b(?!\())/', '$this->request->webroot' ), array( '$this->base -> $this->request->base', '/(\$this->base\b(?!\())/', '$this->request->base' ), array( '$this->here -> $this->request->here', '/(\$this->here\b(?!\())/', '$this->request->here' ), array( '$this->action -> $this->request->action', '/(\$this->action\b(?!\())/', '$this->request->action' ), array( '$this->request->onlyAllow() -> $this->request->allowMethod()', '/\$this->request->onlyAllow\(/', '$this->request->allowMethod(' ) ); $this->_filesRegexpUpdate($patterns); } /** * Update Configure::read() calls with no params. * * @return void */ public function configure() { $this->_paths = array( APP ); if (!empty($this->params['plugin'])) { $this->_paths = array(CakePlugin::path($this->params['plugin'])); } $patterns = array( array( "Configure::read() -> Configure::read('debug')", '/Configure::read\(\)/', 'Configure::read(\'debug\')' ), ); $this->_filesRegexpUpdate($patterns); } /** * constants * * @return void */ public function constants() { $this->_paths = array( APP ); if (!empty($this->params['plugin'])) { $this->_paths = array(CakePlugin::path($this->params['plugin'])); } $patterns = array( array( "LIBS -> CAKE", '/\bLIBS\b/', 'CAKE' ), array( "CONFIGS -> APP . 'Config' . DS", '/\bCONFIGS\b/', 'APP . \'Config\' . DS' ), array( "CONTROLLERS -> APP . 'Controller' . DS", '/\bCONTROLLERS\b/', 'APP . \'Controller\' . DS' ), array( "COMPONENTS -> APP . 'Controller' . DS . 'Component' . DS", '/\bCOMPONENTS\b/', 'APP . \'Controller\' . DS . \'Component\'' ), array( "MODELS -> APP . 'Model' . DS", '/\bMODELS\b/', 'APP . \'Model\' . DS' ), array( "BEHAVIORS -> APP . 'Model' . DS . 'Behavior' . DS", '/\bBEHAVIORS\b/', 'APP . \'Model\' . DS . \'Behavior\' . DS' ), array( "VIEWS -> APP . 'View' . DS", '/\bVIEWS\b/', 'APP . \'View\' . DS' ), array( "HELPERS -> APP . 'View' . DS . 'Helper' . DS", '/\bHELPERS\b/', 'APP . \'View\' . DS . \'Helper\' . DS' ), array( "LAYOUTS -> APP . 'View' . DS . 'Layouts' . DS", '/\bLAYOUTS\b/', 'APP . \'View\' . DS . \'Layouts\' . DS' ), array( "ELEMENTS -> APP . 'View' . DS . 'Elements' . DS", '/\bELEMENTS\b/', 'APP . \'View\' . DS . \'Elements\' . DS' ), array( "CONSOLE_LIBS -> CAKE . 'Console' . DS", '/\bCONSOLE_LIBS\b/', 'CAKE . \'Console\' . DS' ), array( "CAKE_TESTS_LIB -> CAKE . 'TestSuite' . DS", '/\bCAKE_TESTS_LIB\b/', 'CAKE . \'TestSuite\' . DS' ), array( "CAKE_TESTS -> CAKE . 'Test' . DS", '/\bCAKE_TESTS\b/', 'CAKE . \'Test\' . DS' ) ); $this->_filesRegexpUpdate($patterns); } /** * Update controller redirects. * * - Make redirect statements return early. * * @return void */ public function controller_redirects() { $this->_paths = App::Path('Controller'); if (!empty($this->params['plugin'])) { $this->_paths = App::Path('Controller', $this->params['plugin']); } $patterns = array( array( '$this->redirect() to return $this->redirect()', '/\t\$this-\>redirect\(/', "\t" . 'return $this->redirect(' ), ); $this->_filesRegexpUpdate($patterns); } /** * Update components. * * - Make components that extend Object to extend Component. * * @return void */ public function components() { $this->_paths = App::Path('Controller/Component'); if (!empty($this->params['plugin'])) { $this->_paths = App::Path('Controller/Component', $this->params['plugin']); } $patterns = array( array( '*Component extends Object to *Component extends Component', '/([a-zA-Z]*Component extends) Object/', '\1 Component' ), ); $this->_filesRegexpUpdate($patterns); } /** * Replace cakeError with built-in exceptions. * NOTE: this ignores calls where you've passed your own secondary parameters to cakeError(). * * @return void */ public function exceptions() { $controllers = array_diff(App::path('controllers'), App::core('controllers'), array(APP)); $components = array_diff(App::path('components'), App::core('components')); $this->_paths = array_merge($controllers, $components); if (!empty($this->params['plugin'])) { $pluginPath = CakePlugin::path($this->params['plugin']); $this->_paths = array( $pluginPath . 'controllers' . DS, $pluginPath . 'controllers' . DS . 'components' . DS, ); } $patterns = array( array( '$this->cakeError("error400") -> throw new BadRequestException()', '/(\$this->cakeError\(["\']error400["\']\));/', 'throw new BadRequestException();' ), array( '$this->cakeError("error404") -> throw new NotFoundException()', '/(\$this->cakeError\(["\']error404["\']\));/', 'throw new NotFoundException();' ), array( '$this->cakeError("error500") -> throw new InternalErrorException()', '/(\$this->cakeError\(["\']error500["\']\));/', 'throw new InternalErrorException();' ), ); $this->_filesRegexpUpdate($patterns); } /** * Move application views files to where they now should be * * Find all view files in the folder and determine where cake expects the file to be * * @return void */ protected function _moveViewFiles() { if (!is_dir('View')) { return; } $dirs = scandir('View'); foreach ($dirs as $old) { if (!is_dir('View' . DS . $old) || $old === '.' || $old === '..') { continue; } $new = 'View' . DS . Inflector::camelize($old); $old = 'View' . DS . $old; if ($new === $old) { continue; } $this->out(__d('cake_console', 'Moving %s to %s', $old, $new)); if (!$this->params['dry-run']) { if ($this->params['git']) { exec('git mv -f ' . escapeshellarg($old) . ' ' . escapeshellarg($old . '__')); exec('git mv -f ' . escapeshellarg($old . '__') . ' ' . escapeshellarg($new)); } else { $Folder = new Folder($old); $Folder->move($new); } } } } /** * Move the AppController, and AppModel classes. * * @return void */ protected function _moveAppClasses() { $files = array( APP . 'app_controller.php' => APP . 'Controller' . DS . 'AppController.php', APP . 'controllers' . DS . 'app_controller.php' => APP . 'Controller' . DS . 'AppController.php', APP . 'app_model.php' => APP . 'Model' . DS . 'AppModel.php', APP . 'models' . DS . 'app_model.php' => APP . 'Model' . DS . 'AppModel.php', ); foreach ($files as $old => $new) { if (file_exists($old)) { $this->out(__d('cake_console', 'Moving %s to %s', $old, $new)); if ($this->params['dry-run']) { continue; } if ($this->params['git']) { exec('git mv -f ' . escapeshellarg($old) . ' ' . escapeshellarg($old . '__')); exec('git mv -f ' . escapeshellarg($old . '__') . ' ' . escapeshellarg($new)); } else { rename($old, $new); } } } } /** * Move application php files to where they now should be * * Find all php files in the folder (honoring recursive) and determine where CakePHP expects the file to be * If the file is not exactly where CakePHP expects it - move it. * * @param string $path The path to move files in. * @param array $options array(recursive, checkFolder) * @return void */ protected function _movePhpFiles($path, $options) { if (!is_dir($path)) { return; } $paths = $this->_paths; $this->_paths = array($path); $this->_files = array(); if ($options['recursive']) { $this->_findFiles('php'); } else { $this->_files = scandir($path); foreach ($this->_files as $i => $file) { if (strlen($file) < 5 || substr($file, -4) !== '.php') { unset($this->_files[$i]); } } } $cwd = getcwd(); foreach ($this->_files as &$file) { $file = $cwd . DS . $file; $contents = file_get_contents($file); preg_match($options['regex'], $contents, $match); if (!$match) { continue; } $class = $match[1]; if (substr($class, 0, 3) === 'Dbo') { $type = 'Dbo'; } else { preg_match('@([A-Z][^A-Z]*)$@', $class, $match); if ($match) { $type = $match[1]; } else { $type = 'unknown'; } } preg_match('@^.*[\\\/]plugins[\\\/](.*?)[\\\/]@', $file, $match); $base = $cwd . DS; $plugin = false; if ($match) { $base = $match[0]; $plugin = $match[1]; } if ($options['checkFolder'] && !empty($this->_map[$type])) { $folder = str_replace('/', DS, $this->_map[$type]); $new = $base . $folder . DS . $class . '.php'; } else { $new = dirname($file) . DS . $class . '.php'; } if ($file === $new) { continue; } $dir = dirname($new); if (!is_dir($dir)) { new Folder($dir, true); } $this->out(__d('cake_console', 'Moving %s to %s', $file, $new), 1, Shell::VERBOSE); if (!$this->params['dry-run']) { if ($this->params['git']) { exec('git mv -f ' . escapeshellarg($file) . ' ' . escapeshellarg($file . '__')); exec('git mv -f ' . escapeshellarg($file . '__') . ' ' . escapeshellarg($new)); } else { rename($file, $new); } } } $this->_paths = $paths; } /** * Updates files based on regular expressions. * * @param array $patterns Array of search and replacement patterns. * @return void */ protected function _filesRegexpUpdate($patterns) { $this->_findFiles($this->params['ext']); foreach ($this->_files as $file) { $this->out(__d('cake_console', 'Updating %s...', $file), 1, Shell::VERBOSE); $this->_updateFile($file, $patterns); } } /** * Searches the paths and finds files based on extension. * * @param string $extensions The extensions to include. Defaults to none. * @return void */ protected function _findFiles($extensions = '') { $this->_files = array(); foreach ($this->_paths as $path) { if (!is_dir($path)) { continue; } $Iterator = new RegexIterator( new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)), '/^.+\.(' . $extensions . ')$/i', RegexIterator::MATCH ); foreach ($Iterator as $file) { if ($file->isFile()) { $this->_files[] = $file->getPathname(); } } } } /** * Update a single file. * * @param string $file The file to update * @param array $patterns The replacement patterns to run. * @return void */ protected function _updateFile($file, $patterns) { $contents = file_get_contents($file); foreach ($patterns as $pattern) { $this->out(__d('cake_console', ' * Updating %s', $pattern[0]), 1, Shell::VERBOSE); $contents = preg_replace($pattern[1], $pattern[2], $contents); } $this->out(__d('cake_console', 'Done updating %s', $file), 1); if (!$this->params['dry-run']) { file_put_contents($file, $contents); } } /** * Gets the option parser instance and configures it. * * @return ConsoleOptionParser */ public function getOptionParser() { $parser = parent::getOptionParser(); $subcommandParser = array( 'options' => array( 'plugin' => array( 'short' => 'p', 'help' => __d('cake_console', 'The plugin to update. Only the specified plugin will be updated.') ), 'ext' => array( 'short' => 'e', 'help' => __d('cake_console', 'The extension(s) to search. A pipe delimited list, or a preg_match compatible subpattern'), 'default' => 'php|ctp|thtml|inc|tpl' ), 'git' => array( 'short' => 'g', 'help' => __d('cake_console', 'Use git command for moving files around.'), 'boolean' => true ), 'dry-run' => array( 'short' => 'd', 'help' => __d('cake_console', 'Dry run the update, no files will actually be modified.'), 'boolean' => true ) ) ); $parser->description( __d('cake_console', "A tool to help automate upgrading an application or plugin " . "from CakePHP 1.3 to 2.0. Be sure to have a backup of your application before " . "running these commands." ))->addSubcommand('all', array( 'help' => __d('cake_console', 'Run all upgrade commands.'), 'parser' => $subcommandParser ))->addSubcommand('tests', array( 'help' => __d('cake_console', 'Update tests class names to FooTest rather than FooTestCase.'), 'parser' => $subcommandParser ))->addSubcommand('locations', array( 'help' => __d('cake_console', 'Move files and folders to their new homes.'), 'parser' => $subcommandParser ))->addSubcommand('i18n', array( 'help' => __d('cake_console', 'Update the i18n translation method calls.'), 'parser' => $subcommandParser ))->addSubcommand('helpers', array( 'help' => __d('cake_console', 'Update calls to helpers.'), 'parser' => $subcommandParser ))->addSubcommand('basics', array( 'help' => __d('cake_console', 'Update removed basics functions to PHP native functions.'), 'parser' => $subcommandParser ))->addSubcommand('request', array( 'help' => __d('cake_console', 'Update removed request access, and replace with $this->request.'), 'parser' => $subcommandParser ))->addSubcommand('configure', array( 'help' => __d('cake_console', "Update Configure::read() to Configure::read('debug')"), 'parser' => $subcommandParser ))->addSubcommand('constants', array( 'help' => __d('cake_console', "Replace Obsolete constants"), 'parser' => $subcommandParser ))->addSubcommand('controller_redirects', array( 'help' => __d('cake_console', 'Return early on controller redirect calls.'), 'parser' => $subcommandParser ))->addSubcommand('components', array( 'help' => __d('cake_console', 'Update components to extend Component class.'), 'parser' => $subcommandParser ))->addSubcommand('exceptions', array( 'help' => __d('cake_console', 'Replace use of cakeError with exceptions.'), 'parser' => $subcommandParser )); return $parser; } } cakephp-2.8.0/lib/Cake/Console/ConsoleErrorHandler.php000066400000000000000000000055151265552240500226060ustar00rootroot00000000000000write(__d('cake_console', "Error: %s\n%s", $exception->getMessage(), $exception->getTraceAsString() )); $code = $exception->getCode(); $code = ($code && is_int($code)) ? $code : 1; return $this->_stop($code); } /** * Handle errors in the console environment. Writes errors to stderr, * and logs messages if Configure::read('debug') is 0. * * @param int $code Error code * @param string $description Description of the error. * @param string $file The file the error occurred in. * @param int $line The line the error occurred on. * @param array $context The backtrace of the error. * @return void */ public function handleError($code, $description, $file = null, $line = null, $context = null) { if (error_reporting() === 0) { return; } $stderr = static::getStderr(); list($name, $log) = ErrorHandler::mapErrorCode($code); $message = __d('cake_console', '%s in [%s, line %s]', $description, $file, $line); $stderr->write(__d('cake_console', "%s Error: %s\n", $name, $message)); if (!Configure::read('debug')) { CakeLog::write($log, $message); } if ($log === LOG_ERR) { return $this->_stop(1); } } /** * Wrapper for exit(), used for testing. * * @param int $code The exit code. * @return void */ protected function _stop($code = 0) { exit($code); } } cakephp-2.8.0/lib/Cake/Console/ConsoleInput.php000066400000000000000000000037731265552240500213220ustar00rootroot00000000000000_canReadline = extension_loaded('readline') && $handle === 'php://stdin' ? true : false; $this->_input = fopen($handle, 'r'); } /** * Read a value from the stream * * @return mixed The value of the stream */ public function read() { if ($this->_canReadline) { $line = readline(''); if (!empty($line)) { readline_add_history($line); } return $line; } return fgets($this->_input); } /** * Checks if data is available on the stream * * @param int $timeout An optional time to wait for data * @return bool True for data available, false otherwise */ public function dataAvailable($timeout = 0) { $readFds = array($this->_input); $readyFds = stream_select($readFds, $writeFds, $errorFds, $timeout); return ($readyFds > 0); } } cakephp-2.8.0/lib/Cake/Console/ConsoleInputArgument.php000066400000000000000000000101421265552240500230110ustar00rootroot00000000000000 $value) { $this->{'_' . $key} = $value; } } else { $this->_name = $name; $this->_help = $help; $this->_required = $required; $this->_choices = $choices; } } /** * Get the value of the name attribute. * * @return string Value of this->_name. */ public function name() { return $this->_name; } /** * Generate the help for this argument. * * @param int $width The width to make the name of the option. * @return string */ public function help($width = 0) { $name = $this->_name; if (strlen($name) < $width) { $name = str_pad($name, $width, ' '); } $optional = ''; if (!$this->isRequired()) { $optional = __d('cake_console', ' (optional)'); } if (!empty($this->_choices)) { $optional .= __d('cake_console', ' (choices: %s)', implode('|', $this->_choices)); } return sprintf('%s%s%s', $name, $this->_help, $optional); } /** * Get the usage value for this argument * * @return string */ public function usage() { $name = $this->_name; if (!empty($this->_choices)) { $name = implode('|', $this->_choices); } $name = '<' . $name . '>'; if (!$this->isRequired()) { $name = '[' . $name . ']'; } return $name; } /** * Check if this argument is a required argument * * @return bool */ public function isRequired() { return (bool)$this->_required; } /** * Check that $value is a valid choice for this argument. * * @param string $value The choice to validate. * @return bool * @throws ConsoleException */ public function validChoice($value) { if (empty($this->_choices)) { return true; } if (!in_array($value, $this->_choices)) { throw new ConsoleException( __d('cake_console', '"%s" is not a valid value for %s. Please use one of "%s"', $value, $this->_name, implode(', ', $this->_choices) )); } return true; } /** * Append this arguments XML representation to the passed in SimpleXml object. * * @param SimpleXmlElement $parent The parent element. * @return SimpleXmlElement The parent with this argument appended. */ public function xml(SimpleXmlElement $parent) { $option = $parent->addChild('argument'); $option->addAttribute('name', $this->_name); $option->addAttribute('help', $this->_help); $option->addAttribute('required', $this->isRequired()); $choices = $option->addChild('choices'); foreach ($this->_choices as $valid) { $choices->addChild('choice', $valid); } return $parent; } } cakephp-2.8.0/lib/Cake/Console/ConsoleInputOption.php000066400000000000000000000125161265552240500225060ustar00rootroot00000000000000 $value) { $this->{'_' . $key} = $value; } } else { $this->_name = $name; $this->_short = $short; $this->_help = $help; $this->_boolean = $boolean; $this->_default = $default; $this->_choices = $choices; } if (strlen($this->_short) > 1) { throw new ConsoleException( __d('cake_console', 'Short option "%s" is invalid, short options must be one letter.', $this->_short) ); } } /** * Get the value of the name attribute. * * @return string Value of this->_name. */ public function name() { return $this->_name; } /** * Get the value of the short attribute. * * @return string Value of this->_short. */ public function short() { return $this->_short; } /** * Generate the help for this this option. * * @param int $width The width to make the name of the option. * @return string */ public function help($width = 0) { $default = $short = ''; if (!empty($this->_default) && $this->_default !== true) { $default = __d('cake_console', ' (default: %s)', $this->_default); } if (!empty($this->_choices)) { $default .= __d('cake_console', ' (choices: %s)', implode('|', $this->_choices)); } if (!empty($this->_short)) { $short = ', -' . $this->_short; } $name = sprintf('--%s%s', $this->_name, $short); if (strlen($name) < $width) { $name = str_pad($name, $width, ' '); } return sprintf('%s%s%s', $name, $this->_help, $default); } /** * Get the usage value for this option * * @return string */ public function usage() { $name = empty($this->_short) ? '--' . $this->_name : '-' . $this->_short; $default = ''; if (!empty($this->_default) && $this->_default !== true) { $default = ' ' . $this->_default; } if (!empty($this->_choices)) { $default = ' ' . implode('|', $this->_choices); } return sprintf('[%s%s]', $name, $default); } /** * Get the default value for this option * * @return mixed */ public function defaultValue() { return $this->_default; } /** * Check if this option is a boolean option * * @return bool */ public function isBoolean() { return (bool)$this->_boolean; } /** * Check that a value is a valid choice for this option. * * @param string $value The choice to validate. * @return bool * @throws ConsoleException */ public function validChoice($value) { if (empty($this->_choices)) { return true; } if (!in_array($value, $this->_choices)) { throw new ConsoleException( __d('cake_console', '"%s" is not a valid value for --%s. Please use one of "%s"', $value, $this->_name, implode(', ', $this->_choices) )); } return true; } /** * Append the option's xml into the parent. * * @param SimpleXmlElement $parent The parent element. * @return SimpleXmlElement The parent with this option appended. */ public function xml(SimpleXmlElement $parent) { $option = $parent->addChild('option'); $option->addAttribute('name', '--' . $this->_name); $short = ''; if (strlen($this->_short)) { $short = $this->_short; } $option->addAttribute('short', '-' . $short); $option->addAttribute('boolean', $this->_boolean); $option->addChild('default', $this->_default); $choices = $option->addChild('choices'); foreach ($this->_choices as $valid) { $choices->addChild('choice', $valid); } return $parent; } } cakephp-2.8.0/lib/Cake/Console/ConsoleInputSubcommand.php000066400000000000000000000057641265552240500233350ustar00rootroot00000000000000 $value) { $this->{'_' . $key} = $value; } } else { $this->_name = $name; $this->_help = $help; $this->_parser = $parser; } if (is_array($this->_parser)) { $this->_parser['command'] = $this->_name; $this->_parser = ConsoleOptionParser::buildFromArray($this->_parser); } } /** * Get the value of the name attribute. * * @return string Value of this->_name. */ public function name() { return $this->_name; } /** * Generate the help for this this subcommand. * * @param int $width The width to make the name of the subcommand. * @return string */ public function help($width = 0) { $name = $this->_name; if (strlen($name) < $width) { $name = str_pad($name, $width, ' '); } return $name . $this->_help; } /** * Get the usage value for this option * * @return mixed Either false or a ConsoleOptionParser */ public function parser() { if ($this->_parser instanceof ConsoleOptionParser) { return $this->_parser; } return false; } /** * Append this subcommand to the Parent element * * @param SimpleXmlElement $parent The parent element. * @return SimpleXmlElement The parent with this subcommand appended. */ public function xml(SimpleXmlElement $parent) { $command = $parent->addChild('command'); $command->addAttribute('name', $this->_name); $command->addAttribute('help', $this->_help); return $parent; } } cakephp-2.8.0/lib/Cake/Console/ConsoleOptionParser.php000066400000000000000000000477521265552240500226550ustar00rootroot00000000000000addOption()` * you can define new options. The name of the option is used as its long form, and you * can supply an additional short form, with the `short` option. Short options should * only be one letter long. Using more than one letter for a short option will raise an exception. * * Calling options can be done using syntax similar to most *nix command line tools. Long options * cane either include an `=` or leave it out. * * `cake myshell command --connection default --name=something` * * Short options can be defined signally or in groups. * * `cake myshell command -cn` * * Short options can be combined into groups as seen above. Each letter in a group * will be treated as a separate option. The previous example is equivalent to: * * `cake myshell command -c -n` * * Short options can also accept values: * * `cake myshell command -c default` * * ### Positional arguments * * If no positional arguments are defined, all of them will be parsed. If you define positional * arguments any arguments greater than those defined will cause exceptions. Additionally you can * declare arguments as optional, by setting the required param to false. * * `$parser->addArgument('model', array('required' => false));` * * ### Providing Help text * * By providing help text for your positional arguments and named arguments, the ConsoleOptionParser * can generate a help display for you. You can view the help for shells by using the `--help` or `-h` switch. * * @package Cake.Console */ class ConsoleOptionParser { /** * Description text - displays before options when help is generated * * @see ConsoleOptionParser::description() * @var string */ protected $_description = null; /** * Epilog text - displays after options when help is generated * * @see ConsoleOptionParser::epilog() * @var string */ protected $_epilog = null; /** * Option definitions. * * @see ConsoleOptionParser::addOption() * @var array */ protected $_options = array(); /** * Map of short -> long options, generated when using addOption() * * @var string */ protected $_shortOptions = array(); /** * Positional argument definitions. * * @see ConsoleOptionParser::addArgument() * @var array */ protected $_args = array(); /** * Subcommands for this Shell. * * @see ConsoleOptionParser::addSubcommand() * @var array */ protected $_subcommands = array(); /** * Command name. * * @var string */ protected $_command = ''; /** * Construct an OptionParser so you can define its behavior * * @param string $command The command name this parser is for. The command name is used for generating help. * @param bool $defaultOptions Whether you want the verbose and quiet options set. Setting * this to false will prevent the addition of `--verbose` & `--quiet` options. */ public function __construct($command = null, $defaultOptions = true) { $this->command($command); $this->addOption('help', array( 'short' => 'h', 'help' => __d('cake_console', 'Display this help.'), 'boolean' => true )); if ($defaultOptions) { $this->addOption('verbose', array( 'short' => 'v', 'help' => __d('cake_console', 'Enable verbose output.'), 'boolean' => true ))->addOption('quiet', array( 'short' => 'q', 'help' => __d('cake_console', 'Enable quiet output.'), 'boolean' => true )); } } /** * Static factory method for creating new OptionParsers so you can chain methods off of them. * * @param string $command The command name this parser is for. The command name is used for generating help. * @param bool $defaultOptions Whether you want the verbose and quiet options set. * @return ConsoleOptionParser */ public static function create($command, $defaultOptions = true) { return new ConsoleOptionParser($command, $defaultOptions); } /** * Build a parser from an array. Uses an array like * * ``` * $spec = array( * 'description' => 'text', * 'epilog' => 'text', * 'arguments' => array( * // list of arguments compatible with addArguments. * ), * 'options' => array( * // list of options compatible with addOptions * ), * 'subcommands' => array( * // list of subcommands to add. * ) * ); * ``` * * @param array $spec The spec to build the OptionParser with. * @return ConsoleOptionParser */ public static function buildFromArray($spec) { $parser = new ConsoleOptionParser($spec['command']); if (!empty($spec['arguments'])) { $parser->addArguments($spec['arguments']); } if (!empty($spec['options'])) { $parser->addOptions($spec['options']); } if (!empty($spec['subcommands'])) { $parser->addSubcommands($spec['subcommands']); } if (!empty($spec['description'])) { $parser->description($spec['description']); } if (!empty($spec['epilog'])) { $parser->epilog($spec['epilog']); } return $parser; } /** * Get or set the command name for shell/task. * * @param string $text The text to set, or null if you want to read * @return string|self If reading, the value of the command. If setting $this will be returned. */ public function command($text = null) { if ($text !== null) { $this->_command = Inflector::underscore($text); return $this; } return $this->_command; } /** * Get or set the description text for shell/task. * * @param string|array $text The text to set, or null if you want to read. If an array the * text will be imploded with "\n" * @return string|self If reading, the value of the description. If setting $this will be returned. */ public function description($text = null) { if ($text !== null) { if (is_array($text)) { $text = implode("\n", $text); } $this->_description = $text; return $this; } return $this->_description; } /** * Get or set an epilog to the parser. The epilog is added to the end of * the options and arguments listing when help is generated. * * @param string|array $text Text when setting or null when reading. If an array the text will be imploded with "\n" * @return string|self If reading, the value of the epilog. If setting $this will be returned. */ public function epilog($text = null) { if ($text !== null) { if (is_array($text)) { $text = implode("\n", $text); } $this->_epilog = $text; return $this; } return $this->_epilog; } /** * Add an option to the option parser. Options allow you to define optional or required * parameters for your console application. Options are defined by the parameters they use. * * ### Options * * - `short` - The single letter variant for this option, leave undefined for none. * - `help` - Help text for this option. Used when generating help for the option. * - `default` - The default value for this option. Defaults are added into the parsed params when the * attached option is not provided or has no value. Using default and boolean together will not work. * are added into the parsed parameters when the option is undefined. Defaults to null. * - `boolean` - The option uses no value, its just a boolean switch. Defaults to false. * If an option is defined as boolean, it will always be added to the parsed params. If no present * it will be false, if present it will be true. * - `choices` A list of valid choices for this option. If left empty all values are valid.. * An exception will be raised when parse() encounters an invalid value. * * @param ConsoleInputOption|string $name The long name you want to the value to be parsed out as when options are parsed. * Will also accept an instance of ConsoleInputOption * @param array $options An array of parameters that define the behavior of the option * @return self */ public function addOption($name, $options = array()) { if (is_object($name) && $name instanceof ConsoleInputOption) { $option = $name; $name = $option->name(); } else { $defaults = array( 'name' => $name, 'short' => null, 'help' => '', 'default' => null, 'boolean' => false, 'choices' => array() ); $options += $defaults; $option = new ConsoleInputOption($options); } $this->_options[$name] = $option; if ($option->short() !== null) { $this->_shortOptions[$option->short()] = $name; } return $this; } /** * Add a positional argument to the option parser. * * ### Params * * - `help` The help text to display for this argument. * - `required` Whether this parameter is required. * - `index` The index for the arg, if left undefined the argument will be put * onto the end of the arguments. If you define the same index twice the first * option will be overwritten. * - `choices` A list of valid choices for this argument. If left empty all values are valid.. * An exception will be raised when parse() encounters an invalid value. * * @param ConsoleInputArgument|string $name The name of the argument. Will also accept an instance of ConsoleInputArgument * @param array $params Parameters for the argument, see above. * @return self */ public function addArgument($name, $params = array()) { if (is_object($name) && $name instanceof ConsoleInputArgument) { $arg = $name; $index = count($this->_args); } else { $defaults = array( 'name' => $name, 'help' => '', 'index' => count($this->_args), 'required' => false, 'choices' => array() ); $options = $params + $defaults; $index = $options['index']; unset($options['index']); $arg = new ConsoleInputArgument($options); } $this->_args[$index] = $arg; ksort($this->_args); return $this; } /** * Add multiple arguments at once. Take an array of argument definitions. * The keys are used as the argument names, and the values as params for the argument. * * @param array $args Array of arguments to add. * @see ConsoleOptionParser::addArgument() * @return self */ public function addArguments(array $args) { foreach ($args as $name => $params) { $this->addArgument($name, $params); } return $this; } /** * Add multiple options at once. Takes an array of option definitions. * The keys are used as option names, and the values as params for the option. * * @param array $options Array of options to add. * @see ConsoleOptionParser::addOption() * @return self */ public function addOptions(array $options) { foreach ($options as $name => $params) { $this->addOption($name, $params); } return $this; } /** * Append a subcommand to the subcommand list. * Subcommands are usually methods on your Shell, but can also be used to document Tasks. * * ### Options * * - `help` - Help text for the subcommand. * - `parser` - A ConsoleOptionParser for the subcommand. This allows you to create method * specific option parsers. When help is generated for a subcommand, if a parser is present * it will be used. * * @param ConsoleInputSubcommand|string $name Name of the subcommand. Will also accept an instance of ConsoleInputSubcommand * @param array $options Array of params, see above. * @return self */ public function addSubcommand($name, $options = array()) { if (is_object($name) && $name instanceof ConsoleInputSubcommand) { $command = $name; $name = $command->name(); } else { $defaults = array( 'name' => $name, 'help' => '', 'parser' => null ); $options += $defaults; $command = new ConsoleInputSubcommand($options); } $this->_subcommands[$name] = $command; return $this; } /** * Remove a subcommand from the option parser. * * @param string $name The subcommand name to remove. * @return self */ public function removeSubcommand($name) { unset($this->_subcommands[$name]); return $this; } /** * Add multiple subcommands at once. * * @param array $commands Array of subcommands. * @return self */ public function addSubcommands(array $commands) { foreach ($commands as $name => $params) { $this->addSubcommand($name, $params); } return $this; } /** * Gets the arguments defined in the parser. * * @return array Array of argument descriptions */ public function arguments() { return $this->_args; } /** * Get the defined options in the parser. * * @return array */ public function options() { return $this->_options; } /** * Get the array of defined subcommands * * @return array */ public function subcommands() { return $this->_subcommands; } /** * Parse the argv array into a set of params and args. If $command is not null * and $command is equal to a subcommand that has a parser, that parser will be used * to parse the $argv * * @param array $argv Array of args (argv) to parse. * @param string $command The subcommand to use. If this parameter is a subcommand, that has a parser, * That parser will be used to parse $argv instead. * @return array array($params, $args) * @throws ConsoleException When an invalid parameter is encountered. */ public function parse($argv, $command = null) { if (isset($this->_subcommands[$command]) && $this->_subcommands[$command]->parser()) { return $this->_subcommands[$command]->parser()->parse($argv); } $params = $args = array(); $this->_tokens = $argv; while (($token = array_shift($this->_tokens)) !== null) { if (substr($token, 0, 2) === '--') { $params = $this->_parseLongOption($token, $params); } elseif (substr($token, 0, 1) === '-') { $params = $this->_parseShortOption($token, $params); } else { $args = $this->_parseArg($token, $args); } } foreach ($this->_args as $i => $arg) { if ($arg->isRequired() && !isset($args[$i]) && empty($params['help'])) { throw new ConsoleException( __d('cake_console', 'Missing required arguments. %s is required.', $arg->name()) ); } } foreach ($this->_options as $option) { $name = $option->name(); $isBoolean = $option->isBoolean(); $default = $option->defaultValue(); if ($default !== null && !isset($params[$name]) && !$isBoolean) { $params[$name] = $default; } if ($isBoolean && !isset($params[$name])) { $params[$name] = false; } } return array($params, $args); } /** * Gets formatted help for this parser object. * Generates help text based on the description, options, arguments, subcommands and epilog * in the parser. * * @param string $subcommand If present and a valid subcommand that has a linked parser. * That subcommands help will be shown instead. * @param string $format Define the output format, can be text or xml * @param int $width The width to format user content to. Defaults to 72 * @return string Generated help. */ public function help($subcommand = null, $format = 'text', $width = 72) { if (isset($this->_subcommands[$subcommand]) && $this->_subcommands[$subcommand]->parser() instanceof self ) { $subparser = $this->_subcommands[$subcommand]->parser(); $subparser->command($this->command() . ' ' . $subparser->command()); return $subparser->help(null, $format, $width); } $formatter = new HelpFormatter($this); if ($format === 'text' || $format === true) { return $formatter->text($width); } elseif ($format === 'xml') { return $formatter->xml(); } } /** * Parse the value for a long option out of $this->_tokens. Will handle * options with an `=` in them. * * @param string $option The option to parse. * @param array $params The params to append the parsed value into * @return array Params with $option added in. */ protected function _parseLongOption($option, $params) { $name = substr($option, 2); if (strpos($name, '=') !== false) { list($name, $value) = explode('=', $name, 2); array_unshift($this->_tokens, $value); } return $this->_parseOption($name, $params); } /** * Parse the value for a short option out of $this->_tokens * If the $option is a combination of multiple shortcuts like -otf * they will be shifted onto the token stack and parsed individually. * * @param string $option The option to parse. * @param array $params The params to append the parsed value into * @return array Params with $option added in. * @throws ConsoleException When unknown short options are encountered. */ protected function _parseShortOption($option, $params) { $key = substr($option, 1); if (strlen($key) > 1) { $flags = str_split($key); $key = $flags[0]; for ($i = 1, $len = count($flags); $i < $len; $i++) { array_unshift($this->_tokens, '-' . $flags[$i]); } } if (!isset($this->_shortOptions[$key])) { throw new ConsoleException(__d('cake_console', 'Unknown short option `%s`', $key)); } $name = $this->_shortOptions[$key]; return $this->_parseOption($name, $params); } /** * Parse an option by its name index. * * @param string $name The name to parse. * @param array $params The params to append the parsed value into * @return array Params with $option added in. * @throws ConsoleException */ protected function _parseOption($name, $params) { if (!isset($this->_options[$name])) { throw new ConsoleException(__d('cake_console', 'Unknown option `%s`', $name)); } $option = $this->_options[$name]; $isBoolean = $option->isBoolean(); $nextValue = $this->_nextToken(); $emptyNextValue = (empty($nextValue) && $nextValue !== '0'); if (!$isBoolean && !$emptyNextValue && !$this->_optionExists($nextValue)) { array_shift($this->_tokens); $value = $nextValue; } elseif ($isBoolean) { $value = true; } else { $value = $option->defaultValue(); } if ($option->validChoice($value)) { $params[$name] = $value; return $params; } return array(); } /** * Check to see if $name has an option (short/long) defined for it. * * @param string $name The name of the option. * @return bool */ protected function _optionExists($name) { if (substr($name, 0, 2) === '--') { return isset($this->_options[substr($name, 2)]); } if ($name{0} === '-' && $name{1} !== '-') { return isset($this->_shortOptions[$name{1}]); } return false; } /** * Parse an argument, and ensure that the argument doesn't exceed the number of arguments * and that the argument is a valid choice. * * @param string $argument The argument to append * @param array $args The array of parsed args to append to. * @return array Args * @throws ConsoleException */ protected function _parseArg($argument, $args) { if (empty($this->_args)) { $args[] = $argument; return $args; } $next = count($args); if (!isset($this->_args[$next])) { throw new ConsoleException(__d('cake_console', 'Too many arguments.')); } if ($this->_args[$next]->validChoice($argument)) { $args[] = $argument; return $args; } } /** * Find the next token in the argv set. * * @return string next token or '' */ protected function _nextToken() { return isset($this->_tokens[0]) ? $this->_tokens[0] : ''; } } cakephp-2.8.0/lib/Cake/Console/ConsoleOutput.php000066400000000000000000000217201265552240500215130ustar00rootroot00000000000000out('Overwrite: foo.php was overwritten.');` * * This would create orange 'Overwrite:' text, while the rest of the text would remain the normal color. * See ConsoleOutput::styles() to learn more about defining your own styles. Nested styles are not supported * at this time. * * @package Cake.Console */ class ConsoleOutput { /** * Raw output constant - no modification of output text. * * @var int */ const RAW = 0; /** * Plain output - tags will be stripped. * * @var int */ const PLAIN = 1; /** * Color output - Convert known tags in to ANSI color escape codes. * * @var int */ const COLOR = 2; /** * Constant for a newline. * * @var string */ const LF = PHP_EOL; /** * File handle for output. * * @var resource */ protected $_output; /** * The number of bytes last written to the output stream * used when overwriting the previous message. * * @var int */ protected $_lastWritten = 0; /** * The current output type. Manipulated with ConsoleOutput::outputAs(); * * @var int */ protected $_outputAs = self::COLOR; /** * text colors used in colored output. * * @var array */ protected static $_foregroundColors = array( 'black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37 ); /** * background colors used in colored output. * * @var array */ protected static $_backgroundColors = array( 'black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47 ); /** * formatting options for colored output * * @var string */ protected static $_options = array( 'bold' => 1, 'underline' => 4, 'blink' => 5, 'reverse' => 7, ); /** * Styles that are available as tags in console output. * You can modify these styles with ConsoleOutput::styles() * * @var array */ protected static $_styles = array( 'emergency' => array('text' => 'red', 'underline' => true), 'alert' => array('text' => 'red', 'underline' => true), 'critical' => array('text' => 'red', 'underline' => true), 'error' => array('text' => 'red', 'underline' => true), 'warning' => array('text' => 'yellow'), 'info' => array('text' => 'cyan'), 'debug' => array('text' => 'yellow'), 'success' => array('text' => 'green'), 'comment' => array('text' => 'blue'), 'question' => array('text' => 'magenta'), 'notice' => array('text' => 'cyan') ); /** * Construct the output object. * * Checks for a pretty console environment. Ansicon and ConEmu allows * pretty consoles on Windows, and is supported. * * @param string $stream The identifier of the stream to write output to. */ public function __construct($stream = 'php://stdout') { $this->_output = fopen($stream, 'w'); if ((DS === '\\' && !(bool)env('ANSICON') && env('ConEmuANSI') !== 'ON') || $stream === 'php://output' || (function_exists('posix_isatty') && !posix_isatty($this->_output)) ) { $this->_outputAs = static::PLAIN; } } /** * Outputs a single or multiple messages to stdout. If no parameters * are passed, outputs just a newline. * * @param string|array $message A string or an array of strings to output * @param int $newlines Number of newlines to append * @return int Returns the number of bytes returned from writing to stdout. */ public function write($message, $newlines = 1) { if (is_array($message)) { $message = implode(static::LF, $message); } return $this->_write($this->styleText($message . str_repeat(static::LF, $newlines))); } /** * Overwrite some already output text. * * Useful for building progress bars, or when you want to replace * text already output to the screen with new text. * * **Warning** You cannot overwrite text that contains newlines. * * @param array|string $message The message to output. * @param int $newlines Number of newlines to append. * @param int|null $size The number of bytes to overwrite. Defaults to the * length of the last message output. * @return void */ public function overwrite($message, $newlines = 1, $size = null) { $size = $size ?: $this->_lastWritten; // Output backspaces. $this->write(str_repeat("\x08", $size), 0); $newBytes = $this->write($message, 0); // Fill any remaining bytes with spaces. $fill = $size - $newBytes; if ($fill > 0) { $this->write(str_repeat(' ', $fill), 0); } if ($newlines) { $this->write("", $newlines); } } /** * Apply styling to text. * * @param string $text Text with styling tags. * @return string String with color codes added. */ public function styleText($text) { if ($this->_outputAs == static::RAW) { return $text; } if ($this->_outputAs == static::PLAIN) { $tags = implode('|', array_keys(static::$_styles)); return preg_replace('##', '', $text); } return preg_replace_callback( '/<(?P[a-z0-9-_]+)>(?P.*?)<\/(\1)>/ims', array($this, '_replaceTags'), $text ); } /** * Replace tags with color codes. * * @param array $matches An array of matches to replace. * @return string */ protected function _replaceTags($matches) { $style = $this->styles($matches['tag']); if (empty($style)) { return '<' . $matches['tag'] . '>' . $matches['text'] . ''; } $styleInfo = array(); if (!empty($style['text']) && isset(static::$_foregroundColors[$style['text']])) { $styleInfo[] = static::$_foregroundColors[$style['text']]; } if (!empty($style['background']) && isset(static::$_backgroundColors[$style['background']])) { $styleInfo[] = static::$_backgroundColors[$style['background']]; } unset($style['text'], $style['background']); foreach ($style as $option => $value) { if ($value) { $styleInfo[] = static::$_options[$option]; } } return "\033[" . implode($styleInfo, ';') . 'm' . $matches['text'] . "\033[0m"; } /** * Writes a message to the output stream. * * @param string $message Message to write. * @return bool success */ protected function _write($message) { $this->_lastWritten = fwrite($this->_output, $message); return $this->_lastWritten; } /** * Get the current styles offered, or append new ones in. * * ### Get a style definition * * `$this->output->styles('error');` * * ### Get all the style definitions * * `$this->output->styles();` * * ### Create or modify an existing style * * `$this->output->styles('annoy', array('text' => 'purple', 'background' => 'yellow', 'blink' => true));` * * ### Remove a style * * `$this->output->styles('annoy', false);` * * @param string $style The style to get or create. * @param array $definition The array definition of the style to change or create a style * or false to remove a style. * @return mixed If you are getting styles, the style or null will be returned. If you are creating/modifying * styles true will be returned. */ public function styles($style = null, $definition = null) { if ($style === null && $definition === null) { return static::$_styles; } if (is_string($style) && $definition === null) { return isset(static::$_styles[$style]) ? static::$_styles[$style] : null; } if ($definition === false) { unset(static::$_styles[$style]); return true; } static::$_styles[$style] = $definition; return true; } /** * Get/Set the output type to use. The output type how formatting tags are treated. * * @param int $type The output type to use. Should be one of the class constants. * @return mixed Either null or the value if getting. */ public function outputAs($type = null) { if ($type === null) { return $this->_outputAs; } $this->_outputAs = $type; } /** * Clean up and close handles */ public function __destruct() { if (is_resource($this->_output)) { fclose($this->_output); } } } cakephp-2.8.0/lib/Cake/Console/HelpFormatter.php000066400000000000000000000131121265552240500214400ustar00rootroot00000000000000help($command, 'xml'); is usually * how you would access help. Or via the `--help=xml` option on the command line. * * Xml output is useful for integration with other tools like IDE's or other build tools. * * @package Cake.Console * @since CakePHP(tm) v 2.0 */ class HelpFormatter { /** * The maximum number of arguments shown when generating usage. * * @var int */ protected $_maxArgs = 6; /** * The maximum number of options shown when generating usage. * * @var int */ protected $_maxOptions = 6; /** * Build the help formatter for an OptionParser * * @param ConsoleOptionParser $parser The option parser help is being generated for. */ public function __construct(ConsoleOptionParser $parser) { $this->_parser = $parser; } /** * Get the help as formatted text suitable for output on the command line. * * @param int $width The width of the help output. * @return string */ public function text($width = 72) { $parser = $this->_parser; $out = array(); $description = $parser->description(); if (!empty($description)) { $out[] = CakeText::wrap($description, $width); $out[] = ''; } $out[] = __d('cake_console', 'Usage:'); $out[] = $this->_generateUsage(); $out[] = ''; $subcommands = $parser->subcommands(); if (!empty($subcommands)) { $out[] = __d('cake_console', 'Subcommands:'); $out[] = ''; $max = $this->_getMaxLength($subcommands) + 2; foreach ($subcommands as $command) { $out[] = CakeText::wrap($command->help($max), array( 'width' => $width, 'indent' => str_repeat(' ', $max), 'indentAt' => 1 )); } $out[] = ''; $out[] = __d('cake_console', 'To see help on a subcommand use `cake %s [subcommand] --help`', $parser->command()); $out[] = ''; } $options = $parser->options(); if (!empty($options)) { $max = $this->_getMaxLength($options) + 8; $out[] = __d('cake_console', 'Options:'); $out[] = ''; foreach ($options as $option) { $out[] = CakeText::wrap($option->help($max), array( 'width' => $width, 'indent' => str_repeat(' ', $max), 'indentAt' => 1 )); } $out[] = ''; } $arguments = $parser->arguments(); if (!empty($arguments)) { $max = $this->_getMaxLength($arguments) + 2; $out[] = __d('cake_console', 'Arguments:'); $out[] = ''; foreach ($arguments as $argument) { $out[] = CakeText::wrap($argument->help($max), array( 'width' => $width, 'indent' => str_repeat(' ', $max), 'indentAt' => 1 )); } $out[] = ''; } $epilog = $parser->epilog(); if (!empty($epilog)) { $out[] = CakeText::wrap($epilog, $width); $out[] = ''; } return implode("\n", $out); } /** * Generate the usage for a shell based on its arguments and options. * Usage strings favor short options over the long ones. and optional args will * be indicated with [] * * @return string */ protected function _generateUsage() { $usage = array('cake ' . $this->_parser->command()); $subcommands = $this->_parser->subcommands(); if (!empty($subcommands)) { $usage[] = '[subcommand]'; } $options = array(); foreach ($this->_parser->options() as $option) { $options[] = $option->usage(); } if (count($options) > $this->_maxOptions) { $options = array('[options]'); } $usage = array_merge($usage, $options); $args = array(); foreach ($this->_parser->arguments() as $argument) { $args[] = $argument->usage(); } if (count($args) > $this->_maxArgs) { $args = array('[arguments]'); } $usage = array_merge($usage, $args); return implode(' ', $usage); } /** * Iterate over a collection and find the longest named thing. * * @param array $collection The collection to find a max length of. * @return int */ protected function _getMaxLength($collection) { $max = 0; foreach ($collection as $item) { $max = (strlen($item->name()) > $max) ? strlen($item->name()) : $max; } return $max; } /** * Get the help as an xml string. * * @param bool $string Return the SimpleXml object or a string. Defaults to true. * @return string|SimpleXmlElement See $string */ public function xml($string = true) { $parser = $this->_parser; $xml = new SimpleXmlElement(''); $xml->addChild('command', $parser->command()); $xml->addChild('description', $parser->description()); $xml->addChild('epilog', $parser->epilog()); $subcommands = $xml->addChild('subcommands'); foreach ($parser->subcommands() as $command) { $command->xml($subcommands); } $options = $xml->addChild('options'); foreach ($parser->options() as $option) { $option->xml($options); } $arguments = $xml->addChild('arguments'); foreach ($parser->arguments() as $argument) { $argument->xml($arguments); } return $string ? $xml->asXml() : $xml; } } cakephp-2.8.0/lib/Cake/Console/Helper/000077500000000000000000000000001265552240500173745ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Helper/BaseShellHelper.php000066400000000000000000000036501265552240500231130ustar00rootroot00000000000000_consoleOutput = $consoleOutput; $this->config($config); } /** * Initialize config & store config values * * @param null $config Config values to set * @return array|void */ public function config($config = null) { if ($config === null) { return $this->_config; } if (!$this->_configInitialized) { $this->_config = array_merge($this->_defaultConfig, $config); $this->_configInitialized = true; } else { $this->_config = array_merge($this->_config, $config); } } /** * This method should output content using `$this->_consoleOutput`. * * @param array $args The arguments for the helper. * @return void */ abstract public function output($args); }cakephp-2.8.0/lib/Cake/Console/Helper/ProgressShellHelper.php000066400000000000000000000062121265552240500240420ustar00rootroot00000000000000 null); if (isset($args[0])) { $args['callback'] = $args[0]; } if (!$args['callback'] || !is_callable($args['callback'])) { throw new RuntimeException('Callback option must be a callable.'); } $this->init($args); $callback = $args['callback']; while ($this->_progress < $this->_total) { $callback($this); $this->draw(); } $this->_consoleOutput->write(''); } /** * Initialize the progress bar for use. * * - `total` The total number of items in the progress bar. Defaults * to 100. * - `width` The width of the progress bar. Defaults to 80. * * @param array $args The initialization data. * @return void */ public function init(array $args = array()) { $args += array('total' => 100, 'width' => 80); $this->_progress = 0; $this->_width = $args['width']; $this->_total = $args['total']; } /** * Increment the progress bar. * * @param int $num The amount of progress to advance by. * @return void */ public function increment($num = 1) { $this->_progress = min(max(0, $this->_progress + $num), $this->_total); } /** * Render the progress bar based on the current state. * * @return void */ public function draw() { $numberLen = strlen(' 100%'); $complete = round($this->_progress / $this->_total, 2); $barLen = ($this->_width - $numberLen) * ($this->_progress / $this->_total); $bar = ''; if ($barLen > 1) { $bar = str_repeat('=', $barLen - 1) . '>'; } $pad = ceil($this->_width - $numberLen - $barLen); if ($pad > 0) { $bar .= str_repeat(' ', $pad); } $percent = ($complete * 100) . '%'; $bar .= str_pad($percent, $numberLen, ' ', STR_PAD_LEFT); $this->_consoleOutput->overwrite($bar, 0); } }cakephp-2.8.0/lib/Cake/Console/Helper/TableShellHelper.php000066400000000000000000000061671265552240500232760ustar00rootroot00000000000000 true, 'rowSeparator' => false, 'headerStyle' => 'info', ); /** * Calculate the column widths * * @param array $rows The rows on which the columns width will be calculated on. * @return array */ protected function _calculateWidths($rows) { $widths = array(); foreach ($rows as $line) { for ($i = 0, $len = count($line); $i < $len; $i++) { $columnLength = mb_strlen($line[$i]); if ($columnLength > (isset($widths[$i]) ? $widths[$i] : 0)) { $widths[$i] = $columnLength; } } } return $widths; } /** * Output a row separator. * * @param array $widths The widths of each column to output. * @return void */ protected function _rowSeparator($widths) { $out = ''; foreach ($widths as $column) { $out .= '+' . str_repeat('-', $column + 2); } $out .= '+'; $this->_consoleOutput->write($out); } /** * Output a row. * * @param array $row The row to output. * @param array $widths The widths of each column to output. * @param array $options Options to be passed. * @return void */ protected function _render($row, $widths, $options = array()) { $out = ''; foreach ($row as $i => $column) { $pad = $widths[$i] - mb_strlen($column); if (!empty($options['style'])) { $column = $this->_addStyle($column, $options['style']); } $out .= '| ' . $column . str_repeat(' ', $pad) . ' '; } $out .= '|'; $this->_consoleOutput->write($out); } /** * Output a table. * * @param array $rows The data to render out. * @return void */ public function output($rows) { $config = $this->config(); $widths = $this->_calculateWidths($rows); $this->_rowSeparator($widths); if ($config['headers'] === true) { $this->_render(array_shift($rows), $widths, array('style' => $config['headerStyle'])); $this->_rowSeparator($widths); } foreach ($rows as $line) { $this->_render($line, $widths); if ($config['rowSeparator'] === true) { $this->_rowSeparator($widths); } } if ($config['rowSeparator'] !== true) { $this->_rowSeparator($widths); } } /** * Add style tags * * @param string $text The text to be surrounded * @param string $style The style to be applied * @return string */ protected function _addStyle($text, $style) { return '<' . $style . '>' . $text . ''; } }cakephp-2.8.0/lib/Cake/Console/Shell.php000066400000000000000000000645401265552240500177460ustar00rootroot00000000000000name) { $this->name = Inflector::camelize(str_replace(array('Shell', 'Task'), '', get_class($this))); } $this->Tasks = new TaskCollection($this); $this->stdout = $stdout ? $stdout : new ConsoleOutput('php://stdout'); $this->stderr = $stderr ? $stderr : new ConsoleOutput('php://stderr'); $this->stdin = $stdin ? $stdin : new ConsoleInput('php://stdin'); $this->_useLogger(); $parent = get_parent_class($this); if ($this->tasks !== null && $this->tasks !== false) { $this->_mergeVars(array('tasks'), $parent, true); } if (!empty($this->uses)) { $this->_mergeVars(array('uses'), $parent, false); } } /** * Initializes the Shell * acts as constructor for subclasses * allows configuration of tasks prior to shell execution * * @return void * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::initialize */ public function initialize() { $this->_loadModels(); $this->loadTasks(); } /** * Starts up the Shell and displays the welcome message. * Allows for checking and configuring prior to command or main execution * * Override this method if you want to remove the welcome information, * or otherwise modify the pre-command flow. * * @return void * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::startup */ public function startup() { $this->_welcome(); } /** * Displays a header for the shell * * @return void */ protected function _welcome() { $this->out(); $this->out(__d('cake_console', 'Welcome to CakePHP %s Console', 'v' . Configure::version())); $this->hr(); $this->out(__d('cake_console', 'App : %s', APP_DIR)); $this->out(__d('cake_console', 'Path: %s', APP)); $this->hr(); } /** * If $uses is an array load each of the models in the array * * @return bool */ protected function _loadModels() { if (is_array($this->uses)) { list(, $this->modelClass) = pluginSplit(current($this->uses)); foreach ($this->uses as $modelClass) { $this->loadModel($modelClass); } } return true; } /** * Lazy loads models using the loadModel() method if declared in $uses * * @param string $name The name of the model to look for. * @return void */ public function __isset($name) { if (is_array($this->uses)) { foreach ($this->uses as $modelClass) { list(, $class) = pluginSplit($modelClass); if ($name === $class) { return $this->loadModel($modelClass); } } } } /** * Loads and instantiates models required by this shell. * * @param string $modelClass Name of model class to load * @param mixed $id Initial ID the instanced model class should have * @return mixed true when single model found and instance created, error returned if model not found. * @throws MissingModelException if the model class cannot be found. */ public function loadModel($modelClass = null, $id = null) { if ($modelClass === null) { $modelClass = $this->modelClass; } $this->uses = ($this->uses) ? (array)$this->uses : array(); if (!in_array($modelClass, $this->uses)) { $this->uses[] = $modelClass; } list($plugin, $modelClass) = pluginSplit($modelClass, true); if (!isset($this->modelClass)) { $this->modelClass = $modelClass; } $this->{$modelClass} = ClassRegistry::init(array( 'class' => $plugin . $modelClass, 'alias' => $modelClass, 'id' => $id )); if (!$this->{$modelClass}) { throw new MissingModelException($modelClass); } return true; } /** * Loads tasks defined in public $tasks * * @return bool */ public function loadTasks() { if ($this->tasks === true || empty($this->tasks) || empty($this->Tasks)) { return true; } $this->_taskMap = TaskCollection::normalizeObjectArray((array)$this->tasks); $this->taskNames = array_merge($this->taskNames, array_keys($this->_taskMap)); return true; } /** * Check to see if this shell has a task with the provided name. * * @param string $task The task name to check. * @return bool Success * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::hasTask */ public function hasTask($task) { return isset($this->_taskMap[Inflector::camelize($task)]); } /** * Check to see if this shell has a callable method by the given name. * * @param string $name The method name to check. * @return bool * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::hasMethod */ public function hasMethod($name) { try { $method = new ReflectionMethod($this, $name); if (!$method->isPublic() || substr($name, 0, 1) === '_') { return false; } if ($method->getDeclaringClass()->name === 'Shell') { return false; } return true; } catch (ReflectionException $e) { return false; } } /** * Dispatch a command to another Shell. Similar to Object::requestAction() * but intended for running shells from other shells. * * ### Usage: * * With a string command: * * `return $this->dispatchShell('schema create DbAcl');` * * Avoid using this form if you have string arguments, with spaces in them. * The dispatched will be invoked incorrectly. Only use this form for simple * command dispatching. * * With an array command: * * `return $this->dispatchShell('schema', 'create', 'i18n', '--dry');` * * @return mixed The return of the other shell. * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::dispatchShell */ public function dispatchShell() { $args = func_get_args(); if (is_string($args[0]) && count($args) === 1) { $args = explode(' ', $args[0]); } $Dispatcher = new ShellDispatcher($args, false); return $Dispatcher->dispatch(); } /** * Runs the Shell with the provided argv. * * Delegates calls to Tasks and resolves methods inside the class. Commands are looked * up with the following order: * * - Method on the shell. * - Matching task name. * - `main()` method. * * If a shell implements a `main()` method, all missing method calls will be sent to * `main()` with the original method name in the argv. * * @param string $command The command name to run on this shell. If this argument is empty, * and the shell has a `main()` method, that will be called instead. * @param array $argv Array of arguments to run the shell with. This array should be missing the shell name. * @return void * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::runCommand */ public function runCommand($command, $argv) { $isTask = $this->hasTask($command); $isMethod = $this->hasMethod($command); $isMain = $this->hasMethod('main'); if ($isTask || $isMethod && $command !== 'execute') { array_shift($argv); } $this->OptionParser = $this->getOptionParser(); try { list($this->params, $this->args) = $this->OptionParser->parse($argv, $command); } catch (ConsoleException $e) { $this->out($this->OptionParser->help($command)); return false; } if (!empty($this->params['quiet'])) { $this->_useLogger(false); } if (!empty($this->params['plugin'])) { CakePlugin::load($this->params['plugin']); } $this->command = $command; if (!empty($this->params['help'])) { return $this->_displayHelp($command); } if (($isTask || $isMethod || $isMain) && $command !== 'execute') { $this->startup(); } if ($isTask) { $command = Inflector::camelize($command); return $this->{$command}->runCommand('execute', $argv); } if ($isMethod) { return $this->{$command}(); } if ($isMain) { return $this->main(); } $this->out($this->OptionParser->help($command)); return false; } /** * Display the help in the correct format * * @param string $command The command to get help for. * @return void */ protected function _displayHelp($command) { $format = 'text'; if (!empty($this->args[0]) && $this->args[0] === 'xml') { $format = 'xml'; $this->stdout->outputAs(ConsoleOutput::RAW); } else { $this->_welcome(); } return $this->out($this->OptionParser->help($command, $format)); } /** * Gets the option parser instance and configures it. * * By overriding this method you can configure the ConsoleOptionParser before returning it. * * @return ConsoleOptionParser * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::getOptionParser */ public function getOptionParser() { $name = ($this->plugin ? $this->plugin . '.' : '') . $this->name; $parser = new ConsoleOptionParser($name); return $parser; } /** * Overload get for lazy building of tasks * * @param string $name The property name to access. * @return Shell Object of Task */ public function __get($name) { if (empty($this->{$name}) && in_array($name, $this->taskNames)) { $properties = $this->_taskMap[$name]; $this->{$name} = $this->Tasks->load($properties['class'], $properties['settings']); $this->{$name}->args =& $this->args; $this->{$name}->params =& $this->params; $this->{$name}->initialize(); $this->{$name}->loadTasks(); } return $this->{$name}; } /** * Safely access the values in $this->params. * * @param string $name The name of the parameter to get. * @return string|bool|null Value. Will return null if it doesn't exist. */ public function param($name) { if (!isset($this->params[$name])) { return null; } return $this->params[$name]; } /** * Prompts the user for input, and returns it. * * @param string $prompt Prompt text. * @param string|array $options Array or string of options. * @param string $default Default input value. * @return mixed Either the default value, or the user-provided input. * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::in */ public function in($prompt, $options = null, $default = null) { if (!$this->interactive) { return $default; } $originalOptions = $options; $in = $this->_getInput($prompt, $originalOptions, $default); if ($options && is_string($options)) { if (strpos($options, ',')) { $options = explode(',', $options); } elseif (strpos($options, '/')) { $options = explode('/', $options); } else { $options = array($options); } } if (is_array($options)) { $options = array_merge( array_map('strtolower', $options), array_map('strtoupper', $options), $options ); while ($in === '' || !in_array($in, $options)) { $in = $this->_getInput($prompt, $originalOptions, $default); } } return $in; } /** * Prompts the user for input, and returns it. * * @param string $prompt Prompt text. * @param string|array $options Array or string of options. * @param string $default Default input value. * @return Either the default value, or the user-provided input. */ protected function _getInput($prompt, $options, $default) { if (!is_array($options)) { $printOptions = ''; } else { $printOptions = '(' . implode('/', $options) . ')'; } if ($default === null) { $this->stdout->write('' . $prompt . '' . " $printOptions \n" . '> ', 0); } else { $this->stdout->write('' . $prompt . '' . " $printOptions \n" . "[$default] > ", 0); } $result = $this->stdin->read(); if ($result === false) { $this->_stop(self::CODE_ERROR); return self::CODE_ERROR; } $result = trim($result); if ($default !== null && ($result === '' || $result === null)) { return $default; } return $result; } /** * Wrap a block of text. * Allows you to set the width, and indenting on a block of text. * * ### Options * * - `width` The width to wrap to. Defaults to 72 * - `wordWrap` Only wrap on words breaks (spaces) Defaults to true. * - `indent` Indent the text with the string provided. Defaults to null. * * @param string $text Text the text to format. * @param string|int|array $options Array of options to use, or an integer to wrap the text to. * @return string Wrapped / indented text * @see CakeText::wrap() * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::wrapText */ public function wrapText($text, $options = array()) { return CakeText::wrap($text, $options); } /** * Outputs a single or multiple messages to stdout. If no parameters * are passed outputs just a newline. * * ### Output levels * * There are 3 built-in output level. Shell::QUIET, Shell::NORMAL, Shell::VERBOSE. * The verbose and quiet output levels, map to the `verbose` and `quiet` output switches * present in most shells. Using Shell::QUIET for a message means it will always display. * While using Shell::VERBOSE means it will only display when verbose output is toggled. * * @param string|array $message A string or an array of strings to output * @param int $newlines Number of newlines to append * @param int $level The message's output level, see above. * @return int|bool Returns the number of bytes returned from writing to stdout. * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::out */ public function out($message = null, $newlines = 1, $level = Shell::NORMAL) { $currentLevel = Shell::NORMAL; if (!empty($this->params['verbose'])) { $currentLevel = Shell::VERBOSE; } if (!empty($this->params['quiet'])) { $currentLevel = Shell::QUIET; } if ($level <= $currentLevel) { $this->_lastWritten = $this->stdout->write($message, $newlines); return $this->_lastWritten; } return true; } /** * Overwrite some already output text. * * Useful for building progress bars, or when you want to replace * text already output to the screen with new text. * * **Warning** You cannot overwrite text that contains newlines. * * @param array|string $message The message to output. * @param int $newlines Number of newlines to append. * @param int $size The number of bytes to overwrite. Defaults to the length of the last message output. * @return int|bool Returns the number of bytes returned from writing to stdout. */ public function overwrite($message, $newlines = 1, $size = null) { $size = $size ? $size : $this->_lastWritten; // Output backspaces. $this->out(str_repeat("\x08", $size), 0); $newBytes = $this->out($message, 0); // Fill any remaining bytes with spaces. $fill = $size - $newBytes; if ($fill > 0) { $this->out(str_repeat(' ', $fill), 0); } if ($newlines) { $this->out($this->nl($newlines), 0); } } /** * Outputs a single or multiple error messages to stderr. If no parameters * are passed outputs just a newline. * * @param string|array $message A string or an array of strings to output * @param int $newlines Number of newlines to append * @return void * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::err */ public function err($message = null, $newlines = 1) { $this->stderr->write($message, $newlines); } /** * Returns a single or multiple linefeeds sequences. * * @param int $multiplier Number of times the linefeed sequence should be repeated * @return string * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::nl */ public function nl($multiplier = 1) { return str_repeat(ConsoleOutput::LF, $multiplier); } /** * Outputs a series of minus characters to the standard output, acts as a visual separator. * * @param int $newlines Number of newlines to pre- and append * @param int $width Width of the line, defaults to 63 * @return void * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::hr */ public function hr($newlines = 0, $width = 63) { $this->out(null, $newlines); $this->out(str_repeat('-', $width)); $this->out(null, $newlines); } /** * Displays a formatted error message * and exits the application with status code 1 * * @param string $title Title of the error * @param string $message An optional error message * @return void * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::error */ public function error($title, $message = null) { $this->err(__d('cake_console', 'Error: %s', $title)); if (!empty($message)) { $this->err($message); } $this->_stop(self::CODE_ERROR); return self::CODE_ERROR; } /** * Clear the console * * @return void * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::clear */ public function clear() { if (empty($this->params['noclear'])) { if (DS === '/') { passthru('clear'); } else { passthru('cls'); } } } /** * Creates a file at given path * * @param string $path Where to put the file. * @param string $contents Content to put in the file. * @return bool Success * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::createFile */ public function createFile($path, $contents) { $path = str_replace(DS . DS, DS, $path); $this->out(); if (is_file($path) && empty($this->params['force']) && $this->interactive === true) { $this->out(__d('cake_console', 'File `%s` exists', $path)); $key = $this->in(__d('cake_console', 'Do you want to overwrite?'), array('y', 'n', 'q'), 'n'); if (strtolower($key) === 'q') { $this->out(__d('cake_console', 'Quitting.'), 2); $this->_stop(); return true; } elseif (strtolower($key) !== 'y') { $this->out(__d('cake_console', 'Skip `%s`', $path), 2); return false; } } else { $this->out(__d('cake_console', 'Creating file %s', $path)); } $File = new File($path, true); if ($File->exists() && $File->writable()) { $data = $File->prepare($contents); $File->write($data); $this->out(__d('cake_console', 'Wrote `%s`', $path)); return true; } $this->err(__d('cake_console', 'Could not write to `%s`.', $path), 2); return false; } /** * Load given shell helper class * * @param string $name Name of the helper class. Supports plugin syntax. * @return BaseShellHelper Instance of helper class * @throws RuntimeException If invalid class name is provided */ public function helper($name) { if (isset($this->_helpers[$name])) { return $this->_helpers[$name]; } list($plugin, $helperClassName) = pluginSplit($name, true); $helperClassName = Inflector::camelize($name) . "ShellHelper"; App::uses($helperClassName, $plugin . "Console/Helper"); if (!class_exists($helperClassName)) { throw new RuntimeException("Class " . $helperClassName . " not found"); } $helper = new $helperClassName($this->stdout); $this->_helpers[$name] = $helper; return $helper; } /** * Action to create a Unit Test * * @return bool Success */ protected function _checkUnitTest() { if (class_exists('PHPUnit_Framework_TestCase')) { return true; //@codingStandardsIgnoreStart } elseif (@include 'PHPUnit' . DS . 'Autoload.php') { //@codingStandardsIgnoreEnd return true; } elseif (App::import('Vendor', 'phpunit', array('file' => 'PHPUnit' . DS . 'Autoload.php'))) { return true; } $prompt = __d('cake_console', 'PHPUnit is not installed. Do you want to bake unit test files anyway?'); $unitTest = $this->in($prompt, array('y', 'n'), 'y'); $result = strtolower($unitTest) === 'y' || strtolower($unitTest) === 'yes'; if ($result) { $this->out(); $this->out(__d('cake_console', 'You can download PHPUnit from %s', 'http://phpunit.de')); } return $result; } /** * Makes absolute file path easier to read * * @param string $file Absolute file path * @return string short path * @link http://book.cakephp.org/2.0/en/console-and-shells.html#Shell::shortPath */ public function shortPath($file) { $shortPath = str_replace(ROOT, null, $file); $shortPath = str_replace('..' . DS, '', $shortPath); return str_replace(DS . DS, DS, $shortPath); } /** * Creates the proper controller path for the specified controller class name * * @param string $name Controller class name * @return string Path to controller */ protected function _controllerPath($name) { return Inflector::underscore($name); } /** * Creates the proper controller plural name for the specified controller class name * * @param string $name Controller class name * @return string Controller plural name */ protected function _controllerName($name) { return Inflector::pluralize(Inflector::camelize($name)); } /** * Creates the proper model camelized name (singularized) for the specified name * * @param string $name Name * @return string Camelized and singularized model name */ protected function _modelName($name) { return Inflector::camelize(Inflector::singularize($name)); } /** * Creates the proper underscored model key for associations * * @param string $name Model class name * @return string Singular model key */ protected function _modelKey($name) { return Inflector::underscore($name) . '_id'; } /** * Creates the proper model name from a foreign key * * @param string $key Foreign key * @return string Model name */ protected function _modelNameFromKey($key) { return Inflector::camelize(str_replace('_id', '', $key)); } /** * creates the singular name for use in views. * * @param string $name The plural underscored value. * @return string name */ protected function _singularName($name) { return Inflector::variable(Inflector::singularize($name)); } /** * Creates the plural name for views * * @param string $name Name to use * @return string Plural name for views */ protected function _pluralName($name) { return Inflector::variable(Inflector::pluralize($name)); } /** * Creates the singular human name used in views * * @param string $name Controller name * @return string Singular human name */ protected function _singularHumanName($name) { return Inflector::humanize(Inflector::underscore(Inflector::singularize($name))); } /** * Creates the plural human name used in views * * @param string $name Controller name * @return string Plural human name */ protected function _pluralHumanName($name) { return Inflector::humanize(Inflector::underscore($name)); } /** * Find the correct path for a plugin. Scans $pluginPaths for the plugin you want. * * @param string $pluginName Name of the plugin you want ie. DebugKit * @return string path path to the correct plugin. */ protected function _pluginPath($pluginName) { if (CakePlugin::loaded($pluginName)) { return CakePlugin::path($pluginName); } return current(App::path('plugins')) . $pluginName . DS; } /** * Used to enable or disable logging stream output to stdout and stderr * If you don't wish to see in your stdout or stderr everything that is logged * through CakeLog, call this function with first param as false * * @param bool $enable whether to enable CakeLog output or not * @return void */ protected function _useLogger($enable = true) { if (!$enable) { CakeLog::drop('stdout'); CakeLog::drop('stderr'); return; } CakeLog::config('stdout', array( 'engine' => 'Console', 'types' => array('notice', 'info'), 'stream' => $this->stdout, )); CakeLog::config('stderr', array( 'engine' => 'Console', 'types' => array('emergency', 'alert', 'critical', 'error', 'warning', 'debug'), 'stream' => $this->stderr, )); } } cakephp-2.8.0/lib/Cake/Console/ShellDispatcher.php000066400000000000000000000237611265552240500217550ustar00rootroot00000000000000parseParams($args); if ($bootstrap) { $this->_initConstants(); $this->_initEnvironment(); } } /** * Run the dispatcher * * @param array $argv The argv from PHP * @return void */ public static function run($argv) { $dispatcher = new ShellDispatcher($argv); return $dispatcher->_stop($dispatcher->dispatch() === false ? 1 : 0); } /** * Defines core configuration. * * @return void */ protected function _initConstants() { if (function_exists('ini_set')) { ini_set('html_errors', false); ini_set('implicit_flush', true); ini_set('max_execution_time', 0); } if (!defined('CAKE_CORE_INCLUDE_PATH')) { define('CAKE_CORE_INCLUDE_PATH', dirname(dirname(dirname(__FILE__)))); define('CAKEPHP_SHELL', true); if (!defined('DS')) { define('DS', DIRECTORY_SEPARATOR); } if (!defined('CORE_PATH')) { define('CORE_PATH', CAKE_CORE_INCLUDE_PATH . DS); } } } /** * Defines current working environment. * * @return void * @throws CakeException */ protected function _initEnvironment() { if (!$this->_bootstrap()) { $message = "Unable to load CakePHP core.\nMake sure " . DS . 'lib' . DS . 'Cake exists in ' . CAKE_CORE_INCLUDE_PATH; throw new CakeException($message); } if (!isset($this->args[0]) || !isset($this->params['working'])) { $message = "This file has been loaded incorrectly and cannot continue.\n" . "Please make sure that " . DS . 'lib' . DS . 'Cake' . DS . "Console is in your system path,\n" . "and check the cookbook for the correct usage of this command.\n" . "(http://book.cakephp.org/)"; throw new CakeException($message); } $this->shiftArgs(); } /** * Initializes the environment and loads the CakePHP core. * * @return bool Success. */ protected function _bootstrap() { if (!defined('ROOT')) { define('ROOT', $this->params['root']); } if (!defined('APP_DIR')) { define('APP_DIR', $this->params['app']); } if (!defined('APP')) { define('APP', $this->params['working'] . DS); } if (!defined('WWW_ROOT')) { define('WWW_ROOT', APP . $this->params['webroot'] . DS); } if (!defined('TMP') && !is_dir(APP . 'tmp')) { define('TMP', CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'Console' . DS . 'Templates' . DS . 'skel' . DS . 'tmp' . DS); } $boot = file_exists(ROOT . DS . APP_DIR . DS . 'Config' . DS . 'bootstrap.php'); require CORE_PATH . 'Cake' . DS . 'bootstrap.php'; if (!file_exists(APP . 'Config' . DS . 'core.php')) { include_once CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'Console' . DS . 'Templates' . DS . 'skel' . DS . 'Config' . DS . 'core.php'; App::build(); } $this->setErrorHandlers(); if (!defined('FULL_BASE_URL')) { $url = Configure::read('App.fullBaseUrl'); define('FULL_BASE_URL', $url ? $url : 'http://localhost'); Configure::write('App.fullBaseUrl', FULL_BASE_URL); } return true; } /** * Set the error/exception handlers for the console * based on the `Error.consoleHandler`, and `Exception.consoleHandler` values * if they are set. If they are not set, the default ConsoleErrorHandler will be * used. * * @return void */ public function setErrorHandlers() { App::uses('ConsoleErrorHandler', 'Console'); $error = Configure::read('Error'); $exception = Configure::read('Exception'); $errorHandler = new ConsoleErrorHandler(); if (empty($error['consoleHandler'])) { $error['consoleHandler'] = array($errorHandler, 'handleError'); Configure::write('Error', $error); } if (empty($exception['consoleHandler'])) { $exception['consoleHandler'] = array($errorHandler, 'handleException'); Configure::write('Exception', $exception); } set_exception_handler($exception['consoleHandler']); set_error_handler($error['consoleHandler'], Configure::read('Error.level')); App::uses('Debugger', 'Utility'); Debugger::getInstance()->output('txt'); } /** * Dispatches a CLI request * * @return bool * @throws MissingShellMethodException */ public function dispatch() { $shell = $this->shiftArgs(); if (!$shell) { $this->help(); return false; } if (in_array($shell, array('help', '--help', '-h'))) { $this->help(); return true; } $Shell = $this->_getShell($shell); $command = null; if (isset($this->args[0])) { $command = $this->args[0]; } if ($Shell instanceof Shell) { $Shell->initialize(); return $Shell->runCommand($command, $this->args); } $methods = array_diff(get_class_methods($Shell), get_class_methods('Shell')); $added = in_array($command, $methods); $private = $command[0] === '_' && method_exists($Shell, $command); if (!$private) { if ($added) { $this->shiftArgs(); $Shell->startup(); return $Shell->{$command}(); } if (method_exists($Shell, 'main')) { $Shell->startup(); return $Shell->main(); } } throw new MissingShellMethodException(array('shell' => $shell, 'method' => $command)); } /** * Get shell to use, either plugin shell or application shell * * All paths in the loaded shell paths are searched. * * @param string $shell Optionally the name of a plugin * @return mixed An object * @throws MissingShellException when errors are encountered. */ protected function _getShell($shell) { list($plugin, $shell) = pluginSplit($shell, true); $plugin = Inflector::camelize($plugin); $class = Inflector::camelize($shell) . 'Shell'; App::uses('Shell', 'Console'); App::uses('AppShell', 'Console/Command'); App::uses($class, $plugin . 'Console/Command'); if (!class_exists($class)) { $plugin = Inflector::camelize($shell) . '.'; App::uses($class, $plugin . 'Console/Command'); } if (!class_exists($class)) { throw new MissingShellException(array( 'class' => $class )); } $Shell = new $class(); $Shell->plugin = trim($plugin, '.'); return $Shell; } /** * Parses command line options and extracts the directory paths from $params * * @param array $args Parameters to parse * @return void */ public function parseParams($args) { $this->_parsePaths($args); $defaults = array( 'app' => 'app', 'root' => dirname(dirname(dirname(dirname(__FILE__)))), 'working' => null, 'webroot' => 'webroot' ); $params = array_merge($defaults, array_intersect_key($this->params, $defaults)); $isWin = false; foreach ($defaults as $default => $value) { if (strpos($params[$default], '\\') !== false) { $isWin = true; break; } } $params = str_replace('\\', '/', $params); if (isset($params['working'])) { $params['working'] = trim($params['working']); } if (!empty($params['working']) && (!isset($this->args[0]) || isset($this->args[0]) && $this->args[0][0] !== '.')) { if ($params['working'][0] === '.') { $params['working'] = realpath($params['working']); } if (empty($this->params['app']) && $params['working'] != $params['root']) { $params['root'] = dirname($params['working']); $params['app'] = basename($params['working']); } else { $params['root'] = $params['working']; } } if ($params['app'][0] === '/' || preg_match('/([a-z])(:)/i', $params['app'], $matches)) { $params['root'] = dirname($params['app']); } elseif (strpos($params['app'], '/')) { $params['root'] .= '/' . dirname($params['app']); } $params['app'] = basename($params['app']); $params['working'] = rtrim($params['root'], '/'); if (!$isWin || !preg_match('/^[A-Z]:$/i', $params['app'])) { $params['working'] .= '/' . $params['app']; } if (!empty($matches[0]) || !empty($isWin)) { $params = str_replace('/', '\\', $params); } $this->params = $params + $this->params; } /** * Parses out the paths from from the argv * * @param array $args The argv to parse. * @return void */ protected function _parsePaths($args) { $parsed = array(); $keys = array('-working', '--working', '-app', '--app', '-root', '--root'); $args = (array)$args; foreach ($keys as $key) { while (($index = array_search($key, $args)) !== false) { $keyname = str_replace('-', '', $key); $valueIndex = $index + 1; $parsed[$keyname] = $args[$valueIndex]; array_splice($args, $index, 2); } } $this->args = $args; $this->params = $parsed; } /** * Removes first argument and shifts other arguments up * * @return mixed Null if there are no arguments otherwise the shifted argument */ public function shiftArgs() { return array_shift($this->args); } /** * Shows console help. Performs an internal dispatch to the CommandList Shell * * @return void */ public function help() { $this->args = array_merge(array('command_list'), $this->args); $this->dispatch(); } /** * Stop execution of the current script * * @param int|string $status see http://php.net/exit for values * @return void */ protected function _stop($status = 0) { exit($status); } } cakephp-2.8.0/lib/Cake/Console/TaskCollection.php000066400000000000000000000053171265552240500216120ustar00rootroot00000000000000_Shell = $Shell; } /** * Loads/constructs a task. Will return the instance in the registry if it already exists. * * You can alias your task as an existing task by setting the 'className' key, i.e., * ``` * public $tasks = array( * 'DbConfig' => array( * 'className' => 'Bakeplus.DbConfigure' * ); * ); * ``` * All calls to the `DbConfig` task would use `DbConfigure` found in the `Bakeplus` plugin instead. * * @param string $task Task name to load * @param array $settings Settings for the task. * @return Task A task object, Either the existing loaded task or a new one. * @throws MissingTaskException when the task could not be found */ public function load($task, $settings = array()) { if (is_array($settings) && isset($settings['className'])) { $alias = $task; $task = $settings['className']; } list($plugin, $name) = pluginSplit($task, true); if (!isset($alias)) { $alias = $name; } if (isset($this->_loaded[$alias])) { return $this->_loaded[$alias]; } $taskClass = $name . 'Task'; App::uses($taskClass, $plugin . 'Console/Command/Task'); $exists = class_exists($taskClass); if (!$exists) { throw new MissingTaskException(array( 'class' => $taskClass, 'plugin' => substr($plugin, 0, -1) )); } $this->_loaded[$alias] = new $taskClass( $this->_Shell->stdout, $this->_Shell->stderr, $this->_Shell->stdin ); return $this->_loaded[$alias]; } } cakephp-2.8.0/lib/Cake/Console/Templates/000077500000000000000000000000001265552240500201135ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/default/000077500000000000000000000000001265552240500215375ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/default/actions/000077500000000000000000000000001265552240500231775ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/default/actions/controller_actions.ctp000066400000000000000000000133421265552240500276150ustar00rootroot00000000000000 /** * index method * * @return void */ public function index() { $this->->recursive = 0; $this->set('', $this->Paginator->paginate()); } /** * view method * * @throws NotFoundException * @param string $id * @return void */ public function view($id = null) { if (!$this->->exists($id)) { throw new NotFoundException(__('Invalid ')); } $options = array('conditions' => array('.' . $this->->primaryKey => $id)); $this->set('', $this->->find('first', $options)); } /** * add method * * @return void */ public function add() { if ($this->request->is('post')) { $this->->create(); if ($this->->save($this->request->data)) { $this->Flash->success(__('The has been saved.')); return $this->redirect(array('action' => 'index')); } else { $this->Flash->error(__('The could not be saved. Please, try again.')); return $this->flash(__('The has been saved.'), array('action' => 'index')); } } {$assoc} as $associationName => $relation): if (!empty($associationName)): $otherModelName = $this->_modelName($associationName); $otherPluralName = $this->_pluralName($associationName); echo "\t\t\${$otherPluralName} = \$this->{$currentModelName}->{$otherModelName}->find('list');\n"; $compact[] = "'{$otherPluralName}'"; endif; endforeach; endforeach; if (!empty($compact)): echo "\t\t\$this->set(compact(".join(', ', $compact)."));\n"; endif; ?> } /** * edit method * * @throws NotFoundException * @param string $id * @return void */ public function edit($id = null) { if (!$this->->exists($id)) { throw new NotFoundException(__('Invalid ')); } if ($this->request->is(array('post', 'put'))) { if ($this->->save($this->request->data)) { $this->Flash->success(__('The has been saved.')); return $this->redirect(array('action' => 'index')); } else { $this->Flash->error(__('The could not be saved. Please, try again.')); return $this->flash(__('The has been saved.'), array('action' => 'index')); } } else { $options = array('conditions' => array('.' . $this->->primaryKey => $id)); $this->request->data = $this->->find('first', $options); } {$assoc} as $associationName => $relation): if (!empty($associationName)): $otherModelName = $this->_modelName($associationName); $otherPluralName = $this->_pluralName($associationName); echo "\t\t\${$otherPluralName} = \$this->{$currentModelName}->{$otherModelName}->find('list');\n"; $compact[] = "'{$otherPluralName}'"; endif; endforeach; endforeach; if (!empty($compact)): echo "\t\t\$this->set(compact(".join(', ', $compact)."));\n"; endif; ?> } /** * delete method * * @throws NotFoundException * @param string $id * @return void */ public function delete($id = null) { $this->->id = $id; if (!$this->->exists()) { throw new NotFoundException(__('Invalid ')); } $this->request->allowMethod('post', 'delete'); if ($this->->delete()) { $this->Flash->success(__('The has been deleted.')); } else { $this->Flash->error(__('The could not be deleted. Please, try again.')); } return $this->redirect(array('action' => 'index')); return $this->flash(__('The has been deleted.'), array('action' => 'index')); } else { return $this->flash(__('The could not be deleted. Please, try again.'), array('action' => 'index')); } } cakephp-2.8.0/lib/Cake/Console/Templates/default/classes/000077500000000000000000000000001265552240500231745ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/default/classes/controller.ctp000066400000000000000000000042401265552240500260670ustar00rootroot00000000000000 /** * Controller */ class Controller extends AppController { /** * Scaffold * * @var mixed */ public $scaffold; } cakephp-2.8.0/lib/Cake/Console/Templates/default/classes/fixture.ctp000066400000000000000000000025041265552240500253730ustar00rootroot00000000000000 /** * Fixture */ class Fixture extends CakeTestFixture { /** * Table name * * @var string */ public $table = ''; /** * Import * * @var array */ public $import = ; /** * Fields * * @var array */ public $fields = ; /** * Records * * @var array */ public $records = ; } cakephp-2.8.0/lib/Cake/Console/Templates/default/classes/model.ctp000066400000000000000000000131671265552240500250140ustar00rootroot00000000000000 /** * Model * */ class extends AppModel { /** * Use database config * * @var string */ public $useDbConfig = ''; /** * Primary key field * * @var string */ public $primaryKey = ''; /** * Display field * * @var string */ public $displayField = ''; /** * Behaviors * * @var array */ public $actsAs = array(); $validations): echo "\t\t'$field' => array(\n"; foreach ($validations as $key => $validator): echo "\t\t\t'$key' => array(\n"; echo "\t\t\t\t'rule' => array('$validator'),\n"; echo "\t\t\t\t//'message' => 'Your custom message here',\n"; echo "\t\t\t\t//'allowEmpty' => false,\n"; echo "\t\t\t\t//'required' => false,\n"; echo "\t\t\t\t//'last' => false, // Stop validation after this rule\n"; echo "\t\t\t\t//'on' => 'create', // Limit validation to 'create' or 'update' operations\n"; echo "\t\t\t),\n"; endforeach; echo "\t\t),\n"; endforeach; echo "\t);\n"; endif; foreach ($associations as $assoc): if (!empty($assoc)): ?> // The Associations below have been created with all possible keys, those that are not needed can be removed $relation): $out = "\n\t\t'{$relation['alias']}' => array(\n"; $out .= "\t\t\t'className' => '{$relation['className']}',\n"; $out .= "\t\t\t'foreignKey' => '{$relation['foreignKey']}',\n"; $out .= "\t\t\t'conditions' => '',\n"; $out .= "\t\t\t'fields' => '',\n"; $out .= "\t\t\t'order' => ''\n"; $out .= "\t\t)"; if ($i + 1 < $typeCount) { $out .= ","; } echo $out; endforeach; echo "\n\t);\n"; endif; endforeach; if (!empty($associations['hasMany'])): $belongsToCount = count($associations['hasMany']); echo "\n/**\n * hasMany associations\n *\n * @var array\n */"; echo "\n\tpublic \$hasMany = array("; foreach ($associations['hasMany'] as $i => $relation): $out = "\n\t\t'{$relation['alias']}' => array(\n"; $out .= "\t\t\t'className' => '{$relation['className']}',\n"; $out .= "\t\t\t'foreignKey' => '{$relation['foreignKey']}',\n"; $out .= "\t\t\t'dependent' => false,\n"; $out .= "\t\t\t'conditions' => '',\n"; $out .= "\t\t\t'fields' => '',\n"; $out .= "\t\t\t'order' => '',\n"; $out .= "\t\t\t'limit' => '',\n"; $out .= "\t\t\t'offset' => '',\n"; $out .= "\t\t\t'exclusive' => '',\n"; $out .= "\t\t\t'finderQuery' => '',\n"; $out .= "\t\t\t'counterQuery' => ''\n"; $out .= "\t\t)"; if ($i + 1 < $belongsToCount) { $out .= ","; } echo $out; endforeach; echo "\n\t);\n\n"; endif; if (!empty($associations['hasAndBelongsToMany'])): $habtmCount = count($associations['hasAndBelongsToMany']); echo "\n/**\n * hasAndBelongsToMany associations\n *\n * @var array\n */"; echo "\n\tpublic \$hasAndBelongsToMany = array("; foreach ($associations['hasAndBelongsToMany'] as $i => $relation): $out = "\n\t\t'{$relation['alias']}' => array(\n"; $out .= "\t\t\t'className' => '{$relation['className']}',\n"; $out .= "\t\t\t'joinTable' => '{$relation['joinTable']}',\n"; $out .= "\t\t\t'foreignKey' => '{$relation['foreignKey']}',\n"; $out .= "\t\t\t'associationForeignKey' => '{$relation['associationForeignKey']}',\n"; $out .= "\t\t\t'unique' => 'keepExisting',\n"; $out .= "\t\t\t'conditions' => '',\n"; $out .= "\t\t\t'fields' => '',\n"; $out .= "\t\t\t'order' => '',\n"; $out .= "\t\t\t'limit' => '',\n"; $out .= "\t\t\t'offset' => '',\n"; $out .= "\t\t\t'finderQuery' => '',\n"; $out .= "\t\t)"; if ($i + 1 < $habtmCount) { $out .= ","; } echo $out; endforeach; echo "\n\t);\n\n"; endif; ?> } cakephp-2.8.0/lib/Cake/Console/Templates/default/classes/test.ctp000066400000000000000000000040121265552240500246600ustar00rootroot00000000000000 App::uses('', ''); /** * Test Case */ class Test extends ControllerTestCase { class Test extends CakeTestCase { /** * Fixtures * * @var array */ public $fixtures = array( '' ); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this-> } /** * tearDown method * * @return void */ public function tearDown() { unset($this->); parent::tearDown(); } /** * test method * * @return void */ public function test() { $this->markTestIncomplete('test not implemented.'); } } cakephp-2.8.0/lib/Cake/Console/Templates/default/views/000077500000000000000000000000001265552240500226745ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/default/views/form.ctp000066400000000000000000000052621265552240500243540ustar00rootroot00000000000000
Form->create('{$modelClass}'); ?>\n"; ?>
", Inflector::humanize($action), $singularHumanName); ?> Form->input('{$field}');\n"; } } if (!empty($associations['hasAndBelongsToMany'])) { foreach ($associations['hasAndBelongsToMany'] as $assocName => $assocData) { echo "\t\techo \$this->Form->input('{$assocName}');\n"; } } echo "\t?>\n"; ?>
Form->end(__('Submit')); ?>\n"; ?>

"; ?>

  • Form->postLink(__('Delete'), array('action' => 'delete', \$this->Form->value('{$modelClass}.{$primaryKey}')), array('confirm' => __('Are you sure you want to delete # %s?', \$this->Form->value('{$modelClass}.{$primaryKey}')))); ?>"; ?>
  • Html->link(__('List " . $pluralHumanName . "'), array('action' => 'index')); ?>"; ?>
  • $data) { foreach ($data as $alias => $details) { if ($details['controller'] != $this->name && !in_array($details['controller'], $done)) { echo "\t\t
  • Html->link(__('List " . Inflector::humanize($details['controller']) . "'), array('controller' => '{$details['controller']}', 'action' => 'index')); ?>
  • \n"; echo "\t\t
  • Html->link(__('New " . Inflector::humanize(Inflector::underscore($alias)) . "'), array('controller' => '{$details['controller']}', 'action' => 'add')); ?>
  • \n"; $done[] = $details['controller']; } } } ?>
cakephp-2.8.0/lib/Cake/Console/Templates/default/views/index.ctp000066400000000000000000000076561265552240500245310ustar00rootroot00000000000000

"; ?>

\n"; echo "\t\n"; foreach ($fields as $field) { $isKey = false; if (!empty($associations['belongsTo'])) { foreach ($associations['belongsTo'] as $alias => $details) { if ($field === $details['foreignKey']) { $isKey = true; echo "\t\t\n"; break; } } } if ($isKey !== true) { echo "\t\t\n"; } } echo "\t\t\n"; echo "\t\n"; echo "\n"; ?>
Paginator->sort('{$field}'); ?>"; ?> "; ?>
\n\t\t\tHtml->link(\${$singularVar}['{$alias}']['{$details['displayField']}'], array('controller' => '{$details['controller']}', 'action' => 'view', \${$singularVar}['{$alias}']['{$details['primaryKey']}'])); ?>\n\t\t \n"; echo "\t\t\tHtml->link(__('View'), array('action' => 'view', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n"; echo "\t\t\tHtml->link(__('Edit'), array('action' => 'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n"; echo "\t\t\tForm->postLink(__('Delete'), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), array('confirm' => __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}']))); ?>\n"; echo "\t\t

Paginator->counter(array( 'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}') )); ?>"; ?>

Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled'));\n"; echo "\t\techo \$this->Paginator->numbers(array('separator' => ''));\n"; echo "\t\techo \$this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled'));\n"; echo "\t?>\n"; ?>

"; ?>

  • Html->link(__('New " . $singularHumanName . "'), array('action' => 'add')); ?>"; ?>
  • $data) { foreach ($data as $alias => $details) { if ($details['controller'] != $this->name && !in_array($details['controller'], $done)) { echo "\t\t
  • Html->link(__('List " . Inflector::humanize($details['controller']) . "'), array('controller' => '{$details['controller']}', 'action' => 'index')); ?>
  • \n"; echo "\t\t
  • Html->link(__('New " . Inflector::humanize(Inflector::underscore($alias)) . "'), array('controller' => '{$details['controller']}', 'action' => 'add')); ?>
  • \n"; $done[] = $details['controller']; } } } ?>
cakephp-2.8.0/lib/Cake/Console/Templates/default/views/view.ctp000066400000000000000000000143371265552240500243660ustar00rootroot00000000000000

"; ?>

$details) { if ($field === $details['foreignKey']) { $isKey = true; echo "\t\t
\n"; echo "\t\t
\n\t\t\tHtml->link(\${$singularVar}['{$alias}']['{$details['displayField']}'], array('controller' => '{$details['controller']}', 'action' => 'view', \${$singularVar}['{$alias}']['{$details['primaryKey']}'])); ?>\n\t\t\t \n\t\t
\n"; break; } } } if ($isKey !== true) { echo "\t\t
\n"; echo "\t\t
\n\t\t\t\n\t\t\t \n\t\t
\n"; } } ?>

"; ?>

    Html->link(__('Edit " . $singularHumanName ."'), array('action' => 'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?> \n"; echo "\t\t
  • Form->postLink(__('Delete " . $singularHumanName . "'), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), array('confirm' => __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}']))); ?>
  • \n"; echo "\t\t
  • Html->link(__('List " . $pluralHumanName . "'), array('action' => 'index')); ?>
  • \n"; echo "\t\t
  • Html->link(__('New " . $singularHumanName . "'), array('action' => 'add')); ?>
  • \n"; $done = array(); foreach ($associations as $type => $data) { foreach ($data as $alias => $details) { if ($details['controller'] != $this->name && !in_array($details['controller'], $done)) { echo "\t\t
  • Html->link(__('List " . Inflector::humanize($details['controller']) . "'), array('controller' => '{$details['controller']}', 'action' => 'index')); ?>
  • \n"; echo "\t\t
  • Html->link(__('New " . Inflector::humanize(Inflector::underscore($alias)) . "'), array('controller' => '{$details['controller']}', 'action' => 'add')); ?>
  • \n"; $done[] = $details['controller']; } } } ?>
$details): ?> $details): $otherSingularVar = Inflector::variable($alias); $otherPluralHumanName = Inflector::humanize($details['controller']); ?> cakephp-2.8.0/lib/Cake/Console/Templates/skel/000077500000000000000000000000001265552240500210515ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/.htaccess000066400000000000000000000001641265552240500226500ustar00rootroot00000000000000 RewriteEngine on RewriteRule ^$ webroot/ [L] RewriteRule (.*) webroot/$1 [L] cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/000077500000000000000000000000001265552240500222565ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/Schema/000077500000000000000000000000001265552240500234565ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/Schema/db_acl.php000066400000000000000000000060451265552240500254000ustar00rootroot00000000000000 array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 'parent_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'model' => array('type' => 'string', 'null' => true), 'foreign_key' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'alias' => array('type' => 'string', 'null' => true), 'lft' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'rght' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)) ); /** * ARO - Access Request Object - Something that wants something */ public $aros = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 'parent_id' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'model' => array('type' => 'string', 'null' => true), 'foreign_key' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'alias' => array('type' => 'string', 'null' => true), 'lft' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'rght' => array('type' => 'integer', 'null' => true, 'default' => null, 'length' => 10), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)) ); /** * Used by the Cake::Model:Permission class. * Checks if the given $aro has access to action $action in $aco. */ public $aros_acos = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 'aro_id' => array('type' => 'integer', 'null' => false, 'length' => 10, 'key' => 'index'), 'aco_id' => array('type' => 'integer', 'null' => false, 'length' => 10), '_create' => array('type' => 'string', 'null' => false, 'default' => '0', 'length' => 2), '_read' => array('type' => 'string', 'null' => false, 'default' => '0', 'length' => 2), '_update' => array('type' => 'string', 'null' => false, 'default' => '0', 'length' => 2), '_delete' => array('type' => 'string', 'null' => false, 'default' => '0', 'length' => 2), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), 'ARO_ACO_KEY' => array('column' => array('aro_id', 'aco_id'), 'unique' => 1)) ); } cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/Schema/db_acl.sql000066400000000000000000000030751265552240500254100ustar00rootroot00000000000000# $Id$ # # Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) # # Licensed under The MIT License # For full copyright and license information, please see the LICENSE.txt # Redistributions of files must retain the above copyright notice. # MIT License (http://www.opensource.org/licenses/mit-license.php) CREATE TABLE acos ( id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT, parent_id INTEGER(10) DEFAULT NULL, model VARCHAR(255) DEFAULT '', foreign_key INTEGER(10) UNSIGNED DEFAULT NULL, alias VARCHAR(255) DEFAULT '', lft INTEGER(10) DEFAULT NULL, rght INTEGER(10) DEFAULT NULL, PRIMARY KEY (id) ); CREATE TABLE aros_acos ( id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT, aro_id INTEGER(10) UNSIGNED NOT NULL, aco_id INTEGER(10) UNSIGNED NOT NULL, _create CHAR(2) NOT NULL DEFAULT 0, _read CHAR(2) NOT NULL DEFAULT 0, _update CHAR(2) NOT NULL DEFAULT 0, _delete CHAR(2) NOT NULL DEFAULT 0, PRIMARY KEY(id) ); CREATE TABLE aros ( id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT, parent_id INTEGER(10) DEFAULT NULL, model VARCHAR(255) DEFAULT '', foreign_key INTEGER(10) UNSIGNED DEFAULT NULL, alias VARCHAR(255) DEFAULT '', lft INTEGER(10) DEFAULT NULL, rght INTEGER(10) DEFAULT NULL, PRIMARY KEY (id) ); /* this indexes will improve acl perfomance */ CREATE INDEX idx_acos_lft_rght ON `acos` (`lft`, `rght`); CREATE INDEX idx_acos_alias ON `acos` (`alias`); CREATE INDEX idx_aros_lft_rght ON `aros` (`lft`, `rght`); CREATE INDEX idx_aros_alias ON `aros` (`alias`); CREATE INDEX idx_aco_id ON `aros_acos` (`aco_id`); cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/Schema/i18n.php000066400000000000000000000042111265552240500247440ustar00rootroot00000000000000 array('type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary'), 'locale' => array('type' => 'string', 'null' => false, 'length' => 6, 'key' => 'index'), 'model' => array('type' => 'string', 'null' => false, 'key' => 'index'), 'foreign_key' => array('type' => 'integer', 'null' => false, 'length' => 10, 'key' => 'index'), 'field' => array('type' => 'string', 'null' => false, 'key' => 'index'), 'content' => array('type' => 'text', 'null' => true, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1), 'locale' => array('column' => 'locale', 'unique' => 0), 'model' => array('column' => 'model', 'unique' => 0), 'row_id' => array('column' => 'foreign_key', 'unique' => 0), 'field' => array('column' => 'field', 'unique' => 0)) ); } cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/Schema/i18n.sql000066400000000000000000000015731265552240500247640ustar00rootroot00000000000000# $Id$ # # Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) # # Licensed under The MIT License # For full copyright and license information, please see the LICENSE.txt # Redistributions of files must retain the above copyright notice. # MIT License (http://www.opensource.org/licenses/mit-license.php) CREATE TABLE i18n ( id int(10) NOT NULL auto_increment, locale varchar(6) NOT NULL, model varchar(255) NOT NULL, foreign_key int(10) NOT NULL, field varchar(255) NOT NULL, content mediumtext, PRIMARY KEY (id), # UNIQUE INDEX I18N_LOCALE_FIELD(locale, model, foreign_key, field), # INDEX I18N_LOCALE_ROW(locale, model, foreign_key), # INDEX I18N_LOCALE_MODEL(locale, model), # INDEX I18N_FIELD(model, foreign_key, field), # INDEX I18N_ROW(model, foreign_key), INDEX locale (locale), INDEX model (model), INDEX row_id (foreign_key), INDEX field (field) );cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/Schema/sessions.php000066400000000000000000000031571265552240500260430ustar00rootroot00000000000000 array('type' => 'string', 'null' => false, 'key' => 'primary'), 'data' => array('type' => 'text', 'null' => true, 'default' => null), 'expires' => array('type' => 'integer', 'null' => true, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)) ); } cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/Schema/sessions.sql000066400000000000000000000010351265552240500260440ustar00rootroot00000000000000# $Id$ # # Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) # 1785 E. Sahara Avenue, Suite 490-204 # Las Vegas, Nevada 89104 # # Licensed under The MIT License # For full copyright and license information, please see the LICENSE.txt # Redistributions of files must retain the above copyright notice. # MIT License (http://www.opensource.org/licenses/mit-license.php) CREATE TABLE cake_sessions ( id varchar(255) NOT NULL default '', data text, expires int(11) default NULL, PRIMARY KEY (id) );cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/acl.ini.php000066400000000000000000000030351265552240500243050ustar00rootroot00000000000000; ;/** ; * ACL Configuration ; * ; * @link http://cakephp.org CakePHP(tm) Project ; * @package app.Config ; * @since CakePHP(tm) v 0.10.0.1076 ; */ ; acl.ini.php - CakePHP ACL Configuration ; --------------------------------------------------------------------- ; Use this file to specify user permissions. ; aco = access control object (something in your application) ; aro = access request object (something requesting access) ; ; User records are added as follows: ; ; [uid] ; groups = group1, group2, group3 ; allow = aco1, aco2, aco3 ; deny = aco4, aco5, aco6 ; ; Group records are added in a similar manner: ; ; [gid] ; allow = aco1, aco2, aco3 ; deny = aco4, aco5, aco6 ; ; The allow, deny, and groups sections are all optional. ; NOTE: groups names *cannot* ever be the same as usernames! ; ; ACL permissions are checked in the following order: ; 1. Check for user denies (and DENY if specified) ; 2. Check for user allows (and ALLOW if specified) ; 3. Gather user's groups ; 4. Check group denies (and DENY if specified) ; 5. Check group allows (and ALLOW if specified) ; 6. If no aro, aco, or group information is found, DENY ; ; --------------------------------------------------------------------- ;------------------------------------- ;Users ;------------------------------------- [username-goes-here] groups = group1, group2 deny = aco1, aco2 allow = aco3, aco4 ;------------------------------------- ;Groups ;------------------------------------- [groupname-goes-here] deny = aco5, aco6 allow = aco7, aco8 cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/acl.php000066400000000000000000000105201265552240500235240ustar00rootroot00000000000000Auth->authorize = array('Actions' => array('actionPath' => 'controllers/'),...) * * Now, when a user (i.e. jeff) authenticates successfully and requests a controller action (i.e. /invoices/delete) * that is not allowed by default (e.g. via $this->Auth->allow('edit') in the Invoices controller) then AuthComponent * will ask the configured ACL interface if access is granted. Under the assumptions 1. and 2. this will be * done via a call to Acl->check() with * * array('User' => array('username' => 'jeff', 'group_id' => 4, ...)) * * as ARO and * * '/controllers/invoices/delete' * * as ACO. * * If the configured map looks like * * $config['map'] = array( * 'User' => 'User/username', * 'Role' => 'User/group_id', * ); * * then PhpAcl will lookup if we defined a role like User/jeff. If that role is not found, PhpAcl will try to * find a definition for Role/4. If the definition isn't found then a default role (Role/default) will be used to * check rules for the given ACO. The search can be expanded by defining aliases in the alias configuration. * E.g. if you want to use a more readable name than Role/4 in your definitions you can define an alias like * * $config['alias'] = array( * 'Role/4' => 'Role/editor', * ); * * In the roles configuration you can define roles on the lhs and inherited roles on the rhs: * * $config['roles'] = array( * 'Role/admin' => null, * 'Role/accountant' => null, * 'Role/editor' => null, * 'Role/manager' => 'Role/editor, Role/accountant', * 'User/jeff' => 'Role/manager', * ); * * In this example manager inherits all rules from editor and accountant. Role/admin doesn't inherit from any role. * Lets define some rules: * * $config['rules'] = array( * 'allow' => array( * '*' => 'Role/admin', * 'controllers/users/(dashboard|profile)' => 'Role/default', * 'controllers/invoices/*' => 'Role/accountant', * 'controllers/articles/*' => 'Role/editor', * 'controllers/users/*' => 'Role/manager', * 'controllers/invoices/delete' => 'Role/manager', * ), * 'deny' => array( * 'controllers/invoices/delete' => 'Role/accountant, User/jeff', * 'controllers/articles/(delete|publish)' => 'Role/editor', * ), * ); * * Ok, so as jeff inherits from Role/manager he's matched every rule that references User/jeff, Role/manager, * Role/editor, Role/accountant and Role/default. However, for jeff, rules for User/jeff are more specific than * rules for Role/manager, rules for Role/manager are more specific than rules for Role/editor and so on. * This is important when allow and deny rules match for a role. E.g. Role/accountant is allowed * controllers/invoices/* but at the same time controllers/invoices/delete is denied. But there is a more * specific rule defined for Role/manager which is allowed controllers/invoices/delete. However, the most specific * rule denies access to the delete action explicitly for User/jeff, so he'll be denied access to the resource. * * If we would remove the role definition for User/jeff, then jeff would be granted access as he would be resolved * to Role/manager and Role/manager has an allow rule. */ /** * The role map defines how to resolve the user record from your application * to the roles you defined in the roles configuration. */ $config['map'] = array( 'User' => 'User/username', 'Role' => 'User/group_id', ); /** * define aliases to map your model information to * the roles defined in your role configuration. */ $config['alias'] = array( 'Role/4' => 'Role/editor', ); /** * role configuration */ $config['roles'] = array( 'Role/admin' => null, ); /** * rule configuration */ $config['rules'] = array( 'allow' => array( '*' => 'Role/admin', ), 'deny' => array(), ); cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/bootstrap.php000066400000000000000000000110561265552240500250070ustar00rootroot00000000000000 'File')); /** * The settings below can be used to set additional paths to models, views and controllers. * * App::build(array( * 'Model' => array('/path/to/models/', '/next/path/to/models/'), * 'Model/Behavior' => array('/path/to/behaviors/', '/next/path/to/behaviors/'), * 'Model/Datasource' => array('/path/to/datasources/', '/next/path/to/datasources/'), * 'Model/Datasource/Database' => array('/path/to/databases/', '/next/path/to/database/'), * 'Model/Datasource/Session' => array('/path/to/sessions/', '/next/path/to/sessions/'), * 'Controller' => array('/path/to/controllers/', '/next/path/to/controllers/'), * 'Controller/Component' => array('/path/to/components/', '/next/path/to/components/'), * 'Controller/Component/Auth' => array('/path/to/auths/', '/next/path/to/auths/'), * 'Controller/Component/Acl' => array('/path/to/acls/', '/next/path/to/acls/'), * 'View' => array('/path/to/views/', '/next/path/to/views/'), * 'View/Helper' => array('/path/to/helpers/', '/next/path/to/helpers/'), * 'Console' => array('/path/to/consoles/', '/next/path/to/consoles/'), * 'Console/Command' => array('/path/to/commands/', '/next/path/to/commands/'), * 'Console/Command/Task' => array('/path/to/tasks/', '/next/path/to/tasks/'), * 'Lib' => array('/path/to/libs/', '/next/path/to/libs/'), * 'Locale' => array('/path/to/locales/', '/next/path/to/locales/'), * 'Vendor' => array('/path/to/vendors/', '/next/path/to/vendors/'), * 'Plugin' => array('/path/to/plugins/', '/next/path/to/plugins/'), * )); */ /** * Custom Inflector rules can be set to correctly pluralize or singularize table, model, controller names or whatever other * string is passed to the inflection functions * * Inflector::rules('singular', array('rules' => array(), 'irregular' => array(), 'uninflected' => array())); * Inflector::rules('plural', array('rules' => array(), 'irregular' => array(), 'uninflected' => array())); */ /** * Plugins need to be loaded manually, you can either load them one by one or all of them in a single call * Uncomment one of the lines below, as you need. Make sure you read the documentation on CakePlugin to use more * advanced ways of loading plugins * * CakePlugin::loadAll(); // Loads all plugins at once * CakePlugin::load('DebugKit'); // Loads a single plugin named DebugKit */ /** * You can attach event listeners to the request lifecycle as Dispatcher Filter . By default CakePHP bundles two filters: * * - AssetDispatcher filter will serve your asset files (css, images, js, etc) from your themes and plugins * - CacheDispatcher filter will read the Cache.check configure variable and try to serve cached content generated from controllers * * Feel free to remove or add filters as you see fit for your application. A few examples: * * Configure::write('Dispatcher.filters', array( * 'MyCacheFilter', // will use MyCacheFilter class from the Routing/Filter package in your app. * 'MyPlugin.MyFilter', // will use MyFilter class from the Routing/Filter package in MyPlugin plugin. * array('callable' => $aFunction, 'on' => 'before', 'priority' => 9), // A valid PHP callback type to be called on beforeDispatch * array('callable' => $anotherMethod, 'on' => 'after'), // A valid PHP callback type to be called on afterDispatch * * )); */ Configure::write('Dispatcher.filters', array( 'AssetDispatcher', 'CacheDispatcher' )); /** * Configures default file logging options */ App::uses('CakeLog', 'Log'); CakeLog::config('debug', array( 'engine' => 'File', 'types' => array('notice', 'info', 'debug'), 'file' => 'debug', )); CakeLog::config('error', array( 'engine' => 'File', 'types' => array('warning', 'error', 'critical', 'alert', 'emergency'), 'file' => 'error', )); cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/core.php000066400000000000000000000322241265552240500237220ustar00rootroot00000000000000 0 * and log errors with CakeLog when debug = 0. * * Options: * * - `handler` - callback - The callback to handle errors. You can set this to any callable type, * including anonymous functions. * Make sure you add App::uses('MyHandler', 'Error'); when using a custom handler class * - `level` - integer - The level of errors you are interested in capturing. * - `trace` - boolean - Include stack traces for errors in log files. * * @see ErrorHandler for more information on error handling and configuration. */ Configure::write('Error', array( 'handler' => 'ErrorHandler::handleError', 'level' => E_ALL & ~E_DEPRECATED, 'trace' => true )); /** * Configure the Exception handler used for uncaught exceptions. By default, * ErrorHandler::handleException() is used. It will display a HTML page for the exception, and * while debug > 0, framework errors like Missing Controller will be displayed. When debug = 0, * framework errors will be coerced into generic HTTP errors. * * Options: * * - `handler` - callback - The callback to handle exceptions. You can set this to any callback type, * including anonymous functions. * Make sure you add App::uses('MyHandler', 'Error'); when using a custom handler class * - `renderer` - string - The class responsible for rendering uncaught exceptions. If you choose a custom class you * should place the file for that class in app/Lib/Error. This class needs to implement a render method. * - `log` - boolean - Should Exceptions be logged? * - `skipLog` - array - list of exceptions to skip for logging. Exceptions that * extend one of the listed exceptions will also be skipped for logging. * Example: `'skipLog' => array('NotFoundException', 'UnauthorizedException')` * * @see ErrorHandler for more information on exception handling and configuration. */ Configure::write('Exception', array( 'handler' => 'ErrorHandler::handleException', 'renderer' => 'ExceptionRenderer', 'log' => true )); /** * Application wide charset encoding */ Configure::write('App.encoding', 'UTF-8'); /** * To configure CakePHP *not* to use mod_rewrite and to * use CakePHP pretty URLs, remove these .htaccess * files: * * /.htaccess * /app/.htaccess * /app/webroot/.htaccess * * And uncomment the App.baseUrl below. But keep in mind * that plugin assets such as images, CSS and JavaScript files * will not work without URL rewriting! * To work around this issue you should either symlink or copy * the plugin assets into you app's webroot directory. This is * recommended even when you are using mod_rewrite. Handling static * assets through the Dispatcher is incredibly inefficient and * included primarily as a development convenience - and * thus not recommended for production applications. */ //Configure::write('App.baseUrl', env('SCRIPT_NAME')); /** * To configure CakePHP to use a particular domain URL * for any URL generation inside the application, set the following * configuration variable to the http(s) address to your domain. This * will override the automatic detection of full base URL and can be * useful when generating links from the CLI (e.g. sending emails) */ //Configure::write('App.fullBaseUrl', 'http://example.com'); /** * Web path to the public images directory under webroot. * If not set defaults to 'img/' */ //Configure::write('App.imageBaseUrl', 'img/'); /** * Web path to the CSS files directory under webroot. * If not set defaults to 'css/' */ //Configure::write('App.cssBaseUrl', 'css/'); /** * Web path to the js files directory under webroot. * If not set defaults to 'js/' */ //Configure::write('App.jsBaseUrl', 'js/'); /** * Uncomment the define below to use CakePHP prefix routes. * * The value of the define determines the names of the routes * and their associated controller actions: * * Set to an array of prefixes you want to use in your application. Use for * admin or other prefixed routes. * * Routing.prefixes = array('admin', 'manager'); * * Enables: * `admin_index()` and `/admin/controller/index` * `manager_index()` and `/manager/controller/index` */ //Configure::write('Routing.prefixes', array('admin')); /** * Turn off all caching application-wide. */ //Configure::write('Cache.disable', true); /** * Enable cache checking. * * If set to true, for view caching you must still use the controller * public $cacheAction inside your controllers to define caching settings. * You can either set it controller-wide by setting public $cacheAction = true, * or in each action using $this->cacheAction = true. */ //Configure::write('Cache.check', true); /** * Enable cache view prefixes. * * If set it will be prepended to the cache name for view file caching. This is * helpful if you deploy the same application via multiple subdomains and languages, * for instance. Each version can then have its own view cache namespace. * Note: The final cache file name will then be `prefix_cachefilename`. */ //Configure::write('Cache.viewPrefix', 'prefix'); /** * Session configuration. * * Contains an array of settings to use for session configuration. The defaults key is * used to define a default preset to use for sessions, any settings declared here will override * the settings of the default config. * * ## Options * * - `Session.cookie` - The name of the cookie to use. Defaults to 'CAKEPHP' * - `Session.timeout` - The number of minutes you want sessions to live for. This timeout is handled by CakePHP * - `Session.cookieTimeout` - The number of minutes you want session cookies to live for. * - `Session.checkAgent` - Do you want the user agent to be checked when starting sessions? You might want to set the * value to false, when dealing with older versions of IE, Chrome Frame or certain web-browsing devices and AJAX * - `Session.defaults` - The default configuration set to use as a basis for your session. * There are four builtins: php, cake, cache, database. * - `Session.handler` - Can be used to enable a custom session handler. Expects an array of callables, * that can be used with `session_save_handler`. Using this option will automatically add `session.save_handler` * to the ini array. * - `Session.autoRegenerate` - Enabling this setting, turns on automatic renewal of sessions, and * sessionids that change frequently. See CakeSession::$requestCountdown. * - `Session.ini` - An associative array of additional ini values to set. * * The built in defaults are: * * - 'php' - Uses settings defined in your php.ini. * - 'cake' - Saves session files in CakePHP's /tmp directory. * - 'database' - Uses CakePHP's database sessions. * - 'cache' - Use the Cache class to save sessions. * * To define a custom session handler, save it at /app/Model/Datasource/Session/.php. * Make sure the class implements `CakeSessionHandlerInterface` and set Session.handler to * * To use database sessions, run the app/Config/Schema/sessions.php schema using * the cake shell command: cake schema create Sessions */ Configure::write('Session', array( 'defaults' => 'php' )); /** * A random string used in security hashing methods. */ Configure::write('Security.salt', 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi'); /** * A random numeric string (digits only) used to encrypt/decrypt strings. */ Configure::write('Security.cipherSeed', '76859309657453542496749683645'); /** * Apply timestamps with the last modified time to static assets (js, css, images). * Will append a query string parameter containing the time the file was modified. This is * useful for invalidating browser caches. * * Set to `true` to apply timestamps when debug > 0. Set to 'force' to always enable * timestamping regardless of debug value. */ //Configure::write('Asset.timestamp', true); /** * Compress CSS output by removing comments, whitespace, repeating tags, etc. * This requires a/var/cache directory to be writable by the web server for caching. * and /vendors/csspp/csspp.php * * To use, prefix the CSS link URL with '/ccss/' instead of '/css/' or use HtmlHelper::css(). */ //Configure::write('Asset.filter.css', 'css.php'); /** * Plug in your own custom JavaScript compressor by dropping a script in your webroot to handle the * output, and setting the config below to the name of the script. * * To use, prefix your JavaScript link URLs with '/cjs/' instead of '/js/' or use JsHelper::link(). */ //Configure::write('Asset.filter.js', 'custom_javascript_output_filter.php'); /** * The class name and database used in CakePHP's * access control lists. */ Configure::write('Acl.classname', 'DbAcl'); Configure::write('Acl.database', 'default'); /** * Uncomment this line and correct your server timezone to fix * any date & time related errors. */ //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] * 'mask' => 0664, //[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://www.danga.com/memcached/) * * 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 * )); */ /** * Configure the cache handlers that CakePHP will use for internal * metadata like class maps, and model schema. * * By default File is used, but for improved performance you should use APC. * * Note: 'default' and other application caches should be configured in app/Config/bootstrap.php. * Please check the comments in bootstrap.php for more info on the cache engines available * and their settings. */ $engine = 'File'; // In development mode, caches should expire quickly. $duration = '+999 days'; if (Configure::read('debug') > 0) { $duration = '+10 seconds'; } // Prefix each application on the same server with a different string, to avoid Memcache and APC conflicts. $prefix = 'myapp_'; /** * Configure the cache used for general framework caching. Path information, * object listings, and translation cache files are stored with this configuration. */ Cache::config('_cake_core_', array( 'engine' => $engine, 'prefix' => $prefix . 'cake_core_', 'path' => CACHE . 'persistent' . DS, 'serialize' => ($engine === 'File'), 'duration' => $duration )); /** * Configure the cache for model and datasource caches. This cache configuration * is used to store schema descriptions, and table listings in connections. */ Cache::config('_cake_model_', array( 'engine' => $engine, 'prefix' => $prefix . 'cake_model_', 'path' => CACHE . 'models' . DS, 'serialize' => ($engine === 'File'), 'duration' => $duration )); cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/database.php.default000066400000000000000000000047571265552240500261730ustar00rootroot00000000000000 The name of a supported datasource; valid options are as follows: * Database/Mysql - MySQL 4 & 5, * Database/Sqlite - SQLite (PHP5 only), * Database/Postgres - PostgreSQL 7 and higher, * Database/Sqlserver - Microsoft SQL Server 2005 and higher * * You can add custom database datasources (or override existing datasources) by adding the * appropriate file to app/Model/Datasource/Database. Datasources should be named 'MyDatasource.php', * * * persistent => true / false * Determines whether or not the database should use a persistent connection * * host => * the host you connect to the database. To add a socket or port number, use 'port' => # * * prefix => * Uses the given prefix for all the tables in this database. This setting can be overridden * on a per-table basis with the Model::$tablePrefix property. * * schema => * For Postgres/Sqlserver specifies which schema you would like to use the tables in. Postgres defaults to 'public'. For Sqlserver, it defaults to empty and use * the connected user's default schema (typically 'dbo'). * * encoding => * For MySQL, Postgres specifies the character encoding to use when connecting to the * database. Uses database default not specified. * * unix_socket => * For MySQL to connect via socket specify the `unix_socket` parameter instead of `host` and `port` * * settings => * Array of key/value pairs, on connection it executes SET statements for each pair * For MySQL : http://dev.mysql.com/doc/refman/5.6/en/set-statement.html * For Postgres : http://www.postgresql.org/docs/9.2/static/sql-set.html * For Sql Server : http://msdn.microsoft.com/en-us/library/ms190356.aspx * * flags => * A key/value array of driver specific connection options. */ class DATABASE_CONFIG { public $default = array( 'datasource' => 'Database/Mysql', 'persistent' => false, 'host' => 'localhost', 'login' => 'user', 'password' => 'password', 'database' => 'database_name', 'prefix' => '', //'encoding' => 'utf8', ); public $test = array( 'datasource' => 'Database/Mysql', 'persistent' => false, 'host' => 'localhost', 'login' => 'user', 'password' => 'password', 'database' => 'test_database_name', 'prefix' => '', //'encoding' => 'utf8', ); } cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/email.php.default000066400000000000000000000037101265552240500255020ustar00rootroot00000000000000 The name of a supported transport; valid options are as follows: * Mail - Send using PHP mail function * Smtp - Send using SMTP * Debug - Do not send the email, just return the result * * You can add custom transports (or override existing transports) by adding the * appropriate file to app/Network/Email. Transports should be named 'YourTransport.php', * where 'Your' is the name of the transport. * * from => * The origin email. See CakeEmail::from() about the valid values */ class EmailConfig { public $default = array( 'transport' => 'Mail', 'from' => 'you@localhost', //'charset' => 'utf-8', //'headerCharset' => 'utf-8', ); public $smtp = array( 'transport' => 'Smtp', 'from' => array('site@localhost' => 'My Site'), 'host' => 'localhost', 'port' => 25, 'timeout' => 30, 'username' => 'user', 'password' => 'secret', 'client' => null, 'log' => false, //'charset' => 'utf-8', //'headerCharset' => 'utf-8', ); public $fast = array( 'from' => 'you@localhost', 'sender' => null, 'to' => null, 'cc' => null, 'bcc' => null, 'replyTo' => null, 'readReceipt' => null, 'returnPath' => null, 'messageId' => true, 'subject' => null, 'message' => null, 'headers' => null, 'viewRender' => null, 'template' => false, 'layout' => false, 'viewVars' => null, 'attachments' => null, 'emailFormat' => null, 'transport' => 'Smtp', 'host' => 'localhost', 'port' => 25, 'timeout' => 30, 'username' => 'user', 'password' => 'secret', 'client' => null, 'log' => true, //'charset' => 'utf-8', //'headerCharset' => 'utf-8', ); } cakephp-2.8.0/lib/Cake/Console/Templates/skel/Config/routes.php000066400000000000000000000021711265552240500243110ustar00rootroot00000000000000 'pages', 'action' => 'display', 'home')); /** * ...and connect the rest of 'Pages' controller's URLs. */ Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display')); /** * Load all plugin routes. See the CakePlugin documentation on * how to customize the loading of plugin routes. */ CakePlugin::routes(); /** * Load the CakePHP default routes. Only remove this if you do not want to use * the built-in default routes. */ require CAKE . 'Config' . DS . 'routes.php'; cakephp-2.8.0/lib/Cake/Console/Templates/skel/Console/000077500000000000000000000000001265552240500224535ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Console/Command/000077500000000000000000000000001265552240500240315ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Console/Command/AppShell.php000066400000000000000000000005461265552240500262570ustar00rootroot00000000000000redirect('/'); } $page = $subpage = $title_for_layout = null; if (!empty($path[0])) { $page = $path[0]; } if (!empty($path[1])) { $subpage = $path[1]; } if (!empty($path[$count - 1])) { $title_for_layout = Inflector::humanize($path[$count - 1]); } $this->set(compact('page', 'subpage', 'title_for_layout')); try { $this->render(implode('/', $path)); } catch (MissingViewException $e) { if (Configure::read('debug')) { throw $e; } throw new NotFoundException(); } } } cakephp-2.8.0/lib/Cake/Console/Templates/skel/Lib/000077500000000000000000000000001265552240500215575ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Lib/empty000066400000000000000000000000001265552240500226260ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Locale/000077500000000000000000000000001265552240500222505ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Locale/eng/000077500000000000000000000000001265552240500230215ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Locale/eng/LC_MESSAGES/000077500000000000000000000000001265552240500246065ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Locale/eng/LC_MESSAGES/empty000066400000000000000000000000001265552240500256550ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Model/000077500000000000000000000000001265552240500221115ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Model/AppModel.php000066400000000000000000000007771265552240500243360ustar00rootroot00000000000000addTestDirectoryRecursive(TESTS . 'Case'); return $suite; } } cakephp-2.8.0/lib/Cake/Console/Templates/skel/Test/Case/Controller/000077500000000000000000000000001265552240500247665ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Test/Case/Controller/Component/000077500000000000000000000000001265552240500267305ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Test/Case/Controller/Component/empty000066400000000000000000000000001265552240500277770ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Test/Case/Model/000077500000000000000000000000001265552240500237035ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Test/Case/Model/Behavior/000077500000000000000000000000001265552240500254425ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Test/Case/Model/Behavior/empty000066400000000000000000000000001265552240500265110ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Test/Case/View/000077500000000000000000000000001265552240500235555ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Test/Case/View/Helper/000077500000000000000000000000001265552240500247745ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Test/Case/View/Helper/empty000066400000000000000000000000001265552240500260430ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Test/Fixture/000077500000000000000000000000001265552240500234165ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Test/Fixture/empty000066400000000000000000000000001265552240500244650ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Vendor/000077500000000000000000000000001265552240500223065ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/Vendor/empty000066400000000000000000000000001265552240500233550ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/000077500000000000000000000000001265552240500217635ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Elements/000077500000000000000000000000001265552240500235375ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Elements/Flash/000077500000000000000000000000001265552240500245745ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Elements/Flash/default.ctp000066400000000000000000000002211265552240500267230ustar00rootroot00000000000000
cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Emails/000077500000000000000000000000001265552240500231755ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Emails/html/000077500000000000000000000000001265552240500241415ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Emails/html/default.ctp000066400000000000000000000014011265552240500262710ustar00rootroot00000000000000 ' . $line . "

\n"; endforeach;cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Emails/text/000077500000000000000000000000001265552240500241615ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Emails/text/default.ctp000066400000000000000000000012441265552240500263160ustar00rootroot00000000000000 cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Errors/000077500000000000000000000000001265552240500232375ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Errors/error400.ctp000066400000000000000000000007441265552240500253310ustar00rootroot00000000000000

: '{$url}'" ); ?>

0): echo $this->element('exception_stack_trace'); endif; cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Errors/error500.ctp000066400000000000000000000006461265552240500253330ustar00rootroot00000000000000

:

0): echo $this->element('exception_stack_trace'); endif; cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Helper/000077500000000000000000000000001265552240500232025ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Helper/AppHelper.php000066400000000000000000000010111265552240500255640ustar00rootroot00000000000000 <?php echo $this->fetch('title'); ?> fetch('content'); ?>

This email was sent using the CakePHP Framework

cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Layouts/Emails/text/000077500000000000000000000000001265552240500256215ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Layouts/Emails/text/default.ctp000066400000000000000000000014011265552240500277510ustar00rootroot00000000000000 fetch('content'); ?> This email was sent using the CakePHP Framework, http://cakephp.org. cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Layouts/ajax.ctp000066400000000000000000000003001265552240500250470ustar00rootroot00000000000000 fetch('content'); ?> cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Layouts/default.ctp000066400000000000000000000022121265552240500255540ustar00rootroot00000000000000 Html->charset(); ?> <?php echo $cakeDescription ?>: <?php echo $this->fetch('title'); ?> Html->meta('icon'); echo $this->Html->css('cake.generic'); echo $this->fetch('meta'); echo $this->fetch('css'); echo $this->fetch('script'); ?>
Session->flash(); ?> fetch('content'); ?>
element('sql_dump'); ?> cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Layouts/error.ctp000066400000000000000000000022121265552240500252610ustar00rootroot00000000000000 Html->charset(); ?> <?php echo $cakeDescription ?>: <?php echo $this->fetch('title'); ?> Html->meta('icon'); echo $this->Html->css('cake.generic'); echo $this->fetch('meta'); echo $this->fetch('css'); echo $this->fetch('script'); ?>
Session->flash(); ?> fetch('content'); ?>
element('sql_dump'); ?> cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Layouts/flash.ctp000066400000000000000000000012321265552240500252260ustar00rootroot00000000000000 Html->charset(); ?> <?php echo $pageTitle; ?>

cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Layouts/js/000077500000000000000000000000001265552240500240375ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Layouts/js/default.ctp000066400000000000000000000001621265552240500261720ustar00rootroot00000000000000 cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Layouts/rss/000077500000000000000000000000001265552240500242325ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Layouts/rss/default.ctp000066400000000000000000000003611265552240500263660ustar00rootroot00000000000000fetch('title'); endif; echo $this->Rss->document( $this->Rss->channel( array(), $channel, $this->fetch('content') ) ); cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Layouts/xml/000077500000000000000000000000001265552240500242235ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Layouts/xml/default.ctp000066400000000000000000000000471265552240500263600ustar00rootroot00000000000000fetch('content'); ?> cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Pages/000077500000000000000000000000001265552240500230225ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Pages/home.ctp000066400000000000000000000216761265552240500244760ustar00rootroot00000000000000

0): Debugger::checkSecurityKeys(); endif; ?>

1) Help me configure it 2) I don't / can't use URL rewriting

=')): echo ''; echo __d('cake_dev', 'Your version of PHP is 5.2.8 or higher.'); echo ''; else: echo ''; echo __d('cake_dev', 'Your version of PHP is too low. You need PHP 5.2.8 or higher to use CakePHP.'); echo ''; endif; ?>

'; echo __d('cake_dev', 'Your tmp directory is writable.'); echo ''; else: echo ''; echo __d('cake_dev', 'Your tmp directory is NOT writable.'); echo ''; endif; ?>

'; echo __d('cake_dev', 'The %s is being used for core caching. To change the config edit %s', '' . $settings['engine'] . 'Engine', 'APP/Config/core.php'); echo ''; else: echo ''; echo __d('cake_dev', 'Your cache is NOT working. Please check the settings in %s', 'APP/Config/core.php'); echo ''; endif; ?>

'; echo __d('cake_dev', 'Your database configuration file is present.'); $filePresent = true; echo ''; else: echo ''; echo __d('cake_dev', 'Your database configuration file is NOT present.'); echo '
'; echo __d('cake_dev', 'Rename %s to %s', 'APP/Config/database.php.default', 'APP/Config/database.php'); echo '
'; endif; ?>

getMessage(); if (method_exists($connectionError, 'getAttributes')): $attributes = $connectionError->getAttributes(); if (isset($errorMsg['message'])): $errorMsg .= '
' . $attributes['message']; endif; endif; } ?>

isConnected()): echo ''; echo __d('cake_dev', 'CakePHP is able to connect to the database.'); echo ''; else: echo ''; echo __d('cake_dev', 'CakePHP is NOT able to connect to the database.'); echo '

'; echo $errorMsg; echo '
'; endif; ?>

'; echo __d('cake_dev', 'PCRE has not been compiled with Unicode support.'); echo '
'; echo __d('cake_dev', 'Recompile PCRE with Unicode support by adding --enable-unicode-properties when configuring'); echo '

'; endif; ?>

'; echo __d('cake_dev', 'DebugKit plugin is present'); echo ''; else: echo ''; echo __d('cake_dev', 'DebugKit is not installed. It will help you inspect and debug different aspects of your application.'); echo '
'; echo __d('cake_dev', 'You can install it from %s', $this->Html->link('GitHub', 'https://github.com/cakephp/debug_kit/tree/2.2')); echo '
'; endif; ?>

To change its layout, edit: %s.
You can also add some CSS styles for your pages at: %s.', 'APP/View/Pages/home.ctp', 'APP/View/Layouts/default.ctp', 'APP/webroot/css'); ?>

Html->link( sprintf('%s %s', __d('cake_dev', 'New'), __d('cake_dev', 'CakePHP 2.0 Docs')), 'http://book.cakephp.org/2.0/en/', array('target' => '_blank', 'escape' => false) ); ?>

Html->link( __d('cake_dev', 'The 15 min Blog Tutorial'), 'http://book.cakephp.org/2.0/en/tutorials-and-examples/blog/blog.html', array('target' => '_blank', 'escape' => false) ); ?>

  • Html->link('DebugKit', 'https://github.com/cakephp/debug_kit/tree/2.2') ?>:
  • Html->link('Localized', 'https://github.com/cakephp/localized') ?>:

cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Scaffolds/000077500000000000000000000000001265552240500236675ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/View/Scaffolds/empty000066400000000000000000000000001265552240500247360ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/index.php000066400000000000000000000003011265552240500226630ustar00rootroot00000000000000 RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/css/000077500000000000000000000000001265552240500233225ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/css/cake.generic.css000066400000000000000000000361301265552240500263550ustar00rootroot00000000000000@charset "utf-8"; /** * Generic CSS for CakePHP * * CakePHP(tm) : Rapid Development Framework (http://cakephp.org) * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://cakephp.org CakePHP(tm) Project * @package app.webroot.css * @license http://www.opensource.org/licenses/mit-license.php MIT License */ * { margin:0; padding:0; } /** General Style Info **/ body { background: #003d4c; color: #fff; font-family:'lucida grande',verdana,helvetica,arial,sans-serif; font-size:90%; margin: 0; } a { color: #003d4c; text-decoration: underline; font-weight: bold; } a:hover { color: #367889; text-decoration:none; } a img { border:none; } h1, h2, h3, h4 { font-weight: normal; margin-bottom:0.5em; } h1 { background:#fff; color: #003d4c; font-size: 100%; } h2 { background:#fff; color: #e32; font-family:'Gill Sans','lucida grande', helvetica, arial, sans-serif; font-size: 190%; } h3 { color: #2c6877; font-family:'Gill Sans','lucida grande', helvetica, arial, sans-serif; font-size: 165%; } h4 { color: #993; font-weight: normal; } ul, li { margin: 0 12px; } p { margin: 0 0 1em 0; } /** Layout **/ #container { text-align: left; } #header{ padding: 10px 20px; } #header h1 { line-height:20px; background: #003d4c url('../img/cake.icon.png') no-repeat left; color: #fff; padding: 0 30px; } #header h1 a { color: #fff; background: #003d4c; font-weight: normal; text-decoration: none; } #header h1 a:hover { color: #fff; background: #003d4c; text-decoration: underline; } #content{ background: #fff; clear: both; color: #333; padding: 10px 20px 40px 20px; overflow: auto; } #footer { clear: both; padding: 6px 10px; text-align: right; } #header a, #footer a { color: #fff; } /** containers **/ div.form, div.index, div.view { float:right; width:76%; border-left:1px solid #666; padding:10px 2%; } div.actions { float:left; width:16%; padding:10px 1.5%; } div.actions h3 { padding-top:0; color:#777; } /** Tables **/ table { border-right:0; clear: both; color: #333; margin-bottom: 10px; width: 100%; } th { border:0; border-bottom:2px solid #555; text-align: left; padding:4px; } th a { display: block; padding: 2px 4px; text-decoration: none; } th a.asc:after { content: ' โ‡ฃ'; } th a.desc:after { content: ' โ‡ก'; } table tr td { padding: 6px; text-align: left; vertical-align: top; border-bottom:1px solid #ddd; } table tr:nth-child(even) { background: #f9f9f9; } td.actions { text-align: center; white-space: nowrap; } table td.actions a { margin: 0 6px; padding:2px 5px; } /* SQL log */ .cake-sql-log { background: #fff; } .cake-sql-log td { padding: 4px 8px; text-align: left; font-family: Monaco, Consolas, "Courier New", monospaced; } .cake-sql-log caption { color:#fff; } /** Paging **/ .paging { background:#fff; color: #ccc; margin-top: 1em; clear:both; } .paging .current, .paging .disabled, .paging a { text-decoration: none; padding: 5px 8px; display: inline-block } .paging > span { display: inline-block; border: 1px solid #ccc; border-left: 0; } .paging > span:hover { background: #efefef; } .paging .prev { border-left: 1px solid #ccc; -moz-border-radius: 4px 0 0 4px; -webkit-border-radius: 4px 0 0 4px; border-radius: 4px 0 0 4px; } .paging .next { -moz-border-radius: 0 4px 4px 0; -webkit-border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0; } .paging .disabled { color: #ddd; } .paging .disabled:hover { background: transparent; } .paging .current { background: #efefef; color: #c73e14; } /** Scaffold View **/ dl { line-height: 2em; margin: 0em 0em; width: 60%; } dl dd:nth-child(4n+2), dl dt:nth-child(4n+1) { background: #f4f4f4; } dt { font-weight: bold; padding-left: 4px; vertical-align: top; width: 10em; } dd { margin-left: 10em; margin-top: -2em; vertical-align: top; } /** Forms **/ form { clear: both; margin-right: 20px; padding: 0; width: 95%; } fieldset { border: none; margin-bottom: 1em; padding: 16px 10px; } fieldset legend { color: #e32; font-size: 160%; font-weight: bold; } fieldset fieldset { margin-top: 0; padding: 10px 0 0; } fieldset fieldset legend { font-size: 120%; font-weight: normal; } fieldset fieldset div { clear: left; margin: 0 20px; } form div { clear: both; margin-bottom: 1em; padding: .5em; vertical-align: text-top; } form .input { color: #444; } form .required { font-weight: bold; } form .required label:after { color: #e32; content: '*'; display:inline; } form div.submit { border: 0; clear: both; margin-top: 10px; } label { display: block; font-size: 110%; margin-bottom:3px; } input, textarea { clear: both; font-size: 140%; font-family: "frutiger linotype", "lucida grande", "verdana", sans-serif; padding: 1%; width:98%; } select { clear: both; font-size: 120%; vertical-align: text-bottom; } select[multiple=multiple] { width: 100%; } option { font-size: 120%; padding: 0 3px; } input[type=checkbox] { clear: left; float: left; margin: 0 6px 7px 2px; width: auto; } div.checkbox label { display: inline; } input[type=radio] { float:left; width:auto; margin: 6px 0; padding: 0; line-height: 26px; } .radio label { margin: 0 0 6px 20px; line-height: 26px; } input[type=submit] { display: inline; font-size: 110%; width: auto; } form .submit input[type=submit] { background:#62af56; background-image: -webkit-gradient(linear, left top, left bottom, from(#76BF6B), to(#3B8230)); background-image: -webkit-linear-gradient(top, #76BF6B, #3B8230); background-image: -moz-linear-gradient(top, #76BF6B, #3B8230); border-color: #2d6324; color: #fff; text-shadow: rgba(0, 0, 0, 0.5) 0 -1px 0; padding: 8px 10px; } form .submit input[type=submit]:hover { background: #5BA150; } /* Form errors */ form .error { background: #FFDACC; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; font-weight: normal; } form .error-message { -moz-border-radius: none; -webkit-border-radius: none; border-radius: none; border: none; background: none; margin: 0; padding-left: 4px; padding-right: 0; } form .error, form .error-message { color: #9E2424; -webkit-box-shadow: none; -moz-box-shadow: none; -ms-box-shadow: none; -o-box-shadow: none; box-shadow: none; text-shadow: none; } /** Notices and Errors **/ .message { clear: both; color: #fff; font-size: 140%; font-weight: bold; margin: 0 0 1em 0; padding: 5px; } .success, .message, .cake-error, .cake-debug, .notice, p.error, .error-message { background: #ffcc00; background-repeat: repeat-x; background-image: -moz-linear-gradient(top, #ffcc00, #E6B800); background-image: -ms-linear-gradient(top, #ffcc00, #E6B800); background-image: -webkit-gradient(linear, left top, left bottom, from(#ffcc00), to(#E6B800)); background-image: -webkit-linear-gradient(top, #ffcc00, #E6B800); background-image: -o-linear-gradient(top, #ffcc00, #E6B800); background-image: linear-gradient(top, #ffcc00, #E6B800); text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25); border: 1px solid rgba(0, 0, 0, 0.2); margin-bottom: 18px; padding: 7px 14px; color: #404040; text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); } .success, .message, .cake-error, p.error, .error-message { clear: both; color: #fff; background: #c43c35; border: 1px solid rgba(0, 0, 0, 0.5); background-repeat: repeat-x; background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); background-image: -webkit-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35)); background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); background-image: linear-gradient(top, #ee5f5b, #c43c35); text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3); } .success { clear: both; color: #fff; border: 1px solid rgba(0, 0, 0, 0.5); background: #3B8230; background-repeat: repeat-x; background-image: -webkit-gradient(linear, left top, left bottom, from(#76BF6B), to(#3B8230)); background-image: -webkit-linear-gradient(top, #76BF6B, #3B8230); background-image: -moz-linear-gradient(top, #76BF6B, #3B8230); background-image: -ms-linear-gradient(top, #76BF6B, #3B8230); background-image: -o-linear-gradient(top, #76BF6B, #3B8230); background-image: linear-gradient(top, #76BF6B, #3B8230); text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.3); } p.error { font-family: Monaco, Consolas, Courier, monospace; font-size: 120%; padding: 0.8em; margin: 1em 0; } p.error em { font-weight: normal; line-height: 140%; } .notice { color: #000; display: block; font-size: 120%; padding: 0.8em; margin: 1em 0; } .success { color: #fff; } /** Actions **/ .actions ul { margin: 0; padding: 0; } .actions li { margin:0 0 0.5em 0; list-style-type: none; white-space: nowrap; padding: 0; } .actions ul li a { font-weight: normal; display: block; clear: both; } /* Buttons and button links */ input[type=submit], .actions ul li a, .actions a { font-weight:normal; padding: 4px 8px; background: #dcdcdc; background-image: -webkit-gradient(linear, left top, left bottom, from(#fefefe), to(#dcdcdc)); background-image: -webkit-linear-gradient(top, #fefefe, #dcdcdc); background-image: -moz-linear-gradient(top, #fefefe, #dcdcdc); background-image: -ms-linear-gradient(top, #fefefe, #dcdcdc); background-image: -o-linear-gradient(top, #fefefe, #dcdcdc); background-image: linear-gradient(top, #fefefe, #dcdcdc); color:#333; border:1px solid #bbb; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; text-decoration: none; text-shadow: #fff 0 1px 0; min-width: 0; -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 1px 1px rgba(0, 0, 0, 0.2); -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 1px 1px rgba(0, 0, 0, 0.2); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.3), 0 1px 1px rgba(0, 0, 0, 0.2); -webkit-user-select: none; user-select: none; } .actions ul li a:hover, .actions a:hover { background: #ededed; border-color: #acacac; text-decoration: none; } input[type=submit]:active, .actions ul li a:active, .actions a:active { background: #eee; background-image: -webkit-gradient(linear, left top, left bottom, from(#dfdfdf), to(#eee)); background-image: -webkit-linear-gradient(top, #dfdfdf, #eee); background-image: -moz-linear-gradient(top, #dfdfdf, #eee); background-image: -ms-linear-gradient(top, #dfdfdf, #eee); background-image: -o-linear-gradient(top, #dfdfdf, #eee); background-image: linear-gradient(top, #dfdfdf, #eee); text-shadow: #eee 0 1px 0; -moz-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.3); -webkit-box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.3); box-shadow: inset 0 1px 4px rgba(0, 0, 0, 0.3); border-color: #aaa; text-decoration: none; } /** Related **/ .related { clear: both; display: block; } /** Debugging **/ pre { color: #000; background: #f0f0f0; padding: 15px; -moz-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3); -webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3); box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3); } .cake-debug-output { padding: 0; position: relative; } .cake-debug-output > span { position: absolute; top: 5px; right: 5px; background: rgba(255, 255, 255, 0.3); -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; padding: 5px 6px; color: #000; display: block; float: left; -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.25), 0 1px 0 rgba(255, 255, 255, 0.5); -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.25), 0 1px 0 rgba(255, 255, 255, 0.5); box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.25), 0 1px 0 rgba(255, 255, 255, 0.5); text-shadow: 0 1px 1px rgba(255, 255, 255, 0.8); } .cake-debug, .cake-error { font-size: 16px; line-height: 20px; clear: both; } .cake-error > a { text-shadow: none; } .cake-error { white-space: normal; } .cake-stack-trace { background: rgba(255, 255, 255, 0.7); color: #333; margin: 10px 0 5px 0; padding: 10px 10px 0 10px; font-size: 120%; line-height: 140%; overflow: auto; position: relative; -moz-border-radius: 4px; -webkit-border-radius: 4px; border-radius: 4px; } .cake-stack-trace a { text-shadow: none; background: rgba(255, 255, 255, 0.7); padding: 5px; -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; margin: 0 4px 10px 2px; font-family: sans-serif; font-size: 14px; line-height: 14px; display: inline-block; text-decoration: none; -moz-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.3); -webkit-box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.3); box-shadow: inset 0 1px 0 rgba(0, 0, 0, 0.3); } .cake-code-dump pre { position: relative; overflow: auto; } .cake-context { margin-bottom: 10px; } .cake-stack-trace pre { color: #000; background-color: #F0F0F0; margin: 0 0 10px 0; padding: 1em; overflow: auto; text-shadow: none; } .cake-stack-trace li { padding: 10px 5px 0; margin: 0 0 4px 0; font-family: monospace; border: 1px solid #bbb; -moz-border-radius: 4px; -wekbkit-border-radius: 4px; border-radius: 4px; background: #dcdcdc; background-image: -webkit-gradient(linear, left top, left bottom, from(#fefefe), to(#dcdcdc)); background-image: -webkit-linear-gradient(top, #fefefe, #dcdcdc); background-image: -moz-linear-gradient(top, #fefefe, #dcdcdc); background-image: -ms-linear-gradient(top, #fefefe, #dcdcdc); background-image: -o-linear-gradient(top, #fefefe, #dcdcdc); background-image: linear-gradient(top, #fefefe, #dcdcdc); } /* excerpt */ .cake-code-dump pre, .cake-code-dump pre code { clear: both; font-size: 12px; line-height: 15px; margin: 4px 2px; padding: 4px; overflow: auto; } .cake-code-dump .code-highlight { display: block; background-color: rgba(255, 255, 0, 0.5); } .code-coverage-results div.code-line { padding-left:5px; display:block; margin-left:10px; } .code-coverage-results div.uncovered span.content { background:#ecc; } .code-coverage-results div.covered span.content { background:#cec; } .code-coverage-results div.ignored span.content { color:#aaa; } .code-coverage-results span.line-num { color:#666; display:block; float:left; width:20px; text-align:right; margin-right:5px; } .code-coverage-results span.line-num strong { color:#666; } .code-coverage-results div.start { border:1px solid #aaa; border-width:1px 1px 0 1px; margin-top:30px; padding-top:5px; } .code-coverage-results div.end { border:1px solid #aaa; border-width:0px 1px 1px 1px; margin-bottom:30px; padding-bottom:5px; } .code-coverage-results div.realstart { margin-top:0px; } .code-coverage-results p.note { color:#bbb; padding:5px; margin:5px 0 10px; font-size:10px; } .code-coverage-results span.result-bad { color: #a00; } .code-coverage-results span.result-ok { color: #fa0; } .code-coverage-results span.result-good { color: #0a0; } /** Elements **/ #url-rewriting-warning { display:none; } cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/favicon.ico000066400000000000000000000005641265552240500246600ustar00rootroot00000000000000‰PNG  IHDR DคŠฦPLTEู฿ๆaz•j€—Fa~ฅญ๑๏์โโใฺrstRNS6์ฺึ๛๘IDATxฺญ“ัย0C%!๋ฑ,t8={4๘ฒr )_U@YƒฟL$ดJ‡ต$@๗nส๑๐D`หภ฿๔™ ”^\ื“IENDฎB`‚cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/files/000077500000000000000000000000001265552240500236345ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/files/empty000066400000000000000000000000001265552240500247030ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/img/000077500000000000000000000000001265552240500233065ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/img/cake.icon.png000066400000000000000000000016571265552240500256570ustar00rootroot00000000000000‰PNG  IHDR‰ tEXtSoftwareAdobe ImageReadyqษe<QIDATxฺฌT]HSa~ถ…ๅOyิ08?๙3›‘™ป( %กAฤส!† ั)*จhBˆK&ฎะœ"^ค˜C']„n„ถะM\q๚พwุPป๒น๘็{฿๓œ็๑<ฃฤ1zˆD"แขดดิ@ืT*•.::Z'—หกP(˜maa[[[pน\ถตตตr๕bpppฦ-'b!คDฑฑฑmeee๊|ไ0P๒กก!ŒŒŒP๒‡”˜EKBึ`ฑX๘ƒ011มทดดฐ็ๆๆๆ>;ฝkjjโ G ฐถถ–onn>TMMM Qผ็/คา คฅiAฃHJJbvš“ษ4ำืื—รrH๓๔?TUUกซ๋Šฏ„’ทE,/;ั๛?–ล+4Œ<""‚ŠBsQ\\ ญV{ !ฝฯศธJ~„R)J†ิยยd!฿พูแvปYqฤ{฿ุฬๆFดถถ’ฟ/Hj415)มจm.็H$!ˆCจ2Hc˜8ป เืํ๑$!่๎๎ฤ๎ฎ‰‰Iˆ‹SAญVƒใ"ฑฒฒŠฌฌ<ฬฯโ๋ื฿ถ#=]‰ำi‰X_๗QŽ™@Bปลโ1TVๆ บบกก*ๆดธ่„รแ€ื๋eNว‘ร`H€Xฤ๛.ๆ฿Iศn&*ะนบบ‹ว฿ฃผœGIIHS#&F๖ุุฝ๓มf๓"๗)œฯMลฅ‹R<ํ์G{วs[กFlXญŸ๑ๆอ'R9=๔z=k๐๐pๆไ๓๙œ|QQax;OR3‡3ูฉXr{AฃGใIWP_ว15ๅภภภ+ ?๔z9๒๒โQXp;;'0=ํ"น฿…ั3™ฎ๓๑๑1Œฬhผ.ๅ+Vซ6ญVกฮฟฉฮสฬ y๔ขญU#ฝสๅWH๚h\Qq๙ฮ๖v$ฺŸ‘v่EQQ4 ม่“'ๆB:๛Jฅ\UเฏpBโภ%$ศ๋๊๎s2Y &'็Y•ggg…dni๘w‰sภvR“wง pฃ๎ๆอ_zzบxวฝo๔๗๗ณ%pุˆ…Lฑทr66ถ /_พvข฿~ุBtิ[Œ#ฦ?า6งRคXพyIENDฎB`‚cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/img/cake.power.gif000066400000000000000000000003111265552240500260260ustar00rootroot00000000000000GIF87ab ๑4Aภภภ,b ข”ฉหํ#ดฺ‹ณ:๘†โHއฆjVถ๎œ๋Lณ๐ห—่๕๋ษ>•ล vFE%๑‰LFI< ตwฑลฃ7๙^Hาฒว >ƒฬข*ท‚n…Aฅ๔|฿jฃ:=ุ6—Uˆต5'ถจˆAย–ฦ๖GE(gt๐ีลˆ๒y็—ว7 โV“š‚ร๚‚ช kำ:;kหA›{*ม๋๛๛[;cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/img/test-error-icon.png000066400000000000000000000064361265552240500270610ustar00rootroot00000000000000‰PNG  IHDR๓a pHYs  šœ OiCCPPhotoshop ICC profilexฺSgTS้=๗๔BKˆ€”KoR RB‹€‘&*! Jˆ!กูQมEEศ ˆŽŽ€ŒQ, Š ุไ!ขŽƒฃˆŠส๛แ{ฃkึผ๗ๆอตื>็ฌ๓ณฯภ –H3Q5€ ฉBเƒวฤฦแไ.@ $pณd!s#๘~<<+"ภพxำ ภM›ภ0‡๊B™\€„ภt‘8K€@zŽBฆ@F€˜&S `หcbใP-`'ๆำ€๘™{[”! ‘ eˆDh;ฌฯVŠEX0fKฤ9ุ-0IWfHฐทภฮ ฒ 0Qˆ…){`ศ##x„™F๒W<๑+ฎ็*x™ฒ<น$9E[-qWW.(ฮI+6aaš@.ยy™24เ๓ฬ ‘เƒ๓xฮฎฮฮ6Žถ_-๊ฟ"bbใๅฯซp@แt~ั,/ณ€;€mข%๎h^  u๗‹fฒ@ต ฺ้W๓p๘~<฿5ฐj>{‘-จ]c๖K'Xtภโ๗๒ปoมิ(€hƒแฯw๏?G %€fI’q^D$.Tสณ?วD *ฐA๔ม,ภมม `6„B$ฤยBB d€r`)ฌ‚B(†อฐ*`/ิ@4ภQh†“p.ยUธ=p๚ažม(ผ Aศa!ฺˆbŠX#Ž™…๘!มH‹$ ษˆQ"K‘5H1RŠT UH๒=r9‡\Fบ‘;ศ2‚†ผG1”ฒQ=ิ ตCนจ7„Fข ะdt1š ›ะrด=Œ6ก็ะซhฺ>Cว0ภ่3ฤl0.ฦรBฑ8, “cหฑ"ฌ ซฦฐVฌป‰๕cฯฑwEภ 6wB aAHXLXNุHจ $4ฺ 7 „Qย'"“จKด&บ๙ฤb21‡XH,#ึ/{ˆCฤ7$‰C2'นIฑคTาาFาnR#้,ฉ›4H#“ษฺdkฒ9”, +ศ…ไไรไ3ไไ!๒[ b@qค๘Sโ(RสjJๅๅ4ๅe˜2AUฃšRจกT5ZBญกถRฏQ‡จ4uš9อƒIKฅญข•ำhh๗iฏ่tบ•N—ะWาห้G่—่๔w †ƒวˆg(›gwฏ˜Lฆำ‹วT071๋˜็™™oUX*ถ*|‘ส •J•&•*/Tฉชฆชช U๓UหTฉ^S}ฎFU3Sใฉ ิ–ซUชP๋SSgฉ;จ‡ชgจoT?ค~Y‰YรLรOCคQ ฑ_ใผฦ cณx,!k ซ†u5ฤ&ฑอู|v*ป˜ป‹=ชฉก9C3J3WณR๓”f?ใ˜q๘œtN ็(ง—๓~Š๏)โ)ฆ4Lน1e\kช–—–XซHซQซG๋ฝ6ฎํงฆฝEปY๛AวJ'\'Ggฮ็SูSง งM=:๕ฎ.ชkฅกปDwฟnง๎˜žพ^€žLoงyฝ็๚}/Tm๚ง๕G Xณ $ ฮ<ล5qo</ว๑QC]ร@Cฅa•a—แ„‘นั<ฃีFFŒiฦ\ใ$ใmฦmฦฃ&&!&KM๊M๎šRMนฆ)ฆ;L;Lวอฬอขอึ™5›=1ื2็›็›ื›฿ท`ZxZ,ถจถธeIฒไZฆY๎ถผn…Z9YฅXUZ]ณFญญ%ึปญปงงนN“Nซžึgรฐ๑ถษถฉทฐๅุฎถmถ}agbgทลฎร๎“ฝ“}บ}= ‡ูซZ~sดr:V:šฮœ๎?}ล๔–้/gXฯฯุ3ใถห)ฤiS›ำGggนsƒ๓ˆ‹‰K‚ห.—>.›ฦศฝไJt๕q]แzา๕›ณ›ยํจฏ๎6๎i๎‡Ÿฬ4Ÿ)žY3sะรศCเQๅั? Ÿ•0k฿ฌ~OCOgต็#/c/‘Wญืฐทฅwช๗a๏>๖>rŸใ>ใ<72Y_ฬ7ภทศทหOรož_…฿C#dzัง€%g‰A[๛๘z|!ฟŽ?:e๖ฒูํAŒ นAA‚ญ‚ๅมญ!hศ์ญ!๗็˜ฮ‘ฮi…P~่ึะaๆa‹ร~ '…‡…W†?ŽpˆXั1—5wัCs฿D๚D–D›g1O9ฏ-J5*>ช.j<ฺ7บ4บ?ฦ.fYฬีXXIlK9.*ฎ6nlพ฿ํ๓‡โโ ใ{˜/ศ]pyกฮย๔…งฉ.,:–@LˆN8”๐A*จŒ%๒w%Ž yยยg"/ั6ัˆุC\*N๒H*Mz’์‘ผ5y$ล3ฅ,ๅน„'ฉผL L›:žšv m2=:ฝ1ƒ’‘qBช!M“ถg๊gๆfvหฌe…ฒลn‹ท/•ษkณฌY- ถBฆ่TZ(ื*ฒgeWfฟอ‰ส9–ซž+อํฬณส7œ๏Ÿํยแ’ถฅ†KW-Xๆฝฌj9ฒ‰Šฎ—ุ(xๅ‡oสฟ™”ดฉซฤนdฯfาf้ๆ-ž[–ช—ๆ—n ฺูด ฿Vดํ๕๖E/—อ(ปƒถCนฃฟ<ธผeงษฮอ;?TคT๔T๚T6๎าตaื๘nั๎{ผ๖4์ี[ผ๗>ษพUUMีfีe๛I๛ณ๗?ฎ‰ช้๘–๛m]ญNmqํวา#ถืนิีา=TRึ+๋Gวพ๏w- 6 Uœฦโ#pDyไ้๗ ฿๗ :ฺvŒ{ฌแำvg/jBš๒šF›Sš๛[b[บOฬ>ัึ๊zGœ499โ?r้งCฯdฯ&žขหฎ/~๘ี๋ืฮั˜ัก—๒—“ฟm|ฅ๊ภ๋ฏฦยฦพษx31^๔V๛ํมww๏ฃ฿Oไ| (h๙ฑ๕Sะง๛“““˜๓c3- cHRMz%€ƒ๙€้u0๊`:˜o’_ลFIIDATxฺŒ“AkAล;ณูธm–B›CึMlดุ^ฤR๑dฟ@=V๔ ๛z๒ึc/ฝˆwฤxRฐH % )ถ ฅMุ์ฬฮŽ7hkลsyy๏?๓f€ต๖๗ํ๕?N๕ส๛ๆ้ึตคปๅ๒Ÿ‚@|zy๛CฝqผโV๏XูwK฿ล๛็%วqๆwwweน\ถkOึLฝqผ<๗Š }ว>ผ•8oœ ยM`#ŸฯW…c(‹,?Xๆฎ๗s๓{{{Fฃq=๑ขๆ™ฬเฐQ,ืซี*“““c888`๕๑*aR[ง\.ำnท้๕zาqyvvฆณ 6*•ส๚พ๏#ฅฤC†„aH<ŠวโJฅา=<รแ๐ฏโแp˜งฟ‹/bุBX฿๗ํฤฤ„๕}฿ !,ฐ๓ซ~ ?๒L%X€“;:IENDฎB`‚cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/img/test-fail-icon.png000066400000000000000000000007601265552240500266350ustar00rootroot00000000000000‰PNG  IHDR(-StEXtSoftwareAdobe ImageReadyqษe<ฅPLTEำฟลษ๘„นืฯจไชXเฒฺ์์33โญฃํํ๐๐ั๒rึU,66โˆF๎ฬjเณ ฬW-เ ๅใชXร)าิฝ แใไะอุ 00ฬย๓๎{หใีแึ –D•7tRNSY‹žIDATxฺLฯว‚0ะQ‚5ค7ฑ๗^๒Ÿfvแเปฬ์ฦ๕šฒฒ์ฝu>ŠUA0bnฃT๊6ฑr!rสงยw@ค’ห -ธผ \ึ8:$M’”KŒGŸE›4ืฟ=—lไbษศ0ถ๊ปจ)3" ฿๗+)+ยุล๋8:ค็B๑V:โoia™ฝอO€Š ๋๑ใIENDฎB`‚cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/img/test-pass-icon.png000066400000000000000000000014171265552240500266700ustar00rootroot00000000000000‰PNG  IHDR(-StEXtSoftwareAdobe ImageReadyqษe<>PLTE€฿๏฿Pนน8œ8‡OrนrsนsN † ˆ]Mt…„qธq’a๙๙|\ฎ\vnทn … XolŽQ † ~`p^VqkYทท<š<ƒZฉZsฑัฑQคQุ็ุ ` ‘klT … Œี่ีฬไฬrรรІุุ่Uฦเฦ5š5W$n$_ธธtS\ทัทRœผœ‚s „ 3t3“K›K™ม™{f˜fzZญZE•ETฆT๙๛๙u88oทo–น– o a W‰ณl…ณjtRNSผไใ๑IDATxฺ$ฯUnAะุeF3s˜ั;ฬฬLs ฤ^๗Wฉฅ’๊œ ‹•สง0ฬภ9QฎaฺuฝZ† $เm—J๋nž ‡‰ ~บ› ฃภ็0žm=ใ6จ้xjลษ_mภXช้0cฯ`>fอฮƒn่๐jฃrZfถยF ๑|„บW๛!vJ^wฺxožิˆŽt์๛ํื[tP‘ฑบ๚…ฺ๚>ฬ—)–Aะ:}|;[ฬ๏PkS€+xLฅ7ฟ็eษ AIฆใข%ITU"#œVuL35%ม๘Œ‰rย`h’(?ัbำIENDฎB`‚cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/img/test-skip-icon.png000066400000000000000000000022671265552240500266740ustar00rootroot00000000000000‰PNG  IHDR(-StEXtSoftwareAdobe ImageReadyqษe<PLTEiz”(P๖๗๙5XGo ?eุใQ|Mx,U'n +xช'P+S฿ๅl}– >d`อุแZ‡)rฃ#f˜Z‰1bˆU‚/V+QHlyนJnFnAhOz6zจ#hš1r AlŒ๙๚๛$j›T~๓๔๖+T2X\‹Bƒฏพีๅ+g”Is\‰[”นลึโP|Qx•Yˆ'O*S&O,xช#h™,xซ+vฉƒฐอ'Q/U<|งX†*Q0W‰ฃท"Z„ b“+wฉ%kœ&\†ถฬ6k“3vฅ(qฃ"`ŽZ†_Žt“ซ}จล^Žๆ๏๔|คภFog/f ๓ุฑ4ฤ–๙„ี;ŸOงƒ‹3?euสpง~ปฎKงzยƒt๕v?็z‰๒xเหว๋๓kฺToด0เDfฟ(q5 ‹VOรn,่ jwจ4็[8ƒ8l๚ณ ขย+%kวwkŽQ‘*+๔่x& ผr~:๓Lซสค‘:ห๒‘”กn^ฬ›"ๅบMmฎnŠbตuหธ-`ท'ภ+|<'ป]฿ฎIENDฎB`‚cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/index.php000066400000000000000000000067671265552240500243720ustar00rootroot00000000000000dispatch( new CakeRequest(), new CakeResponse() ); cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/js/000077500000000000000000000000001265552240500231465ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/js/empty000066400000000000000000000000001265552240500242150ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Console/Templates/skel/webroot/test.php000066400000000000000000000055561265552240500242350ustar00rootroot00000000000000 /dev/null && pwd -P)/$(basename -- "$NAME") fi while [ -h "$NAME" ]; do DIR=$(dirname -- "$NAME") SYM=$(readlink "$NAME") NAME=$(cd "$DIR" > /dev/null && cd $(dirname -- "$SYM") > /dev/null && pwd)/$(basename -- "$SYM") done echo "$NAME" } CONSOLE=$(dirname -- "$(canonicalize "$0")") APP=`pwd` exec php -q "$CONSOLE"/cake.php -working "$APP" "$@" exit cakephp-2.8.0/lib/Cake/Console/cake.bat000066400000000000000000000016301265552240500175500ustar00rootroot00000000000000:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: Bake is a shell script for running CakePHP bake script :: :: CakePHP(tm) : Rapid Development Framework (http://cakephp.org) :: Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) :: :: Licensed under The MIT License :: Redistributions of files must retain the above copyright notice. :: :: @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) :: @link http://cakephp.org CakePHP(tm) Project :: @package Cake.Console :: @since CakePHP(tm) v 1.2.0.5012 :: @license http://www.opensource.org/licenses/mit-license.php MIT License :: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: @echo off SET app=%0 SET lib=%~dp0 php -q "%lib%cake.php" -working "%CD% " %* echo. exit /B %ERRORLEVEL% cakephp-2.8.0/lib/Cake/Console/cake.php000066400000000000000000000030601265552240500175700ustar00rootroot00000000000000#!/usr/bin/php -q constructClasses(); if (count(Router::extensions()) && !$this->Components->attached('RequestHandler') ) { $this->RequestHandler = $this->Components->load('RequestHandler'); } if ($this->Components->enabled('Auth')) { $this->Components->disable('Auth'); } if ($this->Components->enabled('Security')) { $this->Components->disable('Security'); } $this->_set(array('cacheAction' => false, 'viewPath' => 'Errors')); } } cakephp-2.8.0/lib/Cake/Controller/Component.php000066400000000000000000000125451265552240500213600ustar00rootroot00000000000000_Collection = $collection; $this->settings = $settings; $this->_set($settings); if (!empty($this->components)) { $this->_componentMap = ComponentCollection::normalizeObjectArray($this->components); } } /** * Magic method for lazy loading $components. * * @param string $name Name of component to get. * @return mixed A Component object or null. */ public function __get($name) { if (isset($this->_componentMap[$name]) && !isset($this->{$name})) { $settings = array('enabled' => false) + (array)$this->_componentMap[$name]['settings']; $this->{$name} = $this->_Collection->load($this->_componentMap[$name]['class'], $settings); } if (isset($this->{$name})) { return $this->{$name}; } } /** * Called before the Controller::beforeFilter(). * * @param Controller $controller Controller with components to initialize * @return void * @link http://book.cakephp.org/2.0/en/controllers/components.html#Component::initialize */ public function initialize(Controller $controller) { } /** * Called after the Controller::beforeFilter() and before the controller action * * @param Controller $controller Controller with components to startup * @return void * @link http://book.cakephp.org/2.0/en/controllers/components.html#Component::startup */ public function startup(Controller $controller) { } /** * Called before the Controller::beforeRender(), and before * the view class is loaded, and before Controller::render() * * @param Controller $controller Controller with components to beforeRender * @return void * @link http://book.cakephp.org/2.0/en/controllers/components.html#Component::beforeRender */ public function beforeRender(Controller $controller) { } /** * Called after Controller::render() and before the output is printed to the browser. * * @param Controller $controller Controller with components to shutdown * @return void * @link http://book.cakephp.org/2.0/en/controllers/components.html#Component::shutdown */ public function shutdown(Controller $controller) { } /** * Called before Controller::redirect(). Allows you to replace the URL that will * be redirected to with a new URL. The return of this method can either be an array or a string. * * If the return is an array and contains a 'url' key. You may also supply the following: * * - `status` The status code for the redirect * - `exit` Whether or not the redirect should exit. * * If your response is a string or an array that does not contain a 'url' key it will * be used as the new URL to redirect to. * * @param Controller $controller Controller with components to beforeRedirect * @param string|array $url Either the string or URL array that is being redirected to. * @param int $status The status code of the redirect * @param bool $exit Will the script exit. * @return array|null Either an array or null. * @link http://book.cakephp.org/2.0/en/controllers/components.html#Component::beforeRedirect */ public function beforeRedirect(Controller $controller, $url, $status = null, $exit = true) { } } cakephp-2.8.0/lib/Cake/Controller/Component/000077500000000000000000000000001265552240500206405ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Controller/Component/Acl/000077500000000000000000000000001265552240500213375ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Controller/Component/Acl/AclInterface.php000066400000000000000000000044431265552240500243750ustar00rootroot00000000000000Permission = ClassRegistry::init(array('class' => 'Permission', 'alias' => 'Permission')); $this->Aro = $this->Permission->Aro; $this->Aco = $this->Permission->Aco; } /** * Initializes the containing component and sets the Aro/Aco objects to it. * * @param AclComponent $component The AclComponent instance. * @return void */ public function initialize(Component $component) { $component->Aro = $this->Aro; $component->Aco = $this->Aco; } /** * Checks if the given $aro has access to action $action in $aco * * @param string $aro ARO The requesting object identifier. * @param string $aco ACO The controlled object identifier. * @param string $action Action (defaults to *) * @return bool Success (true if ARO has access to action in ACO, false otherwise) * @link http://book.cakephp.org/2.0/en/core-libraries/components/access-control-lists.html#checking-permissions-the-acl-component */ public function check($aro, $aco, $action = "*") { return $this->Permission->check($aro, $aco, $action); } /** * Allow $aro to have access to action $actions in $aco * * @param string $aro ARO The requesting object identifier. * @param string $aco ACO The controlled object identifier. * @param string $actions Action (defaults to *) * @param int $value Value to indicate access type (1 to give access, -1 to deny, 0 to inherit) * @return bool Success * @link http://book.cakephp.org/2.0/en/core-libraries/components/access-control-lists.html#assigning-permissions */ public function allow($aro, $aco, $actions = "*", $value = 1) { return $this->Permission->allow($aro, $aco, $actions, $value); } /** * Deny access for $aro to action $action in $aco * * @param string $aro ARO The requesting object identifier. * @param string $aco ACO The controlled object identifier. * @param string $action Action (defaults to *) * @return bool Success * @link http://book.cakephp.org/2.0/en/core-libraries/components/access-control-lists.html#assigning-permissions */ public function deny($aro, $aco, $action = "*") { return $this->allow($aro, $aco, $action, -1); } /** * Let access for $aro to action $action in $aco be inherited * * @param string $aro ARO The requesting object identifier. * @param string $aco ACO The controlled object identifier. * @param string $action Action (defaults to *) * @return bool Success */ public function inherit($aro, $aco, $action = "*") { return $this->allow($aro, $aco, $action, 0); } /** * Allow $aro to have access to action $actions in $aco * * @param string $aro ARO The requesting object identifier. * @param string $aco ACO The controlled object identifier. * @param string $action Action (defaults to *) * @return bool Success * @see allow() */ public function grant($aro, $aco, $action = "*") { return $this->allow($aro, $aco, $action); } /** * Deny access for $aro to action $action in $aco * * @param string $aro ARO The requesting object identifier. * @param string $aco ACO The controlled object identifier. * @param string $action Action (defaults to *) * @return bool Success * @see deny() */ public function revoke($aro, $aco, $action = "*") { return $this->deny($aro, $aco, $action); } /** * Get an array of access-control links between the given Aro and Aco * * @param string $aro ARO The requesting object identifier. * @param string $aco ACO The controlled object identifier. * @return array Indexed array with: 'aro', 'aco' and 'link' */ public function getAclLink($aro, $aco) { return $this->Permission->getAclLink($aro, $aco); } /** * Get the keys used in an ACO * * @param array $keys Permission model info * @return array ACO keys */ protected function _getAcoKeys($keys) { return $this->Permission->getAcoKeys($keys); } } cakephp-2.8.0/lib/Cake/Controller/Component/Acl/IniAcl.php000066400000000000000000000112041265552240500232050ustar00rootroot00000000000000config) { $this->config = $this->readConfigFile(APP . 'Config' . DS . 'acl.ini.php'); } $aclConfig = $this->config; if (is_array($aro)) { $aro = Hash::get($aro, $this->userPath); } if (isset($aclConfig[$aro]['deny'])) { $userDenies = $this->arrayTrim(explode(",", $aclConfig[$aro]['deny'])); if (array_search($aco, $userDenies)) { return false; } } if (isset($aclConfig[$aro]['allow'])) { $userAllows = $this->arrayTrim(explode(",", $aclConfig[$aro]['allow'])); if (array_search($aco, $userAllows)) { return true; } } if (isset($aclConfig[$aro]['groups'])) { $userGroups = $this->arrayTrim(explode(",", $aclConfig[$aro]['groups'])); foreach ($userGroups as $group) { if (array_key_exists($group, $aclConfig)) { if (isset($aclConfig[$group]['deny'])) { $groupDenies = $this->arrayTrim(explode(",", $aclConfig[$group]['deny'])); if (array_search($aco, $groupDenies)) { return false; } } if (isset($aclConfig[$group]['allow'])) { $groupAllows = $this->arrayTrim(explode(",", $aclConfig[$group]['allow'])); if (array_search($aco, $groupAllows)) { return true; } } } } } return false; } /** * Parses an INI file and returns an array that reflects the * INI file's section structure. Double-quote friendly. * * @param string $filename File * @return array INI section structure */ public function readConfigFile($filename) { App::uses('IniReader', 'Configure'); $iniFile = new IniReader(dirname($filename) . DS); return $iniFile->read(basename($filename)); } /** * Removes trailing spaces on all array elements (to prepare for searching) * * @param array $array Array to trim * @return array Trimmed array */ public function arrayTrim($array) { foreach ($array as $key => $value) { $array[$key] = trim($value); } array_unshift($array, ""); return $array; } } cakephp-2.8.0/lib/Cake/Controller/Component/Acl/PhpAcl.php000066400000000000000000000327251265552240500232300ustar00rootroot00000000000000options = array( 'policy' => static::DENY, 'config' => APP . 'Config' . DS . 'acl.php', ); } /** * Initialize method * * @param AclComponent $Component Component instance * @return void */ public function initialize(Component $Component) { if (!empty($Component->settings['adapter'])) { $this->options = $Component->settings['adapter'] + $this->options; } App::uses('PhpReader', 'Configure'); $Reader = new PhpReader(dirname($this->options['config']) . DS); $config = $Reader->read(basename($this->options['config'])); $this->build($config); $Component->Aco = $this->Aco; $Component->Aro = $this->Aro; } /** * build and setup internal ACL representation * * @param array $config configuration array, see docs * @return void * @throws AclException When required keys are missing. */ public function build(array $config) { if (empty($config['roles'])) { throw new AclException(__d('cake_dev', '"roles" section not found in configuration.')); } if (empty($config['rules']['allow']) && empty($config['rules']['deny'])) { throw new AclException(__d('cake_dev', 'Neither "allow" nor "deny" rules were provided in configuration.')); } $rules['allow'] = !empty($config['rules']['allow']) ? $config['rules']['allow'] : array(); $rules['deny'] = !empty($config['rules']['deny']) ? $config['rules']['deny'] : array(); $roles = !empty($config['roles']) ? $config['roles'] : array(); $map = !empty($config['map']) ? $config['map'] : array(); $alias = !empty($config['alias']) ? $config['alias'] : array(); $this->Aro = new PhpAro($roles, $map, $alias); $this->Aco = new PhpAco($rules); } /** * No op method, allow cannot be done with PhpAcl * * @param string $aro ARO The requesting object identifier. * @param string $aco ACO The controlled object identifier. * @param string $action Action (defaults to *) * @return bool Success */ public function allow($aro, $aco, $action = "*") { return $this->Aco->access($this->Aro->resolve($aro), $aco, $action, 'allow'); } /** * deny ARO access to ACO * * @param string $aro ARO The requesting object identifier. * @param string $aco ACO The controlled object identifier. * @param string $action Action (defaults to *) * @return bool Success */ public function deny($aro, $aco, $action = "*") { return $this->Aco->access($this->Aro->resolve($aro), $aco, $action, 'deny'); } /** * No op method * * @param string $aro ARO The requesting object identifier. * @param string $aco ACO The controlled object identifier. * @param string $action Action (defaults to *) * @return bool Success */ public function inherit($aro, $aco, $action = "*") { return false; } /** * Main ACL check function. Checks to see if the ARO (access request object) has access to the * ACO (access control object). * * @param string $aro ARO * @param string $aco ACO * @param string $action Action * @return bool true if access is granted, false otherwise */ public function check($aro, $aco, $action = "*") { $allow = $this->options['policy']; $prioritizedAros = $this->Aro->roles($aro); if ($action && $action !== "*") { $aco .= '/' . $action; } $path = $this->Aco->path($aco); if (empty($path)) { return $allow; } foreach ($path as $node) { foreach ($prioritizedAros as $aros) { if (!empty($node['allow'])) { $allow = $allow || count(array_intersect($node['allow'], $aros)); } if (!empty($node['deny'])) { $allow = $allow && !count(array_intersect($node['deny'], $aros)); } } } return $allow; } } /** * Access Control Object */ class PhpAco { /** * holds internal ACO representation * * @var array */ protected $_tree = array(); /** * map modifiers for ACO paths to their respective PCRE pattern * * @var array */ public static $modifiers = array( '*' => '.*', ); /** * Constructor * * @param array $rules Rules array */ public function __construct(array $rules = array()) { foreach (array('allow', 'deny') as $type) { if (empty($rules[$type])) { $rules[$type] = array(); } } $this->build($rules['allow'], $rules['deny']); } /** * return path to the requested ACO with allow and deny rules attached on each level * * @param string $aco ACO string * @return array */ public function path($aco) { $aco = $this->resolve($aco); $path = array(); $level = 0; $root = $this->_tree; $stack = array(array($root, 0)); while (!empty($stack)) { list($root, $level) = array_pop($stack); if (empty($path[$level])) { $path[$level] = array(); } foreach ($root as $node => $elements) { $pattern = '/^' . str_replace(array_keys(static::$modifiers), array_values(static::$modifiers), $node) . '$/'; if ($node == $aco[$level] || preg_match($pattern, $aco[$level])) { // merge allow/denies with $path of current level foreach (array('allow', 'deny') as $policy) { if (!empty($elements[$policy])) { if (empty($path[$level][$policy])) { $path[$level][$policy] = array(); } $path[$level][$policy] = array_merge($path[$level][$policy], $elements[$policy]); } } // traverse if (!empty($elements['children']) && isset($aco[$level + 1])) { array_push($stack, array($elements['children'], $level + 1)); } } } } return $path; } /** * allow/deny ARO access to ARO * * @param string $aro ARO string * @param string $aco ACO string * @param string $action Action string * @param string $type access type * @return void */ public function access($aro, $aco, $action, $type = 'deny') { $aco = $this->resolve($aco); $depth = count($aco); $root = $this->_tree; $tree = &$root; foreach ($aco as $i => $node) { if (!isset($tree[$node])) { $tree[$node] = array( 'children' => array(), ); } if ($i < $depth - 1) { $tree = &$tree[$node]['children']; } else { if (empty($tree[$node][$type])) { $tree[$node][$type] = array(); } $tree[$node][$type] = array_merge(is_array($aro) ? $aro : array($aro), $tree[$node][$type]); } } $this->_tree = &$root; } /** * resolve given ACO string to a path * * @param string $aco ACO string * @return array path */ public function resolve($aco) { if (is_array($aco)) { return array_map('strtolower', $aco); } // strip multiple occurrences of '/' $aco = preg_replace('#/+#', '/', $aco); // make case insensitive $aco = ltrim(strtolower($aco), '/'); return array_filter(array_map('trim', explode('/', $aco))); } /** * build a tree representation from the given allow/deny informations for ACO paths * * @param array $allow ACO allow rules * @param array $deny ACO deny rules * @return void */ public function build(array $allow, array $deny = array()) { $this->_tree = array(); foreach ($allow as $dotPath => $aros) { if (is_string($aros)) { $aros = array_map('trim', explode(',', $aros)); } $this->access($aros, $dotPath, null, 'allow'); } foreach ($deny as $dotPath => $aros) { if (is_string($aros)) { $aros = array_map('trim', explode(',', $aros)); } $this->access($aros, $dotPath, null, 'deny'); } } } /** * Access Request Object */ class PhpAro { /** * role to resolve to when a provided ARO is not listed in * the internal tree * * @var string */ const DEFAULT_ROLE = 'Role/default'; /** * map external identifiers. E.g. if * * array('User' => array('username' => 'jeff', 'role' => 'editor')) * * is passed as an ARO to one of the methods of AclComponent, PhpAcl * will check if it can be resolved to an User or a Role defined in the * configuration file. * * @var array * @see app/Config/acl.php */ public $map = array( 'User' => 'User/username', 'Role' => 'User/role', ); /** * aliases to map * * @var array */ public $aliases = array(); /** * internal ARO representation * * @var array */ protected $_tree = array(); /** * Constructor * * @param array $aro The aro data * @param array $map The identifier mappings * @param array $aliases The aliases to map. */ public function __construct(array $aro = array(), array $map = array(), array $aliases = array()) { if (!empty($map)) { $this->map = $map; } $this->aliases = $aliases; $this->build($aro); } /** * From the perspective of the given ARO, walk down the tree and * collect all inherited AROs levelwise such that AROs from different * branches with equal distance to the requested ARO will be collected at the same * index. The resulting array will contain a prioritized list of (list of) roles ordered from * the most distant AROs to the requested one itself. * * @param string|array $aro An ARO identifier * @return array prioritized AROs */ public function roles($aro) { $aros = array(); $aro = $this->resolve($aro); $stack = array(array($aro, 0)); while (!empty($stack)) { list($element, $depth) = array_pop($stack); $aros[$depth][] = $element; foreach ($this->_tree as $node => $children) { if (in_array($element, $children)) { array_push($stack, array($node, $depth + 1)); } } } return array_reverse($aros); } /** * resolve an ARO identifier to an internal ARO string using * the internal mapping information. * * @param string|array $aro ARO identifier (User.jeff, array('User' => ...), etc) * @return string internal aro string (e.g. User/jeff, Role/default) */ public function resolve($aro) { foreach ($this->map as $aroGroup => $map) { list ($model, $field) = explode('/', $map, 2); $mapped = ''; if (is_array($aro)) { if (isset($aro['model']) && isset($aro['foreign_key']) && $aro['model'] === $aroGroup) { $mapped = $aroGroup . '/' . $aro['foreign_key']; } elseif (isset($aro[$model][$field])) { $mapped = $aroGroup . '/' . $aro[$model][$field]; } elseif (isset($aro[$field])) { $mapped = $aroGroup . '/' . $aro[$field]; } } elseif (is_string($aro)) { $aro = ltrim($aro, '/'); if (strpos($aro, '/') === false) { $mapped = $aroGroup . '/' . $aro; } else { list($aroModel, $aroValue) = explode('/', $aro, 2); $aroModel = Inflector::camelize($aroModel); if ($aroModel === $model || $aroModel === $aroGroup) { $mapped = $aroGroup . '/' . $aroValue; } } } if (isset($this->_tree[$mapped])) { return $mapped; } // is there a matching alias defined (e.g. Role/1 => Role/admin)? if (!empty($this->aliases[$mapped])) { return $this->aliases[$mapped]; } } return static::DEFAULT_ROLE; } /** * adds a new ARO to the tree * * @param array $aro one or more ARO records * @return void */ public function addRole(array $aro) { foreach ($aro as $role => $inheritedRoles) { if (!isset($this->_tree[$role])) { $this->_tree[$role] = array(); } if (!empty($inheritedRoles)) { if (is_string($inheritedRoles)) { $inheritedRoles = array_map('trim', explode(',', $inheritedRoles)); } foreach ($inheritedRoles as $dependency) { // detect cycles $roles = $this->roles($dependency); if (in_array($role, Hash::flatten($roles))) { $path = ''; foreach ($roles as $roleDependencies) { $path .= implode('|', (array)$roleDependencies) . ' -> '; } trigger_error(__d('cake_dev', 'cycle detected when inheriting %s from %s. Path: %s', $role, $dependency, $path . $role)); continue; } if (!isset($this->_tree[$dependency])) { $this->_tree[$dependency] = array(); } $this->_tree[$dependency][] = $role; } } } } /** * adds one or more aliases to the internal map. Overwrites existing entries. * * @param array $alias alias from => to (e.g. Role/13 -> Role/editor) * @return void */ public function addAlias(array $alias) { $this->aliases = $alias + $this->aliases; } /** * build an ARO tree structure for internal processing * * @param array $aros array of AROs as key and their inherited AROs as values * @return void */ public function build(array $aros) { $this->_tree = array(); $this->addRole($aros); } } cakephp-2.8.0/lib/Cake/Controller/Component/AclComponent.php000066400000000000000000000150141265552240500237340ustar00rootroot00000000000000adapter($name); } /** * Sets or gets the Adapter object currently in the AclComponent. * * `$this->Acl->adapter();` will get the current adapter class while * `$this->Acl->adapter($obj);` will set the adapter class * * Will call the initialize method on the adapter if setting a new one. * * @param AclInterface|string $adapter Instance of AclInterface or a string name of the class to use. (optional) * @return AclInterface|null Either null, or the adapter implementation. * @throws CakeException when the given class is not an instance of AclInterface */ public function adapter($adapter = null) { if ($adapter) { if (is_string($adapter)) { $adapter = new $adapter(); } if (!$adapter instanceof AclInterface) { throw new CakeException(__d('cake_dev', 'AclComponent adapters must implement AclInterface')); } $this->_Instance = $adapter; $this->_Instance->initialize($this); return null; } return $this->_Instance; } /** * Pass-thru function for ACL check instance. Check methods * are used to check whether or not an ARO can access an ACO * * @param array|string|Model $aro ARO The requesting object identifier. See `AclNode::node()` for possible formats * @param array|string|Model $aco ACO The controlled object identifier. See `AclNode::node()` for possible formats * @param string $action Action (defaults to *) * @return bool Success */ public function check($aro, $aco, $action = "*") { return $this->_Instance->check($aro, $aco, $action); } /** * Pass-thru function for ACL allow instance. Allow methods * are used to grant an ARO access to an ACO. * * @param array|string|Model $aro ARO The requesting object identifier. See `AclNode::node()` for possible formats * @param array|string|Model $aco ACO The controlled object identifier. See `AclNode::node()` for possible formats * @param string $action Action (defaults to *) * @return bool Success */ public function allow($aro, $aco, $action = "*") { return $this->_Instance->allow($aro, $aco, $action); } /** * Pass-thru function for ACL deny instance. Deny methods * are used to remove permission from an ARO to access an ACO. * * @param array|string|Model $aro ARO The requesting object identifier. See `AclNode::node()` for possible formats * @param array|string|Model $aco ACO The controlled object identifier. See `AclNode::node()` for possible formats * @param string $action Action (defaults to *) * @return bool Success */ public function deny($aro, $aco, $action = "*") { return $this->_Instance->deny($aro, $aco, $action); } /** * Pass-thru function for ACL inherit instance. Inherit methods * modify the permission for an ARO to be that of its parent object. * * @param array|string|Model $aro ARO The requesting object identifier. See `AclNode::node()` for possible formats * @param array|string|Model $aco ACO The controlled object identifier. See `AclNode::node()` for possible formats * @param string $action Action (defaults to *) * @return bool Success */ public function inherit($aro, $aco, $action = "*") { return $this->_Instance->inherit($aro, $aco, $action); } /** * Pass-thru function for ACL grant instance. An alias for AclComponent::allow() * * @param array|string|Model $aro ARO The requesting object identifier. See `AclNode::node()` for possible formats * @param array|string|Model $aco ACO The controlled object identifier. See `AclNode::node()` for possible formats * @param string $action Action (defaults to *) * @return bool Success * @deprecated 3.0.0 Will be removed in 3.0. */ public function grant($aro, $aco, $action = "*") { trigger_error(__d('cake_dev', '%s is deprecated, use %s instead', 'AclComponent::grant()', 'allow()'), E_USER_WARNING); return $this->_Instance->allow($aro, $aco, $action); } /** * Pass-thru function for ACL grant instance. An alias for AclComponent::deny() * * @param array|string|Model $aro ARO The requesting object identifier. See `AclNode::node()` for possible formats * @param array|string|Model $aco ACO The controlled object identifier. See `AclNode::node()` for possible formats * @param string $action Action (defaults to *) * @return bool Success * @deprecated 3.0.0 Will be removed in 3.0. */ public function revoke($aro, $aco, $action = "*") { trigger_error(__d('cake_dev', '%s is deprecated, use %s instead', 'AclComponent::revoke()', 'deny()'), E_USER_WARNING); return $this->_Instance->deny($aro, $aco, $action); } } cakephp-2.8.0/lib/Cake/Controller/Component/Auth/000077500000000000000000000000001265552240500215415ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Controller/Component/Auth/AbstractPasswordHasher.php000066400000000000000000000036711265552240500267020ustar00rootroot00000000000000config($config); } /** * Get/Set the config * * @param array $config Sets config, if null returns existing config * @return array Returns configs */ public function config($config = null) { if (is_array($config)) { $this->_config = array_merge($this->_config, $config); } return $this->_config; } /** * Generates password hash. * * @param string|array $password Plain text password to hash or array of data * required to generate password hash. * @return string Password hash */ abstract public function hash($password); /** * Check hash. Generate hash from user provided password string or data array * and check against existing hash. * * @param string|array $password Plain text password to hash or data array. * @param string $hashedPassword Existing hashed password. * @return bool True if hashes match else false. */ abstract public function check($password, $hashedPassword); } cakephp-2.8.0/lib/Cake/Controller/Component/Auth/ActionsAuthorize.php000066400000000000000000000026141265552240500255500ustar00rootroot00000000000000_Collection->load('Acl'); $user = array($this->settings['userModel'] => $user); return $Acl->check($user, $this->action($request)); } } cakephp-2.8.0/lib/Cake/Controller/Component/Auth/BaseAuthenticate.php000066400000000000000000000164061265552240500254720ustar00rootroot00000000000000 1).` * - `recursive` The value of the recursive key passed to find(). Defaults to 0. * - `contain` Extra models to contain and store in session. * - `passwordHasher` Password hasher class. Can be a string specifying class name * or an array containing `className` key, any other keys will be passed as * settings to the class. Defaults to 'Simple'. * * @var array */ public $settings = array( 'fields' => array( 'username' => 'username', 'password' => 'password' ), 'userModel' => 'User', 'userFields' => null, 'scope' => array(), 'recursive' => 0, 'contain' => null, 'passwordHasher' => 'Simple' ); /** * A Component collection, used to get more components. * * @var ComponentCollection */ protected $_Collection; /** * Password hasher instance. * * @var AbstractPasswordHasher */ protected $_passwordHasher; /** * Implemented events * * @return array of events => callbacks. */ public function implementedEvents() { return array(); } /** * Constructor * * @param ComponentCollection $collection The Component collection used on this request. * @param array $settings Array of settings to use. */ public function __construct(ComponentCollection $collection, $settings) { $this->_Collection = $collection; $this->settings = Hash::merge($this->settings, $settings); } /** * Find a user record using the standard options. * * The $username parameter can be a (string)username or an array containing * conditions for Model::find('first'). If the $password param is not provided * the password field will be present in returned array. * * Input passwords will be hashed even when a user doesn't exist. This * helps mitigate timing attacks that are attempting to find valid usernames. * * @param string|array $username The username/identifier, or an array of find conditions. * @param string $password The password, only used if $username param is string. * @return bool|array Either false on failure, or an array of user data. */ protected function _findUser($username, $password = null) { $userModel = $this->settings['userModel']; list(, $model) = pluginSplit($userModel); $fields = $this->settings['fields']; if (is_array($username)) { $conditions = $username; } else { $conditions = array( $model . '.' . $fields['username'] => $username ); } if (!empty($this->settings['scope'])) { $conditions = array_merge($conditions, $this->settings['scope']); } $userFields = $this->settings['userFields']; if ($password !== null && $userFields !== null) { $userFields[] = $model . '.' . $fields['password']; } $result = ClassRegistry::init($userModel)->find('first', array( 'conditions' => $conditions, 'recursive' => $this->settings['recursive'], 'fields' => $userFields, 'contain' => $this->settings['contain'], )); if (empty($result[$model])) { $this->passwordHasher()->hash($password); return false; } $user = $result[$model]; if ($password !== null) { if (!$this->passwordHasher()->check($password, $user[$fields['password']])) { return false; } unset($user[$fields['password']]); } unset($result[$model]); return array_merge($user, $result); } /** * Return password hasher object * * @return AbstractPasswordHasher Password hasher instance * @throws CakeException If password hasher class not found or * it does not extend AbstractPasswordHasher */ public function passwordHasher() { if ($this->_passwordHasher) { return $this->_passwordHasher; } $config = array(); if (is_string($this->settings['passwordHasher'])) { $class = $this->settings['passwordHasher']; } else { $class = $this->settings['passwordHasher']['className']; $config = $this->settings['passwordHasher']; unset($config['className']); } list($plugin, $class) = pluginSplit($class, true); $className = $class . 'PasswordHasher'; App::uses($className, $plugin . 'Controller/Component/Auth'); if (!class_exists($className)) { throw new CakeException(__d('cake_dev', 'Password hasher class "%s" was not found.', $class)); } if (!is_subclass_of($className, 'AbstractPasswordHasher')) { throw new CakeException(__d('cake_dev', 'Password hasher must extend AbstractPasswordHasher class.')); } $this->_passwordHasher = new $className($config); return $this->_passwordHasher; } /** * Hash the plain text password so that it matches the hashed/encrypted password * in the datasource. * * @param string $password The plain text password. * @return string The hashed form of the password. * @deprecated 3.0.0 Since 2.4. Use a PasswordHasher class instead. */ protected function _password($password) { return Security::hash($password, null, true); } /** * Authenticate a user based on the request information. * * @param CakeRequest $request Request to get authentication information from. * @param CakeResponse $response A response object that can have headers added. * @return mixed Either false on failure, or an array of user data on success. */ abstract public function authenticate(CakeRequest $request, CakeResponse $response); /** * Allows you to hook into AuthComponent::logout(), * and implement specialized logout behavior. * * All attached authentication objects will have this method * called when a user logs out. * * @param array $user The user about to be logged out. * @return void */ public function logout($user) { } /** * Get a user based on information in the request. Primarily used by stateless authentication * systems like basic and digest auth. * * @param CakeRequest $request Request object. * @return mixed Either false or an array of user information */ public function getUser(CakeRequest $request) { return false; } /** * Handle unauthenticated access attempt. * * @param CakeRequest $request A request object. * @param CakeResponse $response A response object. * @return mixed Either true to indicate the unauthenticated request has been * dealt with and no more action is required by AuthComponent or void (default). */ public function unauthenticated(CakeRequest $request, CakeResponse $response) { } } cakephp-2.8.0/lib/Cake/Controller/Component/Auth/BaseAuthorize.php000066400000000000000000000117341265552240500250250ustar00rootroot00000000000000action(); * - `actionMap` - Action -> crud mappings. Used by authorization objects that want to map actions to CRUD roles. * - `userModel` - Model name that ARO records can be found under. Defaults to 'User'. * * @var array */ public $settings = array( 'actionPath' => null, 'actionMap' => array( 'index' => 'read', 'add' => 'create', 'edit' => 'update', 'view' => 'read', 'delete' => 'delete', 'remove' => 'delete' ), 'userModel' => 'User' ); /** * Constructor * * @param ComponentCollection $collection The controller for this request. * @param string $settings An array of settings. This class does not use any settings. */ public function __construct(ComponentCollection $collection, $settings = array()) { $this->_Collection = $collection; $controller = $collection->getController(); $this->controller($controller); $this->settings = Hash::merge($this->settings, $settings); } /** * Checks user authorization. * * @param array $user Active user data * @param CakeRequest $request Request instance. * @return bool */ abstract public function authorize($user, CakeRequest $request); /** * Accessor to the controller object. * * @param Controller $controller null to get, a controller to set. * @return mixed * @throws CakeException */ public function controller(Controller $controller = null) { if ($controller) { if (!$controller instanceof Controller) { throw new CakeException(__d('cake_dev', '$controller needs to be an instance of Controller')); } $this->_Controller = $controller; return true; } return $this->_Controller; } /** * Get the action path for a given request. Primarily used by authorize objects * that need to get information about the plugin, controller, and action being invoked. * * @param CakeRequest $request The request a path is needed for. * @param string $path Path format. * @return string the action path for the given request. */ public function action(CakeRequest $request, $path = '/:plugin/:controller/:action') { $plugin = empty($request['plugin']) ? null : Inflector::camelize($request['plugin']) . '/'; $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, '/'); } /** * Maps crud actions to actual action names. Used to modify or get the current mapped actions. * * Create additional mappings for a standard CRUD operation: * * ``` * $this->Auth->mapActions(array('create' => array('add', 'register')); * ``` * * Or equivalently: * * ``` * $this->Auth->mapActions(array('register' => 'create', 'add' => 'create')); * ``` * * Create mappings for custom CRUD operations: * * ``` * $this->Auth->mapActions(array('range' => 'search')); * ``` * * You can use the custom CRUD operations to create additional generic permissions * that behave like CRUD operations. Doing this will require additional columns on the * permissions lookup. For example if one wanted an additional search CRUD operation * one would create and additional column '_search' in the aros_acos table. One could * create a custom admin CRUD operation for administration functions similarly if needed. * * @param array $map Either an array of mappings, or undefined to get current values. * @return mixed Either the current mappings or null when setting. * @see AuthComponent::mapActions() */ public function mapActions($map = array()) { if (empty($map)) { return $this->settings['actionMap']; } foreach ($map as $action => $type) { if (is_array($type)) { foreach ($type as $typedAction) { $this->settings['actionMap'][$typedAction] = $action; } } else { $this->settings['actionMap'][$action] = $type; } } } } cakephp-2.8.0/lib/Cake/Controller/Component/Auth/BasicAuthenticate.php000066400000000000000000000077311265552240500256420ustar00rootroot00000000000000 array( * 'authenticate' => array('Basic') * ) * ); * ``` * * You should also set `AuthComponent::$sessionKey = false;` in your AppController's * beforeFilter() to prevent CakePHP from sending a session cookie to the client. * * Since HTTP Basic Authentication is stateless you don't need a login() action * in your controller. The user credentials will be checked on each request. If * valid credentials are not provided, required authentication headers will be sent * by this authentication provider which triggers the login dialog in the browser/client. * * You may also want to use `$this->Auth->unauthorizedRedirect = false;`. * By default, unauthorized users are redirected to the referrer URL, * `AuthComponent::$loginAction`, or '/'. If unauthorizedRedirect is set to * false, a ForbiddenException exception is thrown instead of redirecting. * * @package Cake.Controller.Component.Auth * @since 2.0 */ class BasicAuthenticate extends BaseAuthenticate { /** * Constructor, completes configuration for basic authentication. * * @param ComponentCollection $collection The Component collection used on this request. * @param array $settings An array of settings. */ public function __construct(ComponentCollection $collection, $settings) { parent::__construct($collection, $settings); if (empty($this->settings['realm'])) { $this->settings['realm'] = env('SERVER_NAME'); } } /** * Authenticate a user using HTTP auth. Will use the configured User model and attempt a * login using HTTP auth. * * @param CakeRequest $request The request to authenticate with. * @param CakeResponse $response The response to add headers to. * @return mixed Either false on failure, or an array of user data on success. */ public function authenticate(CakeRequest $request, CakeResponse $response) { return $this->getUser($request); } /** * Get a user based on information in the request. Used by cookie-less auth for stateless clients. * * @param CakeRequest $request Request object. * @return mixed Either false or an array of user information */ public function getUser(CakeRequest $request) { $username = env('PHP_AUTH_USER'); $pass = env('PHP_AUTH_PW'); if (!is_string($username) || $username === '' || !is_string($pass) || $pass === '') { return false; } return $this->_findUser($username, $pass); } /** * Handles an unauthenticated access attempt by sending appropriate login headers * * @param CakeRequest $request A request object. * @param CakeResponse $response A response object. * @return void * @throws UnauthorizedException */ public function unauthenticated(CakeRequest $request, CakeResponse $response) { $Exception = new UnauthorizedException(); $Exception->responseHeader(array($this->loginHeaders())); throw $Exception; } /** * Generate the login headers * * @return string Headers for logging in. */ public function loginHeaders() { return sprintf('WWW-Authenticate: Basic realm="%s"', $this->settings['realm']); } } cakephp-2.8.0/lib/Cake/Controller/Component/Auth/BlowfishAuthenticate.php000066400000000000000000000037551265552240500264000ustar00rootroot00000000000000Auth->authenticate = array( * 'Blowfish' => array( * 'scope' => array('User.active' => 1) * ) * ) * ``` * * When configuring BlowfishAuthenticate you can pass in settings to which fields, model and additional conditions * are used. See FormAuthenticate::$settings for more information. * * For initial password hashing/creation see Security::hash(). Other than how the password is initially hashed, * BlowfishAuthenticate works exactly the same way as FormAuthenticate. * * @package Cake.Controller.Component.Auth * @since CakePHP(tm) v 2.3 * @see AuthComponent::$authenticate * @deprecated 3.0.0 Since 2.4. Just use FormAuthenticate with 'passwordHasher' setting set to 'Blowfish' */ class BlowfishAuthenticate extends FormAuthenticate { /** * Constructor. Sets default passwordHasher to Blowfish * * @param ComponentCollection $collection The Component collection used on this request. * @param array $settings Array of settings to use. */ public function __construct(ComponentCollection $collection, $settings) { $this->settings['passwordHasher'] = 'Blowfish'; parent::__construct($collection, $settings); } } cakephp-2.8.0/lib/Cake/Controller/Component/Auth/BlowfishPasswordHasher.php000066400000000000000000000031101265552240500267000ustar00rootroot00000000000000request->params['admin'])) { * return $user['role'] === 'admin'; * } * return !empty($user); * } * ``` * * the above is simple implementation that would only authorize users of the 'admin' role to access * admin routing. * * @package Cake.Controller.Component.Auth * @since 2.0 * @see AuthComponent::$authenticate */ class ControllerAuthorize extends BaseAuthorize { /** * Get/set the controller this authorize object will be working with. Also checks that isAuthorized is implemented. * * @param Controller $controller null to get, a controller to set. * @return mixed * @throws CakeException */ public function controller(Controller $controller = null) { if ($controller) { if (!method_exists($controller, 'isAuthorized')) { throw new CakeException(__d('cake_dev', '$controller does not implement an %s method.', 'isAuthorized()')); } } return parent::controller($controller); } /** * Checks user authorization using a controller callback. * * @param array $user Active user data * @param CakeRequest $request Request instance. * @return bool */ public function authorize($user, CakeRequest $request) { return (bool)$this->_Controller->isAuthorized($user); } } cakephp-2.8.0/lib/Cake/Controller/Component/Auth/CrudAuthorize.php000066400000000000000000000065761265552240500250600ustar00rootroot00000000000000_setPrefixMappings(); } /** * sets the crud mappings for prefix routes. * * @return void */ protected function _setPrefixMappings() { $crud = array('create', 'read', 'update', 'delete'); $map = array_combine($crud, $crud); $prefixes = Router::prefixes(); if (!empty($prefixes)) { foreach ($prefixes as $prefix) { $map = array_merge($map, array( $prefix . '_index' => 'read', $prefix . '_add' => 'create', $prefix . '_edit' => 'update', $prefix . '_view' => 'read', $prefix . '_remove' => 'delete', $prefix . '_create' => 'create', $prefix . '_read' => 'read', $prefix . '_update' => 'update', $prefix . '_delete' => 'delete' )); } } $this->mapActions($map); } /** * Authorize a user using the mapped actions and the AclComponent. * * @param array $user The user to authorize * @param CakeRequest $request The request needing authorization. * @return bool */ public function authorize($user, CakeRequest $request) { if (!isset($this->settings['actionMap'][$request->params['action']])) { trigger_error(__d('cake_dev', 'CrudAuthorize::authorize() - Attempted access of un-mapped action "%1$s" in controller "%2$s"', $request->action, $request->controller ), E_USER_WARNING ); return false; } $user = array($this->settings['userModel'] => $user); $Acl = $this->_Collection->load('Acl'); return $Acl->check( $user, $this->action($request, ':controller'), $this->settings['actionMap'][$request->params['action']] ); } } cakephp-2.8.0/lib/Cake/Controller/Component/Auth/DigestAuthenticate.php000066400000000000000000000171351265552240500260370ustar00rootroot00000000000000 array( * 'authenticate' => array('Digest') * ) * ); * ``` * * In your login function just call `$this->Auth->login()` without any checks for POST data. This * will send the authentication headers, and trigger the login dialog in the browser/client. * * ### Generating passwords compatible with Digest authentication. * * Due to the Digest authentication specification, digest auth requires a special password value. You * can generate this password using `DigestAuthenticate::password()` * * `$digestPass = DigestAuthenticate::password($username, env('SERVER_NAME'), $password);` * * Its recommended that you store this digest auth only password separate from password hashes used for other * login methods. For example `User.digest_pass` could be used for a digest password, while `User.password` would * store the password hash for use with other methods like Basic or Form. * * @package Cake.Controller.Component.Auth * @since 2.0 */ class DigestAuthenticate extends BasicAuthenticate { /** * Settings for this object. * * - `fields` The fields to use to identify a user by. * - `userModel` The model name of the User, defaults to User. * - `userFields` Array of fields to retrieve from User model, null to retrieve all. Defaults to null. * - `scope` Additional conditions to use when looking up and authenticating users, * i.e. `array('User.is_active' => 1).` * - `recursive` The value of the recursive key passed to find(). Defaults to 0. * - `contain` Extra models to contain and store in session. * - `realm` The realm authentication is for, Defaults to the servername. * - `nonce` A nonce used for authentication. Defaults to `uniqid()`. * - `qop` Defaults to auth, no other values are supported at this time. * - `opaque` A string that must be returned unchanged by clients. * Defaults to `md5($settings['realm'])` * * @var array */ public $settings = array( 'fields' => array( 'username' => 'username', 'password' => 'password' ), 'userModel' => 'User', 'userFields' => null, 'scope' => array(), 'recursive' => 0, 'contain' => null, 'realm' => '', 'qop' => 'auth', 'nonce' => '', 'opaque' => '', 'passwordHasher' => 'Simple', ); /** * Constructor, completes configuration for digest authentication. * * @param ComponentCollection $collection The Component collection used on this request. * @param array $settings An array of settings. */ public function __construct(ComponentCollection $collection, $settings) { parent::__construct($collection, $settings); if (empty($this->settings['nonce'])) { $this->settings['nonce'] = uniqid(''); } if (empty($this->settings['opaque'])) { $this->settings['opaque'] = md5($this->settings['realm']); } } /** * Get a user based on information in the request. Used by cookie-less auth for stateless clients. * * @param CakeRequest $request Request object. * @return mixed Either false or an array of user information */ public function getUser(CakeRequest $request) { $digest = $this->_getDigest(); if (empty($digest)) { return false; } list(, $model) = pluginSplit($this->settings['userModel']); $user = $this->_findUser(array( $model . '.' . $this->settings['fields']['username'] => $digest['username'] )); if (empty($user)) { return false; } $password = $user[$this->settings['fields']['password']]; unset($user[$this->settings['fields']['password']]); if ($digest['response'] === $this->generateResponseHash($digest, $password)) { return $user; } return false; } /** * Gets the digest headers from the request/environment. * * @return array Array of digest information. */ protected function _getDigest() { $digest = env('PHP_AUTH_DIGEST'); if (empty($digest) && function_exists('apache_request_headers')) { $headers = apache_request_headers(); if (!empty($headers['Authorization']) && substr($headers['Authorization'], 0, 7) === 'Digest ') { $digest = substr($headers['Authorization'], 7); } } if (empty($digest)) { return false; } return $this->parseAuthData($digest); } /** * Parse the digest authentication headers and split them up. * * @param string $digest The raw digest authentication headers. * @return array|null An array of digest authentication headers */ public function parseAuthData($digest) { if (substr($digest, 0, 7) === 'Digest ') { $digest = substr($digest, 7); } $keys = $match = array(); $req = array('nonce' => 1, 'nc' => 1, 'cnonce' => 1, 'qop' => 1, 'username' => 1, 'uri' => 1, 'response' => 1); preg_match_all('/(\w+)=([\'"]?)([a-zA-Z0-9\:\#\%\?\&@=\.\/_-]+)\2/', $digest, $match, PREG_SET_ORDER); foreach ($match as $i) { $keys[$i[1]] = $i[3]; unset($req[$i[1]]); } if (empty($req)) { return $keys; } return null; } /** * Generate the response hash for a given digest array. * * @param array $digest Digest information containing data from DigestAuthenticate::parseAuthData(). * @param string $password The digest hash password generated with DigestAuthenticate::password() * @return string Response hash */ public function generateResponseHash($digest, $password) { return md5( $password . ':' . $digest['nonce'] . ':' . $digest['nc'] . ':' . $digest['cnonce'] . ':' . $digest['qop'] . ':' . md5(env('REQUEST_METHOD') . ':' . $digest['uri']) ); } /** * Creates an auth digest password hash to store * * @param string $username The username to use in the digest hash. * @param string $password The unhashed password to make a digest hash for. * @param string $realm The realm the password is for. * @return string the hashed password that can later be used with Digest authentication. */ public static function password($username, $password, $realm) { return md5($username . ':' . $realm . ':' . $password); } /** * Generate the login headers * * @return string Headers for logging in. */ public function loginHeaders() { $options = array( 'realm' => $this->settings['realm'], 'qop' => $this->settings['qop'], 'nonce' => $this->settings['nonce'], 'opaque' => $this->settings['opaque'] ); $opts = array(); foreach ($options as $k => $v) { $opts[] = sprintf('%s="%s"', $k, $v); } return 'WWW-Authenticate: Digest ' . implode(',', $opts); } } cakephp-2.8.0/lib/Cake/Controller/Component/Auth/FormAuthenticate.php000066400000000000000000000056321265552240500255220ustar00rootroot00000000000000Auth->authenticate = array( * 'Form' => array( * 'scope' => array('User.active' => 1) * ) * ) * ``` * * When configuring FormAuthenticate you can pass in settings to which fields, model and additional conditions * are used. See FormAuthenticate::$settings for more information. * * @package Cake.Controller.Component.Auth * @since 2.0 * @see AuthComponent::$authenticate */ class FormAuthenticate extends BaseAuthenticate { /** * Checks the fields to ensure they are supplied. * * @param CakeRequest $request The request that contains login information. * @param string $model The model used for login verification. * @param array $fields The fields to be checked. * @return bool False if the fields have not been supplied. True if they exist. */ protected function _checkFields(CakeRequest $request, $model, $fields) { if (empty($request->data[$model])) { return false; } foreach (array($fields['username'], $fields['password']) as $field) { $value = $request->data($model . '.' . $field); if (empty($value) && $value !== '0' || !is_string($value)) { return false; } } return true; } /** * Authenticates the identity contained in a request. Will use the `settings.userModel`, and `settings.fields` * to find POST data that is used to find a matching record in the `settings.userModel`. Will return false if * there is no post data, either username or password is missing, or if the scope conditions have not been met. * * @param CakeRequest $request The request that contains login information. * @param CakeResponse $response Unused response object. * @return mixed False on login failure. An array of User data on success. */ public function authenticate(CakeRequest $request, CakeResponse $response) { $userModel = $this->settings['userModel']; list(, $model) = pluginSplit($userModel); $fields = $this->settings['fields']; if (!$this->_checkFields($request, $model, $fields)) { return false; } return $this->_findUser( $request->data[$model][$fields['username']], $request->data[$model][$fields['password']] ); } } cakephp-2.8.0/lib/Cake/Controller/Component/Auth/SimplePasswordHasher.php000066400000000000000000000032201265552240500263560ustar00rootroot00000000000000 null); /** * Generates password hash. * * @param string $password Plain text password to hash. * @return string Password hash * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#hashing-passwords */ public function hash($password) { return Security::hash($password, $this->_config['hashType'], true); } /** * Check hash. Generate hash for user provided password and check against existing hash. * * @param string $password Plain text password to hash. * @param string $hashedPassword Existing hashed password. * @return bool True if hashes match else false. */ public function check($password, $hashedPassword) { return $hashedPassword === $this->hash($password); } } cakephp-2.8.0/lib/Cake/Controller/Component/AuthComponent.php000066400000000000000000000625561265552240500241530ustar00rootroot00000000000000Auth->authenticate = array( * 'Form' => array( * 'userModel' => 'Users.User' * ) * ); * ``` * * Using the class name without 'Authenticate' as the key, you can pass in an array of settings for each * authentication object. Additionally you can define settings that should be set to all authentications objects * using the 'all' key: * * ``` * $this->Auth->authenticate = array( * 'all' => array( * 'userModel' => 'Users.User', * 'scope' => array('User.active' => 1) * ), * 'Form', * 'Basic' * ); * ``` * * You can also use AuthComponent::ALL instead of the string 'all'. * * @var array * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html */ public $authenticate = array('Form'); /** * Objects that will be used for authentication checks. * * @var BaseAuthenticate[] */ protected $_authenticateObjects = array(); /** * An array of authorization objects to use for authorizing users. You can configure * multiple adapters and they will be checked sequentially when authorization checks are done. * * ``` * $this->Auth->authorize = array( * 'Crud' => array( * 'actionPath' => 'controllers/' * ) * ); * ``` * * Using the class name without 'Authorize' as the key, you can pass in an array of settings for each * authorization object. Additionally you can define settings that should be set to all authorization objects * using the 'all' key: * * ``` * $this->Auth->authorize = array( * 'all' => array( * 'actionPath' => 'controllers/' * ), * 'Crud', * 'CustomAuth' * ); * ``` * * You can also use AuthComponent::ALL instead of the string 'all' * * @var mixed * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#authorization */ public $authorize = false; /** * Objects that will be used for authorization checks. * * @var BaseAuthorize[] */ protected $_authorizeObjects = array(); /** * The name of an optional view element to render when an Ajax request is made * with an invalid or expired session * * @var string */ public $ajaxLogin = null; /** * Settings to use when Auth needs to do a flash message with SessionComponent::setFlash(). * Available keys are: * * - `element` - The element to use, defaults to 'default'. * - `key` - The key to use, defaults to 'auth' * - `params` - The array of additional params to use, defaults to array() * * @var array */ public $flash = array( 'element' => 'default', 'key' => 'auth', 'params' => array() ); /** * The session key name where the record of the current user is stored. Default * key is "Auth.User". If you are using only stateless authenticators set this * to false to ensure session is not started. * * @var string */ public static $sessionKey = 'Auth.User'; /** * The current user, used for stateless authentication when * sessions are not available. * * @var array */ protected static $_user = array(); /** * A URL (defined as a string or array) to the controller action that handles * logins. Defaults to `/users/login`. * * @var mixed */ public $loginAction = array( 'controller' => 'users', 'action' => 'login', 'plugin' => null ); /** * Normally, if a user is redirected to the $loginAction page, the location they * were redirected from will be stored in the session so that they can be * redirected back after a successful login. If this session value is not * set, redirectUrl() method will return the URL specified in $loginRedirect. * * @var mixed * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#AuthComponent::$loginRedirect */ public $loginRedirect = null; /** * The default action to redirect to after the user is logged out. While AuthComponent does * not handle post-logout redirection, a redirect URL will be returned from AuthComponent::logout(). * Defaults to AuthComponent::$loginAction. * * @var mixed * @see AuthComponent::$loginAction * @see AuthComponent::logout() */ public $logoutRedirect = null; /** * Error to display when user attempts to access an object or action to which they do not have * access. * * @var string|bool * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#AuthComponent::$authError */ public $authError = null; /** * Controls handling of unauthorized access. * - For default value `true` unauthorized user is redirected to the referrer URL * or AuthComponent::$loginRedirect or '/'. * - If set to a string or array the value is used as a URL to redirect to. * - If set to false a ForbiddenException exception is thrown instead of redirecting. * * @var mixed */ public $unauthorizedRedirect = true; /** * Controller actions for which user validation is not required. * * @var array * @see AuthComponent::allow() */ public $allowedActions = array(); /** * Request object * * @var CakeRequest */ public $request; /** * Response object * * @var CakeResponse */ public $response; /** * Method list for bound controller. * * @var array */ protected $_methods = array(); /** * Initializes AuthComponent for use in the controller. * * @param Controller $controller A reference to the instantiating controller object * @return void */ public function initialize(Controller $controller) { $this->request = $controller->request; $this->response = $controller->response; $this->_methods = $controller->methods; if (Configure::read('debug') > 0) { Debugger::checkSecurityKeys(); } } /** * Main execution method. Handles redirecting of invalid users, and processing * of login form data. * * @param Controller $controller A reference to the instantiating controller object * @return bool */ public function startup(Controller $controller) { $methods = array_flip(array_map('strtolower', $controller->methods)); $action = strtolower($controller->request->params['action']); $isMissingAction = ( $controller->scaffold === false && !isset($methods[$action]) ); if ($isMissingAction) { return true; } if (!$this->_setDefaults()) { return false; } if ($this->_isAllowed($controller)) { return true; } if (!$this->_getUser()) { return $this->_unauthenticated($controller); } if ($this->_isLoginAction($controller) || empty($this->authorize) || $this->isAuthorized($this->user()) ) { return true; } return $this->_unauthorized($controller); } /** * Checks whether current action is accessible without authentication. * * @param Controller $controller A reference to the instantiating controller object * @return bool True if action is accessible without authentication else false */ protected function _isAllowed(Controller $controller) { $action = strtolower($controller->request->params['action']); if (in_array($action, array_map('strtolower', $this->allowedActions))) { return true; } return false; } /** * Handles unauthenticated access attempt. First the `unathenticated()` method * of the last authenticator in the chain will be called. The authenticator can * handle sending response or redirection as appropriate and return `true` to * indicate no furthur action is necessary. If authenticator returns null this * method redirects user to login action. If it's an ajax request and * $ajaxLogin is specified that element is rendered else a 403 http status code * is returned. * * @param Controller $controller A reference to the controller object. * @return bool True if current action is login action else false. */ protected function _unauthenticated(Controller $controller) { if (empty($this->_authenticateObjects)) { $this->constructAuthenticate(); } $auth = $this->_authenticateObjects[count($this->_authenticateObjects) - 1]; if ($auth->unauthenticated($this->request, $this->response)) { return false; } if ($this->_isLoginAction($controller)) { if (empty($controller->request->data)) { if (!$this->Session->check('Auth.redirect') && env('HTTP_REFERER')) { $this->Session->write('Auth.redirect', $controller->referer(null, true)); } } return true; } if (!$controller->request->is('ajax')) { $this->flash($this->authError); $this->Session->write('Auth.redirect', $controller->request->here(false)); $controller->redirect($this->loginAction); return false; } if (!empty($this->ajaxLogin)) { $controller->response->statusCode(403); $controller->viewPath = 'Elements'; $response = $controller->render($this->ajaxLogin, $this->RequestHandler->ajaxLayout); $response->send(); $this->_stop(); return false; } $controller->response->statusCode(403); $controller->response->send(); $this->_stop(); return false; } /** * Normalizes $loginAction and checks if current request URL is same as login action. * * @param Controller $controller A reference to the controller object. * @return bool True if current action is login action else false. */ protected function _isLoginAction(Controller $controller) { $url = ''; if (isset($controller->request->url)) { $url = $controller->request->url; } $url = Router::normalize($url); $loginAction = Router::normalize($this->loginAction); return $loginAction === $url; } /** * Handle unauthorized access attempt * * @param Controller $controller A reference to the controller object * @return bool Returns false * @throws ForbiddenException * @see AuthComponent::$unauthorizedRedirect */ protected function _unauthorized(Controller $controller) { if ($this->unauthorizedRedirect === false) { throw new ForbiddenException($this->authError); } $this->flash($this->authError); if ($this->unauthorizedRedirect === true) { $default = '/'; if (!empty($this->loginRedirect)) { $default = $this->loginRedirect; } $url = $controller->referer($default, true); } else { $url = $this->unauthorizedRedirect; } $controller->redirect($url); return false; } /** * Attempts to introspect the correct values for object properties. * * @return bool True */ protected function _setDefaults() { $defaults = array( 'logoutRedirect' => $this->loginAction, 'authError' => __d('cake', 'You are not authorized to access that location.') ); foreach ($defaults as $key => $value) { if (!isset($this->{$key}) || $this->{$key} === true) { $this->{$key} = $value; } } return true; } /** * Check if the provided user is authorized for the request. * * Uses the configured Authorization adapters to check whether or not a user is authorized. * Each adapter will be checked in sequence, if any of them return true, then the user will * be authorized for the request. * * @param array|null $user The user to check the authorization of. If empty the user in the session will be used. * @param CakeRequest|null $request The request to authenticate for. If empty, the current request will be used. * @return bool True if $user is authorized, otherwise false */ public function isAuthorized($user = null, CakeRequest $request = null) { if (empty($user) && !$this->user()) { return false; } if (empty($user)) { $user = $this->user(); } if (empty($request)) { $request = $this->request; } if (empty($this->_authorizeObjects)) { $this->constructAuthorize(); } foreach ($this->_authorizeObjects as $authorizer) { if ($authorizer->authorize($user, $request) === true) { return true; } } return false; } /** * Loads the authorization objects configured. * * @return mixed Either null when authorize is empty, or the loaded authorization objects. * @throws CakeException */ public function constructAuthorize() { if (empty($this->authorize)) { return null; } $this->_authorizeObjects = array(); $config = Hash::normalize((array)$this->authorize); $global = array(); if (isset($config[AuthComponent::ALL])) { $global = $config[AuthComponent::ALL]; unset($config[AuthComponent::ALL]); } foreach ($config as $class => $settings) { list($plugin, $class) = pluginSplit($class, true); $className = $class . 'Authorize'; App::uses($className, $plugin . 'Controller/Component/Auth'); if (!class_exists($className)) { throw new CakeException(__d('cake_dev', 'Authorization adapter "%s" was not found.', $class)); } if (!method_exists($className, 'authorize')) { throw new CakeException(__d('cake_dev', 'Authorization objects must implement an %s method.', 'authorize()')); } $settings = array_merge($global, (array)$settings); $this->_authorizeObjects[] = new $className($this->_Collection, $settings); } return $this->_authorizeObjects; } /** * Takes a list of actions in the current controller for which authentication is not required, or * no parameters to allow all actions. * * You can use allow with either an array, or var args. * * `$this->Auth->allow(array('edit', 'add'));` or * `$this->Auth->allow('edit', 'add');` or * `$this->Auth->allow();` to allow all actions * * @param string|array|null $action Controller action name or array of actions * @return void * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#making-actions-public */ public function allow($action = null) { $args = func_get_args(); if (empty($args) || $action === null) { $this->allowedActions = $this->_methods; return; } if (isset($args[0]) && is_array($args[0])) { $args = $args[0]; } $this->allowedActions = array_merge($this->allowedActions, $args); } /** * Removes items from the list of allowed/no authentication required actions. * * You can use deny with either an array, or var args. * * `$this->Auth->deny(array('edit', 'add'));` or * `$this->Auth->deny('edit', 'add');` or * `$this->Auth->deny();` to remove all items from the allowed list * * @param string|array|null $action Controller action name or array of actions * @return void * @see AuthComponent::allow() * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#making-actions-require-authorization */ public function deny($action = null) { $args = func_get_args(); if (empty($args) || $action === null) { $this->allowedActions = array(); return; } if (isset($args[0]) && is_array($args[0])) { $args = $args[0]; } foreach ($args as $arg) { $i = array_search($arg, $this->allowedActions); if (is_int($i)) { unset($this->allowedActions[$i]); } } $this->allowedActions = array_values($this->allowedActions); } /** * Maps action names to CRUD operations. * * Used for controller-based authentication. Make sure * to configure the authorize property before calling this method. As it delegates $map to all the * attached authorize objects. * * @param array $map Actions to map * @return array * @see BaseAuthorize::mapActions() * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#mapping-actions-when-using-crudauthorize * @deprecated 3.0.0 Map actions using `actionMap` config key on authorize objects instead */ public function mapActions($map = array()) { if (empty($this->_authorizeObjects)) { $this->constructAuthorize(); } $mappedActions = array(); foreach ($this->_authorizeObjects as $auth) { $mappedActions = Hash::merge($mappedActions, $auth->mapActions($map)); } if (empty($map)) { return $mappedActions; } return array(); } /** * Log a user in. * * If a $user is provided that data will be stored as the logged in user. If `$user` is empty or not * specified, the request will be used to identify a user. If the identification was successful, * the user record is written to the session key specified in AuthComponent::$sessionKey. Logging in * will also change the session id in order to help mitigate session replays. * * @param array|null $user Either an array of user data, or null to identify a user using the current request. * @return bool True on login success, false on failure * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#identifying-users-and-logging-them-in */ public function login($user = null) { $this->_setDefaults(); if (empty($user)) { $user = $this->identify($this->request, $this->response); } if ($user) { $this->Session->renew(); $this->Session->write(static::$sessionKey, $user); $event = new CakeEvent('Auth.afterIdentify', $this, array('user' => $user)); $this->_Collection->getController()->getEventManager()->dispatch($event); } return (bool)$this->user(); } /** * Log a user out. * * Returns the logout action to redirect to. Triggers the logout() method of * all the authenticate objects, so they can perform custom logout logic. * AuthComponent will remove the session data, so there is no need to do that * in an authentication object. Logging out will also renew the session id. * This helps mitigate issues with session replays. * * @return string AuthComponent::$logoutRedirect * @see AuthComponent::$logoutRedirect * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#logging-users-out */ public function logout() { $this->_setDefaults(); if (empty($this->_authenticateObjects)) { $this->constructAuthenticate(); } $user = $this->user(); foreach ($this->_authenticateObjects as $auth) { $auth->logout($user); } $this->Session->delete(static::$sessionKey); $this->Session->delete('Auth.redirect'); $this->Session->renew(); return Router::normalize($this->logoutRedirect); } /** * Get the current user. * * Will prefer the static user cache over sessions. The static user * cache is primarily used for stateless authentication. For stateful authentication, * cookies + sessions will be used. * * @param string|null $key field to retrieve. Leave null to get entire User record * @return array|null User record. or null if no user is logged in. * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#accessing-the-logged-in-user */ public static function user($key = null) { if (!empty(static::$_user)) { $user = static::$_user; } elseif (static::$sessionKey && CakeSession::check(static::$sessionKey)) { $user = CakeSession::read(static::$sessionKey); } else { return null; } if ($key === null) { return $user; } return Hash::get($user, $key); } /** * Similar to AuthComponent::user() except if the session user cannot be found, connected authentication * objects will have their getUser() methods called. This lets stateless authentication methods function correctly. * * @return bool True if a user can be found, false if one cannot. */ protected function _getUser() { $user = $this->user(); if ($user) { $this->Session->delete('Auth.redirect'); return true; } if (empty($this->_authenticateObjects)) { $this->constructAuthenticate(); } foreach ($this->_authenticateObjects as $auth) { $result = $auth->getUser($this->request); if (!empty($result) && is_array($result)) { static::$_user = $result; return true; } } return false; } /** * Backwards compatible alias for AuthComponent::redirectUrl(). * * @param string|array|null $url Optional URL to write as the login redirect URL. * @return string Redirect URL * @deprecated 3.0.0 Since 2.3.0, use AuthComponent::redirectUrl() instead */ public function redirect($url = null) { return $this->redirectUrl($url); } /** * Get the URL a user should be redirected to upon login. * * Pass a URL in to set the destination a user should be redirected to upon * logging in. * * If no parameter is passed, gets the authentication redirect URL. The URL * returned is as per following rules: * * - Returns the normalized URL from session Auth.redirect value if it is * present and for the same domain the current app is running on. * - If there is no session value and there is a $loginRedirect, the $loginRedirect * value is returned. * - If there is no session and no $loginRedirect, / is returned. * * @param string|array|null $url Optional URL to write as the login redirect URL. * @return string Redirect URL */ public function redirectUrl($url = null) { if ($url !== null) { $redir = $url; $this->Session->write('Auth.redirect', $redir); } elseif ($this->Session->check('Auth.redirect')) { $redir = $this->Session->read('Auth.redirect'); $this->Session->delete('Auth.redirect'); if (Router::normalize($redir) === Router::normalize($this->loginAction)) { $redir = $this->loginRedirect; } } elseif ($this->loginRedirect) { $redir = $this->loginRedirect; } else { $redir = '/'; } if (is_array($redir)) { return Router::url($redir + array('base' => false)); } return $redir; } /** * Use the configured authentication adapters, and attempt to identify the user * by credentials contained in $request. * * @param CakeRequest $request The request that contains authentication data. * @param CakeResponse $response The response * @return array User record data, or false, if the user could not be identified. */ public function identify(CakeRequest $request, CakeResponse $response) { if (empty($this->_authenticateObjects)) { $this->constructAuthenticate(); } foreach ($this->_authenticateObjects as $auth) { $result = $auth->authenticate($request, $response); if (!empty($result) && is_array($result)) { return $result; } } return false; } /** * Loads the configured authentication objects. * * @return mixed Either null on empty authenticate value, or an array of loaded objects. * @throws CakeException */ public function constructAuthenticate() { if (empty($this->authenticate)) { return null; } $this->_authenticateObjects = array(); $config = Hash::normalize((array)$this->authenticate); $global = array(); if (isset($config[AuthComponent::ALL])) { $global = $config[AuthComponent::ALL]; unset($config[AuthComponent::ALL]); } foreach ($config as $class => $settings) { if (!empty($settings['className'])) { $class = $settings['className']; unset($settings['className']); } list($plugin, $class) = pluginSplit($class, true); $className = $class . 'Authenticate'; App::uses($className, $plugin . 'Controller/Component/Auth'); if (!class_exists($className)) { throw new CakeException(__d('cake_dev', 'Authentication adapter "%s" was not found.', $class)); } if (!method_exists($className, 'authenticate')) { throw new CakeException(__d('cake_dev', 'Authentication objects must implement an %s method.', 'authenticate()')); } $settings = array_merge($global, (array)$settings); $auth = new $className($this->_Collection, $settings); $this->_Collection->getController()->getEventManager()->attach($auth); $this->_authenticateObjects[] = $auth; } return $this->_authenticateObjects; } /** * Hash a password with the application's salt value (as defined with Configure::write('Security.salt'); * * This method is intended as a convenience wrapper for Security::hash(). If you want to use * a hashing/encryption system not supported by that method, do not use this method. * * @param string $password Password to hash * @return string Hashed password * @deprecated 3.0.0 Since 2.4. Use Security::hash() directly or a password hasher object. */ public static function password($password) { return Security::hash($password, null, true); } /** * Check whether or not the current user has data in the session, and is considered logged in. * * @return bool true if the user is logged in, false otherwise * @deprecated 3.0.0 Since 2.5. Use AuthComponent::user() directly. */ public function loggedIn() { return (bool)$this->user(); } /** * Set a flash message. Uses the Session component, and values from AuthComponent::$flash. * * @param string $message The message to set. * @return void */ public function flash($message) { if ($message === false) { return; } $this->Flash->set($message, $this->flash); } } cakephp-2.8.0/lib/Cake/Controller/Component/CookieComponent.php000066400000000000000000000355371265552240500244620ustar00rootroot00000000000000Cookie->name = 'CookieName'; * * @var string */ public $name = 'CakeCookie'; /** * The time a cookie will remain valid. * * Can be either integer Unix timestamp or a date string. * * Overridden with the controller beforeFilter(); * $this->Cookie->time = '5 Days'; * * @var mixed */ public $time = null; /** * Cookie path. * * Overridden with the controller beforeFilter(); * $this->Cookie->path = '/'; * * The path on the server in which the cookie will be available on. * If public $cookiePath is set to '/foo/', the cookie will only be available * within the /foo/ directory and all sub-directories such as /foo/bar/ of domain. * The default value is the entire domain. * * @var string */ public $path = '/'; /** * Domain path. * * The domain that the cookie is available. * * Overridden with the controller beforeFilter(); * $this->Cookie->domain = '.example.com'; * * To make the cookie available on all subdomains of example.com. * Set $this->Cookie->domain = '.example.com'; in your controller beforeFilter * * @var string */ public $domain = ''; /** * Secure HTTPS only cookie. * * Overridden with the controller beforeFilter(); * $this->Cookie->secure = true; * * Indicates that the cookie should only be transmitted over a secure HTTPS connection. * When set to true, the cookie will only be set if a secure connection exists. * * @var bool */ public $secure = false; /** * Encryption key. * * Overridden with the controller beforeFilter(); * $this->Cookie->key = 'SomeRandomString'; * * @var string */ public $key = null; /** * HTTP only cookie * * Set to true to make HTTP only cookies. Cookies that are HTTP only * are not accessible in JavaScript. * * @var bool */ public $httpOnly = false; /** * Values stored in the cookie. * * Accessed in the controller using $this->Cookie->read('Name.key'); * * @see CookieComponent::read(); * @var string */ protected $_values = array(); /** * Type of encryption to use. * * Currently two methods are available: cipher and rijndael * Defaults to Security::cipher(). Cipher is horribly insecure and only * the default because of backwards compatibility. In new applications you should * always change this to 'aes' or 'rijndael'. * * @var string */ protected $_type = 'cipher'; /** * Used to reset cookie time if $expire is passed to CookieComponent::write() * * @var string */ protected $_reset = null; /** * Expire time of the cookie * * This is controlled by CookieComponent::time; * * @var string */ protected $_expires = 0; /** * A reference to the Controller's CakeResponse object * * @var CakeResponse */ protected $_response = null; /** * Constructor * * @param ComponentCollection $collection A ComponentCollection for this component * @param array $settings Array of settings. */ public function __construct(ComponentCollection $collection, $settings = array()) { $this->key = Configure::read('Security.salt'); parent::__construct($collection, $settings); if (isset($this->time)) { $this->_expire($this->time); } $controller = $collection->getController(); if ($controller && isset($controller->response)) { $this->_response = $controller->response; } else { $this->_response = new CakeResponse(); } } /** * Start CookieComponent for use in the controller * * @param Controller $controller Controller instance. * @return void */ public function startup(Controller $controller) { $this->_expire($this->time); $this->_values[$this->name] = array(); } /** * Write a value to the $_COOKIE[$key]; * * Optional [Name.], required key, optional $value, optional $encrypt, optional $expires * $this->Cookie->write('[Name.]key, $value); * * By default all values are encrypted. * You must pass $encrypt false to store values in clear test * * You must use this method before any output is sent to the browser. * Failure to do so will result in header already sent errors. * * @param string|array $key Key for the value * @param mixed $value Value * @param bool $encrypt Set to true to encrypt value, false otherwise * @param int|string $expires Can be either the number of seconds until a cookie * expires, or a strtotime compatible time offset. * @return void * @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html#CookieComponent::write */ public function write($key, $value = null, $encrypt = true, $expires = null) { if (empty($this->_values[$this->name])) { $this->read(); } if ($encrypt === null) { $encrypt = true; } $this->_encrypted = $encrypt; $this->_expire($expires); if (!is_array($key)) { $key = array($key => $value); } foreach ($key as $name => $value) { $names = array($name); if (strpos($name, '.') !== false) { $names = explode('.', $name, 2); } $firstName = $names[0]; $isMultiValue = (is_array($value) || count($names) > 1); if (!isset($this->_values[$this->name][$firstName]) && $isMultiValue) { $this->_values[$this->name][$firstName] = array(); } if (count($names) > 1) { $this->_values[$this->name][$firstName] = Hash::insert( $this->_values[$this->name][$firstName], $names[1], $value ); } else { $this->_values[$this->name][$firstName] = $value; } $this->_write('[' . $firstName . ']', $this->_values[$this->name][$firstName]); } $this->_encrypted = true; } /** * Read the value of the $_COOKIE[$key]; * * Optional [Name.], required key * $this->Cookie->read(Name.key); * * @param string $key Key of the value to be obtained. If none specified, obtain map key => values * @return string|null Value for specified key * @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html#CookieComponent::read */ public function read($key = null) { if (empty($this->_values[$this->name]) && isset($_COOKIE[$this->name])) { $this->_values[$this->name] = $this->_decrypt($_COOKIE[$this->name]); } if (empty($this->_values[$this->name])) { $this->_values[$this->name] = array(); } if ($key === null) { return $this->_values[$this->name]; } if (strpos($key, '.') !== false) { $names = explode('.', $key, 2); $key = $names[0]; } if (!isset($this->_values[$this->name][$key])) { return null; } if (!empty($names[1]) && is_array($this->_values[$this->name][$key])) { return Hash::get($this->_values[$this->name][$key], $names[1]); } return $this->_values[$this->name][$key]; } /** * Returns true if given variable is set in cookie. * * @param string $key Variable name to check for * @return bool True if variable is there */ public function check($key = null) { if (empty($key)) { return false; } return $this->read($key) !== null; } /** * Delete a cookie value * * Optional [Name.], required key * $this->Cookie->delete('Name.key); * * You must use this method before any output is sent to the browser. * Failure to do so will result in header already sent errors. * * This method will delete both the top level and 2nd level cookies set. * For example assuming that $name = App, deleting `User` will delete * both `App[User]` and any other cookie values like `App[User][email]` * This is done to clean up cookie storage from before 2.4.3, where cookies * were stored inconsistently. * * @param string $key Key of the value to be deleted * @return void * @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html#CookieComponent::delete */ public function delete($key) { if (empty($this->_values[$this->name])) { $this->read(); } if (strpos($key, '.') === false) { if (isset($this->_values[$this->name][$key]) && is_array($this->_values[$this->name][$key])) { foreach ($this->_values[$this->name][$key] as $idx => $val) { $this->_delete("[$key][$idx]"); } } $this->_delete("[$key]"); unset($this->_values[$this->name][$key]); return; } $names = explode('.', $key, 2); if (isset($this->_values[$this->name][$names[0]])) { $this->_values[$this->name][$names[0]] = Hash::remove($this->_values[$this->name][$names[0]], $names[1]); } $this->_delete('[' . implode('][', $names) . ']'); } /** * Destroy current cookie * * You must use this method before any output is sent to the browser. * Failure to do so will result in header already sent errors. * * @return void * @link http://book.cakephp.org/2.0/en/core-libraries/components/cookie.html#CookieComponent::destroy */ public function destroy() { if (isset($_COOKIE[$this->name])) { $this->_values[$this->name] = $this->_decrypt($_COOKIE[$this->name]); } foreach ($this->_values[$this->name] as $name => $value) { if (is_array($value)) { foreach ($value as $key => $val) { unset($this->_values[$this->name][$name][$key]); $this->_delete("[$name][$key]"); } } unset($this->_values[$this->name][$name]); $this->_delete("[$name]"); } } /** * Will allow overriding default encryption method. Use this method * in ex: AppController::beforeFilter() before you have read or * written any cookies. * * @param string $type Encryption method * @return void */ public function type($type = 'cipher') { $availableTypes = array( 'cipher', 'rijndael', 'aes' ); if (!in_array($type, $availableTypes)) { trigger_error(__d('cake_dev', 'You must use cipher, rijndael or aes for cookie encryption type'), E_USER_WARNING); $type = 'cipher'; } $this->_type = $type; } /** * Set the expire time for a session variable. * * Creates a new expire time for a session variable. * $expire can be either integer Unix timestamp or a date string. * * Used by write() * CookieComponent::write(string, string, boolean, 8400); * CookieComponent::write(string, string, boolean, '5 Days'); * * @param int|string $expires Can be either Unix timestamp, or date string * @return int Unix timestamp */ protected function _expire($expires = null) { if ($expires === null) { return $this->_expires; } $this->_reset = $this->_expires; if (!$expires) { return $this->_expires = 0; } $now = new DateTime(); if (is_int($expires) || is_numeric($expires)) { return $this->_expires = $now->format('U') + (int)$expires; } $now->modify($expires); return $this->_expires = $now->format('U'); } /** * Set cookie * * @param string $name Name for cookie * @param string $value Value for cookie * @return void */ protected function _write($name, $value) { $this->_response->cookie(array( 'name' => $this->name . $name, 'value' => $this->_encrypt($value), 'expire' => $this->_expires, 'path' => $this->path, 'domain' => $this->domain, 'secure' => $this->secure, 'httpOnly' => $this->httpOnly )); if (!empty($this->_reset)) { $this->_expires = $this->_reset; $this->_reset = null; } } /** * Sets a cookie expire time to remove cookie value * * @param string $name Name of cookie * @return void */ protected function _delete($name) { $this->_response->cookie(array( 'name' => $this->name . $name, 'value' => '', 'expire' => time() - 42000, 'path' => $this->path, 'domain' => $this->domain, 'secure' => $this->secure, 'httpOnly' => $this->httpOnly )); } /** * Encrypts $value using public $type method in Security class * * @param string $value Value to encrypt * @return string Encoded values */ protected function _encrypt($value) { if (is_array($value)) { $value = $this->_implode($value); } if (!$this->_encrypted) { return $value; } $prefix = "Q2FrZQ==."; if ($this->_type === 'rijndael') { $cipher = Security::rijndael($value, $this->key, 'encrypt'); } if ($this->_type === 'cipher') { $cipher = Security::cipher($value, $this->key); } if ($this->_type === 'aes') { $cipher = Security::encrypt($value, $this->key); } return $prefix . base64_encode($cipher); } /** * Decrypts $value using public $type method in Security class * * @param array $values Values to decrypt * @return string decrypted string */ protected function _decrypt($values) { $decrypted = array(); $type = $this->_type; foreach ((array)$values as $name => $value) { if (is_array($value)) { foreach ($value as $key => $val) { $decrypted[$name][$key] = $this->_decode($val); } } else { $decrypted[$name] = $this->_decode($value); } } return $decrypted; } /** * Decodes and decrypts a single value. * * @param string $value The value to decode & decrypt. * @return string Decoded value. */ protected function _decode($value) { $prefix = 'Q2FrZQ==.'; $pos = strpos($value, $prefix); if ($pos === false) { return $this->_explode($value); } $value = base64_decode(substr($value, strlen($prefix))); if ($this->_type === 'rijndael') { $plain = Security::rijndael($value, $this->key, 'decrypt'); } if ($this->_type === 'cipher') { $plain = Security::cipher($value, $this->key); } if ($this->_type === 'aes') { $plain = Security::decrypt($value, $this->key); } return $this->_explode($plain); } /** * Implode method to keep keys are multidimensional arrays * * @param array $array Map of key and values * @return string A json encoded string. */ protected function _implode(array $array) { return json_encode($array); } /** * Explode method to return array from string set in CookieComponent::_implode() * Maintains reading backwards compatibility with 1.x CookieComponent::_implode(). * * @param string $string A string containing JSON encoded data, or a bare string. * @return array Map of key and values */ protected function _explode($string) { $first = substr($string, 0, 1); if ($first === '{' || $first === '[') { $ret = json_decode($string, true); return ($ret !== null) ? $ret : $string; } $array = array(); foreach (explode(',', $string) as $pair) { $key = explode('|', $pair); if (!isset($key[1])) { return $key[0]; } $array[$key[0]] = $key[1]; } return $array; } } cakephp-2.8.0/lib/Cake/Controller/Component/EmailComponent.php000066400000000000000000000250051265552240500242650ustar00rootroot00000000000000_controller = $collection->getController(); parent::__construct($collection, $settings); } /** * Initialize component * * @param Controller $controller Instantiating controller * @return void */ public function initialize(Controller $controller) { if (Configure::read('App.encoding') !== null) { $this->charset = Configure::read('App.encoding'); } } /** * Send an email using the specified content, template and layout * * @param string|array $content Either an array of text lines, or a string with contents * If you are rendering a template this variable will be sent to the templates as `$content` * @param string $template Template to use when sending email * @param string $layout Layout to use to enclose email body * @return bool Success */ public function send($content = null, $template = null, $layout = null) { $lib = new CakeEmail(); $lib->charset = $this->charset; $lib->headerCharset = $this->charset; $lib->from($this->_formatAddresses((array)$this->from)); if (!empty($this->to)) { $lib->to($this->_formatAddresses((array)$this->to)); } if (!empty($this->cc)) { $lib->cc($this->_formatAddresses((array)$this->cc)); } if (!empty($this->bcc)) { $lib->bcc($this->_formatAddresses((array)$this->bcc)); } if (!empty($this->replyTo)) { $lib->replyTo($this->_formatAddresses((array)$this->replyTo)); } if (!empty($this->return)) { $lib->returnPath($this->_formatAddresses((array)$this->return)); } if (!empty($this->readReceipt)) { $lib->readReceipt($this->_formatAddresses((array)$this->readReceipt)); } $lib->subject($this->subject); $lib->messageID($this->messageId); $lib->helpers($this->_controller->helpers); $headers = array('X-Mailer' => $this->xMailer); foreach ($this->headers as $key => $value) { $headers['X-' . $key] = $value; } if ($this->date) { $headers['Date'] = $this->date; } $lib->setHeaders($headers); if ($template) { $this->template = $template; } if ($layout) { $this->layout = $layout; } $lib->template($this->template, $this->layout)->viewVars($this->_controller->viewVars)->emailFormat($this->sendAs); if (!empty($this->attachments)) { $lib->attachments($this->_formatAttachFiles()); } $lib->transport(ucfirst($this->delivery)); if ($this->delivery === 'mail') { $lib->config(array('eol' => $this->lineFeed, 'additionalParameters' => $this->additionalParams)); } elseif ($this->delivery === 'smtp') { $lib->config($this->smtpOptions); } else { $lib->config(array()); } $sent = $lib->send($content); $this->htmlMessage = $lib->message(CakeEmail::MESSAGE_HTML); if (empty($this->htmlMessage)) { $this->htmlMessage = null; } $this->textMessage = $lib->message(CakeEmail::MESSAGE_TEXT); if (empty($this->textMessage)) { $this->textMessage = null; } $this->_header = array(); $this->_message = array(); return $sent; } /** * Reset all EmailComponent internal variables to be able to send out a new email. * * @return void */ public function reset() { $this->template = null; $this->to = array(); $this->from = null; $this->replyTo = null; $this->return = null; $this->cc = array(); $this->bcc = array(); $this->subject = null; $this->additionalParams = null; $this->date = null; $this->attachments = array(); $this->htmlMessage = null; $this->textMessage = null; $this->messageId = true; $this->delivery = 'mail'; } /** * Format the attach array * * @return array */ protected function _formatAttachFiles() { $files = array(); foreach ($this->attachments as $filename => $attachment) { $file = $this->_findFiles($attachment); if (!empty($file)) { if (is_int($filename)) { $filename = basename($file); } $files[$filename] = $file; } } return $files; } /** * Find the specified attachment in the list of file paths * * @param string $attachment Attachment file name to find * @return string|null Path to located file */ protected function _findFiles($attachment) { if (file_exists($attachment)) { return $attachment; } foreach ($this->filePaths as $path) { if (file_exists($path . DS . $attachment)) { $file = $path . DS . $attachment; return $file; } } return null; } /** * Format addresses to be an array with email as key and alias as value * * @param array $addresses Address to format. * @return array */ protected function _formatAddresses($addresses) { $formatted = array(); foreach ($addresses as $address) { if (preg_match('/((.*))?\s?<(.+)>/', $address, $matches) && !empty($matches[2])) { $formatted[$this->_strip($matches[3])] = $matches[2]; } else { $address = $this->_strip($address); $formatted[$address] = $address; } } return $formatted; } /** * Remove certain elements (such as bcc:, to:, %0a) from given value. * Helps prevent header injection / manipulation on user content. * * @param string $value Value to strip * @param bool $message Set to true to indicate main message content * @return string Stripped value */ protected function _strip($value, $message = false) { $search = '%0a|%0d|Content-(?:Type|Transfer-Encoding)\:'; $search .= '|charset\=|mime-version\:|multipart/mixed|(?:[^a-z]to|b?cc)\:.*'; if ($message !== true) { $search .= '|\r|\n'; } $search = '#(?:' . $search . ')#i'; while (preg_match($search, $value)) { $value = preg_replace($search, '', $value); } return $value; } } cakephp-2.8.0/lib/Cake/Controller/Component/FlashComponent.php000066400000000000000000000067111265552240500242760ustar00rootroot00000000000000 'flash', 'element' => 'default', 'params' => array(), ); /** * Constructor * * @param ComponentCollection $collection The ComponentCollection object * @param array $settings Settings passed via controller */ public function __construct(ComponentCollection $collection, $settings = array()) { $this->_defaultConfig = Hash::merge($this->_defaultConfig, $settings); } /** * Used to set a session variable that can be used to output messages in the view. * * In your controller: $this->Flash->set('This has been saved'); * * ### Options: * * - `key` The key to set under the session's Flash key * - `element` The element used to render the flash message. Default to 'default'. * - `params` An array of variables to make available when using an element * * @param string $message Message to be flashed. If an instance * of Exception the exception message will be used and code will be set * in params. * @param array $options An array of options. * @return void */ public function set($message, $options = array()) { $options += $this->_defaultConfig; if ($message instanceof Exception) { $options['params'] += array('code' => $message->getCode()); $message = $message->getMessage(); } list($plugin, $element) = pluginSplit($options['element'], true); if (!empty($options['plugin'])) { $plugin = $options['plugin'] . '.'; } $options['element'] = $plugin . 'Flash/' . $element; CakeSession::write('Message.' . $options['key'], array( 'message' => $message, 'key' => $options['key'], 'element' => $options['element'], 'params' => $options['params'] )); } /** * Magic method for verbose flash methods based on element names. * * For example: $this->Flash->success('My message') would use the * success.ctp element under `app/View/Element/Flash` for rendering the * flash message. * * @param string $name Element name to use. * @param array $args Parameters to pass when calling `FlashComponent::set()`. * @return void * @throws InternalErrorException If missing the flash message. */ public function __call($name, $args) { $options = array('element' => Inflector::underscore($name)); if (count($args) < 1) { throw new InternalErrorException('Flash message missing.'); } if (!empty($args[1])) { $options += (array)$args[1]; } $this->set($args[0], $options); } } cakephp-2.8.0/lib/Cake/Controller/Component/PaginatorComponent.php000066400000000000000000000325001265552240500251600ustar00rootroot00000000000000Paginator->settings = array( * 'limit' => 20, * 'maxLimit' => 100 * ); * ``` * * The above settings will be used to paginate any model. You can configure model specific settings by * keying the settings with the model name. * * ``` * $this->Paginator->settings = array( * 'Post' => array( * 'limit' => 20, * 'maxLimit' => 100 * ), * 'Comment' => array( ... ) * ); * ``` * * This would allow you to have different pagination settings for `Comment` and `Post` models. * * #### Paginating with custom finders * * You can paginate with any find type defined on your model using the `findType` option. * * ``` * $this->Paginator->settings = array( * 'Post' => array( * 'findType' => 'popular' * ) * ); * ``` * * Would paginate using the `find('popular')` method. * * @package Cake.Controller.Component * @link http://book.cakephp.org/2.0/en/core-libraries/components/pagination.html */ class PaginatorComponent extends Component { /** * Pagination settings. These settings control pagination at a general level. * You can also define sub arrays for pagination settings for specific models. * * - `maxLimit` The maximum limit users can choose to view. Defaults to 100 * - `limit` The initial number of items per page. Defaults to 20. * - `page` The starting page, defaults to 1. * - `paramType` What type of parameters you want pagination to use? * - `named` Use named parameters / routed parameters. * - `querystring` Use query string parameters. * * @var array */ public $settings = array( 'page' => 1, 'limit' => 20, 'maxLimit' => 100, 'paramType' => 'named' ); /** * A list of parameters users are allowed to set using request parameters. Modifying * this list will allow users to have more influence over pagination, * be careful with what you permit. * * @var array */ public $whitelist = array( 'limit', 'sort', 'page', 'direction' ); /** * Constructor * * @param ComponentCollection $collection A ComponentCollection this component can use to lazy load its components * @param array $settings Array of configuration settings. */ public function __construct(ComponentCollection $collection, $settings = array()) { $settings = array_merge($this->settings, (array)$settings); $this->Controller = $collection->getController(); parent::__construct($collection, $settings); } /** * Handles automatic pagination of model records. * * @param Model|string $object Model to paginate (e.g: model instance, or 'Model', or 'Model.InnerModel') * @param string|array $scope Additional find conditions to use while paginating * @param array $whitelist List of allowed fields for ordering. This allows you to prevent ordering * on non-indexed, or undesirable columns. See PaginatorComponent::validateSort() for additional details * on how the whitelisting and sort field validation works. * @return array Model query results * @throws MissingModelException * @throws NotFoundException */ public function paginate($object = null, $scope = array(), $whitelist = array()) { if (is_array($object)) { $whitelist = $scope; $scope = $object; $object = null; } $object = $this->_getObject($object); if (!is_object($object)) { throw new MissingModelException($object); } $options = $this->mergeOptions($object->alias); $options = $this->validateSort($object, $options, $whitelist); $options = $this->checkLimit($options); $conditions = $fields = $order = $limit = $page = $recursive = null; if (!isset($options['conditions'])) { $options['conditions'] = array(); } $type = 'all'; if (isset($options[0])) { $type = $options[0]; unset($options[0]); } extract($options); if (is_array($scope) && !empty($scope)) { $conditions = array_merge($conditions, $scope); } elseif (is_string($scope)) { $conditions = array($conditions, $scope); } if ($recursive === null) { $recursive = $object->recursive; } $extra = array_diff_key($options, compact( 'conditions', 'fields', 'order', 'limit', 'page', 'recursive' )); if (!empty($extra['findType'])) { $type = $extra['findType']; unset($extra['findType']); } if ($type !== 'all') { $extra['type'] = $type; } if ((int)$page < 1) { $page = 1; } $page = $options['page'] = (int)$page; if ($object->hasMethod('paginate')) { $results = $object->paginate( $conditions, $fields, $order, $limit, $page, $recursive, $extra ); } else { $parameters = compact('conditions', 'fields', 'order', 'limit', 'page'); if ($recursive != $object->recursive) { $parameters['recursive'] = $recursive; } $results = $object->find($type, array_merge($parameters, $extra)); } $defaults = $this->getDefaults($object->alias); unset($defaults[0]); if (!$results) { $count = 0; } elseif ($object->hasMethod('paginateCount')) { $count = $object->paginateCount($conditions, $recursive, $extra); } elseif ($page === 1 && count($results) < $limit) { $count = count($results); } else { $parameters = compact('conditions'); if ($recursive != $object->recursive) { $parameters['recursive'] = $recursive; } $count = $object->find('count', array_merge($parameters, $extra)); } $pageCount = (int)ceil($count / $limit); $requestedPage = $page; $page = max(min($page, $pageCount), 1); $paging = array( 'page' => $page, 'current' => count($results), 'count' => $count, 'prevPage' => ($page > 1), 'nextPage' => ($count > ($page * $limit)), 'pageCount' => $pageCount, 'order' => $order, 'limit' => $limit, 'options' => Hash::diff($options, $defaults), 'paramType' => $options['paramType'] ); if (!isset($this->Controller->request['paging'])) { $this->Controller->request['paging'] = array(); } $this->Controller->request['paging'] = array_merge( (array)$this->Controller->request['paging'], array($object->alias => $paging) ); if ($requestedPage > $page) { throw new NotFoundException(); } if (!in_array('Paginator', $this->Controller->helpers) && !array_key_exists('Paginator', $this->Controller->helpers) ) { $this->Controller->helpers[] = 'Paginator'; } return $results; } /** * Get the object pagination will occur on. * * @param string|Model $object The object you are looking for. * @return mixed The model object to paginate on. */ protected function _getObject($object) { if (is_string($object)) { $assoc = null; if (strpos($object, '.') !== false) { list($object, $assoc) = pluginSplit($object); } if ($assoc && isset($this->Controller->{$object}->{$assoc})) { return $this->Controller->{$object}->{$assoc}; } if ($assoc && isset($this->Controller->{$this->Controller->modelClass}->{$assoc})) { return $this->Controller->{$this->Controller->modelClass}->{$assoc}; } if (isset($this->Controller->{$object})) { return $this->Controller->{$object}; } if (isset($this->Controller->{$this->Controller->modelClass}->{$object})) { return $this->Controller->{$this->Controller->modelClass}->{$object}; } } if (empty($object) || $object === null) { if (isset($this->Controller->{$this->Controller->modelClass})) { return $this->Controller->{$this->Controller->modelClass}; } $className = null; $name = $this->Controller->uses[0]; if (strpos($this->Controller->uses[0], '.') !== false) { list($name, $className) = explode('.', $this->Controller->uses[0]); } if ($className) { return $this->Controller->{$className}; } return $this->Controller->{$name}; } return $object; } /** * Merges the various options that Pagination uses. * Pulls settings together from the following places: * * - General pagination settings * - Model specific settings. * - Request parameters * * The result of this method is the aggregate of all the option sets combined together. You can change * PaginatorComponent::$whitelist to modify which options/values can be set using request parameters. * * @param string $alias Model alias being paginated, if the general settings has a key with this value * that key's settings will be used for pagination instead of the general ones. * @return array Array of merged options. */ public function mergeOptions($alias) { $defaults = $this->getDefaults($alias); switch ($defaults['paramType']) { case 'named': $request = $this->Controller->request->params['named']; break; case 'querystring': $request = $this->Controller->request->query; break; } $request = array_intersect_key($request, array_flip($this->whitelist)); return array_merge($defaults, $request); } /** * Get the default settings for a $model. If there are no settings for a specific model, the general settings * will be used. * * @param string $alias Model name to get default settings for. * @return array An array of pagination defaults for a model, or the general settings. */ public function getDefaults($alias) { $defaults = $this->settings; if (isset($this->settings[$alias])) { $defaults = $this->settings[$alias]; } $defaults += array( 'page' => 1, 'limit' => 20, 'maxLimit' => 100, 'paramType' => 'named' ); return $defaults; } /** * Validate that the desired sorting can be performed on the $object. Only fields or * virtualFields can be sorted on. The direction param will also be sanitized. Lastly * sort + direction keys will be converted into the model friendly order key. * * You can use the whitelist parameter to control which columns/fields are available for sorting. * This helps prevent users from ordering large result sets on un-indexed values. * * Any columns listed in the sort whitelist will be implicitly trusted. You can use this to sort * on synthetic columns, or columns added in custom find operations that may not exist in the schema. * * @param Model $object The model being paginated. * @param array $options The pagination options being used for this request. * @param array $whitelist The list of columns that can be used for sorting. If empty all keys are allowed. * @return array An array of options with sort + direction removed and replaced with order if possible. */ public function validateSort(Model $object, array $options, array $whitelist = array()) { if (empty($options['order']) && is_array($object->order)) { $options['order'] = $object->order; } if (isset($options['sort'])) { $direction = null; if (isset($options['direction'])) { $direction = strtolower($options['direction']); } if (!in_array($direction, array('asc', 'desc'))) { $direction = 'asc'; } $options['order'] = array($options['sort'] => $direction); } if (!empty($whitelist) && isset($options['order']) && is_array($options['order'])) { $field = key($options['order']); $inWhitelist = in_array($field, $whitelist, true); if (!$inWhitelist) { $options['order'] = null; } return $options; } if (!empty($options['order']) && is_array($options['order'])) { $order = array(); foreach ($options['order'] as $key => $value) { if (is_int($key)) { $key = $value; $value = 'asc'; } $field = $key; $alias = $object->alias; if (strpos($key, '.') !== false) { list($alias, $field) = explode('.', $key); } $correctAlias = ($object->alias === $alias); if ($correctAlias && $object->hasField($field)) { $order[$object->alias . '.' . $field] = $value; } elseif ($correctAlias && $object->hasField($key, true)) { $order[$field] = $value; } elseif (isset($object->{$alias}) && $object->{$alias}->hasField($field, true)) { $order[$alias . '.' . $field] = $value; } } $options['order'] = $order; } return $options; } /** * Check the limit parameter and ensure its within the maxLimit bounds. * * @param array $options An array of options with a limit key to be checked. * @return array An array of options for pagination */ public function checkLimit(array $options) { $options['limit'] = (int)$options['limit']; if (empty($options['limit']) || $options['limit'] < 1) { $options['limit'] = 1; } $options['limit'] = min($options['limit'], $options['maxLimit']); return $options; } } cakephp-2.8.0/lib/Cake/Controller/Component/RequestHandlerComponent.php000066400000000000000000000600521265552240500261650ustar00rootroot00000000000000 array('json_decode', true) ); /** * A mapping between type and viewClass * By default only JSON and XML are mapped, use RequestHandlerComponent::viewClassMap() * * @var array */ protected $_viewClassMap = array( 'json' => 'Json', 'xml' => 'Xml' ); /** * Constructor. Parses the accepted content types accepted by the client using HTTP_ACCEPT * * @param ComponentCollection $collection ComponentCollection object. * @param array $settings Array of settings. */ public function __construct(ComponentCollection $collection, $settings = array()) { parent::__construct($collection, $settings + array('checkHttpCache' => true)); $this->addInputType('xml', array(array($this, 'convertXml'))); $Controller = $collection->getController(); $this->request = $Controller->request; $this->response = $Controller->response; } /** * Checks to see if a file extension has been parsed by the Router, or if the * HTTP_ACCEPT_TYPE has matches only one content type with the supported extensions. * If there is only one matching type between the supported content types & extensions, * and the requested mime-types, RequestHandler::$ext is set to that value. * * @param Controller $controller A reference to the controller * @return void * @see Router::parseExtensions() */ public function initialize(Controller $controller) { if (isset($this->request->params['ext'])) { $this->ext = $this->request->params['ext']; } if (empty($this->ext) || $this->ext === 'html') { $this->_setExtension(); } $this->params = $controller->params; if (!empty($this->settings['viewClassMap'])) { $this->viewClassMap($this->settings['viewClassMap']); } } /** * Set the extension based on the accept headers. * Compares the accepted types and configured extensions. * If there is one common type, that is assigned as the ext/content type * for the response. * Type with the highest weight will be set. If the highest weight has more * then one type matching the extensions, the order in which extensions are specified * determines which type will be set. * * If html is one of the preferred types, no content type will be set, this * is to avoid issues with browsers that prefer html and several other content types. * * @return void */ protected function _setExtension() { $accept = $this->request->parseAccept(); if (empty($accept)) { return; } $accepts = $this->response->mapType($accept); $preferedTypes = current($accepts); if (array_intersect($preferedTypes, array('html', 'xhtml'))) { return; } $extensions = Router::extensions(); foreach ($accepts as $types) { $ext = array_intersect($extensions, $types); if ($ext) { $this->ext = current($ext); break; } } } /** * The startup method of the RequestHandler enables several automatic behaviors * related to the detection of certain properties of the HTTP request, including: * * - Disabling layout rendering for Ajax requests (based on the HTTP_X_REQUESTED_WITH header) * - If Router::parseExtensions() is enabled, the layout and template type are * 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`. 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. * - If the XML data is POSTed, the data is parsed into an XML object, which is assigned * to the $data property of the controller, which can then be saved to a model object. * * @param Controller $controller A reference to the controller * @return void */ public function startup(Controller $controller) { $controller->request->params['isAjax'] = $this->request->is('ajax'); $isRecognized = ( !in_array($this->ext, array('html', 'htm')) && $this->response->getMimeType($this->ext) ); if (!empty($this->ext) && $isRecognized) { $this->renderAs($controller, $this->ext); } elseif ($this->request->is('ajax')) { $this->renderAs($controller, 'ajax'); } elseif (empty($this->ext) || in_array($this->ext, array('html', 'htm'))) { $this->respondAs('html', array('charset' => Configure::read('App.encoding'))); } foreach ($this->_inputTypeMap as $type => $handler) { if ($this->requestedWith($type)) { $input = call_user_func_array(array($controller->request, 'input'), $handler); $controller->request->data = $input; } } } /** * Helper method to parse xml input data, due to lack of anonymous functions * this lives here. * * @param string $xml XML string. * @return array Xml array data */ public function convertXml($xml) { try { $xml = Xml::build($xml, array('readFile' => false)); if (isset($xml->data)) { return Xml::toArray($xml->data); } return Xml::toArray($xml); } catch (XmlException $e) { return array(); } } /** * Handles (fakes) redirects for Ajax requests using requestAction() * Modifies the $_POST and $_SERVER['REQUEST_METHOD'] to simulate a new GET request. * * @param Controller $controller A reference to the controller * @param string|array $url A string or array containing the redirect location * @param int|array $status HTTP Status for redirect * @param bool $exit Whether to exit script, defaults to `true`. * @return void */ public function beforeRedirect(Controller $controller, $url, $status = null, $exit = true) { if (!$this->request->is('ajax')) { return; } if (empty($url)) { return; } $_SERVER['REQUEST_METHOD'] = 'GET'; foreach ($_POST as $key => $val) { unset($_POST[$key]); } if (is_array($url)) { $url = Router::url($url + array('base' => false)); } if (!empty($status)) { $statusCode = $this->response->httpCodes($status); $code = key($statusCode); $this->response->statusCode($code); } $this->response->body($this->requestAction($url, array('return', 'bare' => false))); $this->response->send(); $this->_stop(); } /** * Checks if the response can be considered different according to the request * headers, and the caching response headers. If it was not modified, then the * render process is skipped. And the client will get a blank response with a * "304 Not Modified" header. * * @param Controller $controller Controller instance. * @return bool False if the render process should be aborted. */ public function beforeRender(Controller $controller) { if ($this->settings['checkHttpCache'] && $this->response->checkNotModified($this->request)) { return false; } } /** * Returns true if the current HTTP request is Ajax, false otherwise * * @return bool True if call is Ajax * @deprecated 3.0.0 Use `$this->request->is('ajax')` instead. */ public function isAjax() { return $this->request->is('ajax'); } /** * Returns true if the current HTTP request is coming from a Flash-based client * * @return bool True if call is from Flash * @deprecated 3.0.0 Use `$this->request->is('flash')` instead. */ public function isFlash() { return $this->request->is('flash'); } /** * Returns true if the current request is over HTTPS, false otherwise. * * @return bool True if call is over HTTPS * @deprecated 3.0.0 Use `$this->request->is('ssl')` instead. */ public function isSSL() { return $this->request->is('ssl'); } /** * Returns true if the current call accepts an XML response, false otherwise * * @return bool True if client accepts an XML response */ public function isXml() { return $this->prefers('xml'); } /** * Returns true if the current call accepts an RSS response, false otherwise * * @return bool True if client accepts an RSS response */ public function isRss() { return $this->prefers('rss'); } /** * Returns true if the current call accepts an Atom response, false otherwise * * @return bool True if client accepts an RSS response */ public function isAtom() { return $this->prefers('atom'); } /** * Returns true if user agent string matches a mobile web browser, or if the * client accepts WAP content. * * @return bool True if user agent is a mobile web browser */ public function isMobile() { return $this->request->is('mobile') || $this->accepts('wap'); } /** * Returns true if the client accepts WAP content * * @return bool */ public function isWap() { return $this->prefers('wap'); } /** * Returns true if the current call a POST request * * @return bool True if call is a POST * @deprecated 3.0.0 Use $this->request->is('post'); from your controller. */ public function isPost() { return $this->request->is('post'); } /** * Returns true if the current call a PUT request * * @return bool True if call is a PUT * @deprecated 3.0.0 Use $this->request->is('put'); from your controller. */ public function isPut() { return $this->request->is('put'); } /** * Returns true if the current call a GET request * * @return bool True if call is a GET * @deprecated 3.0.0 Use $this->request->is('get'); from your controller. */ public function isGet() { return $this->request->is('get'); } /** * Returns true if the current call a DELETE request * * @return bool True if call is a DELETE * @deprecated 3.0.0 Use $this->request->is('delete'); from your controller. */ public function isDelete() { return $this->request->is('delete'); } /** * Gets Prototype version if call is Ajax, otherwise empty string. * The Prototype library sets a special "Prototype version" HTTP header. * * @return string|bool When Ajax the prototype version of component making the call otherwise false */ public function getAjaxVersion() { $httpX = env('HTTP_X_PROTOTYPE_VERSION'); return ($httpX === null) ? false : $httpX; } /** * Adds/sets the Content-type(s) for the given name. This method allows * content-types to be mapped to friendly aliases (or extensions), which allows * RequestHandler to automatically respond to requests of that type in the * startup method. * * @param string $name The name of the Content-type, i.e. "html", "xml", "css" * @param string|array $type The Content-type or array of Content-types assigned to the name, * i.e. "text/html", or "application/xml" * @return void * @deprecated 3.0.0 Use `$this->response->type()` instead. */ public function setContent($name, $type = null) { $this->response->type(array($name => $type)); } /** * Gets the server name from which this request was referred * * @return string Server address * @deprecated 3.0.0 Use $this->request->referer() from your controller instead */ public function getReferer() { return $this->request->referer(false); } /** * Gets remote client IP * * @param bool $safe Use safe = false when you think the user might manipulate * their HTTP_CLIENT_IP header. Setting $safe = false will also look at HTTP_X_FORWARDED_FOR * @return string Client IP address * @deprecated 3.0.0 Use $this->request->clientIp() from your, controller instead. */ public function getClientIP($safe = true) { return $this->request->clientIp($safe); } /** * Determines which content types the client accepts. Acceptance is based on * the file extension parsed by the Router (if present), and by the HTTP_ACCEPT * header. Unlike CakeRequest::accepts() this method deals entirely with mapped content types. * * Usage: * * `$this->RequestHandler->accepts(array('xml', 'html', 'json'));` * * Returns true if the client accepts any of the supplied types. * * `$this->RequestHandler->accepts('xml');` * * Returns true if the client accepts xml. * * @param string|array $type Can be null (or no parameter), a string type name, or an * array of types * @return mixed If null or no parameter is passed, returns an array of content * types the client accepts. If a string is passed, returns true * if the client accepts it. If an array is passed, returns true * if the client accepts one or more elements in the array. * @see RequestHandlerComponent::setContent() */ public function accepts($type = null) { $accepted = $this->request->accepts(); if (!$type) { return $this->mapType($accepted); } if (is_array($type)) { foreach ($type as $t) { $t = $this->mapAlias($t); if (in_array($t, $accepted)) { return true; } } return false; } if (is_string($type)) { return in_array($this->mapAlias($type), $accepted); } return false; } /** * Determines the content type of the data the client has sent (i.e. in a POST request) * * @param string|array $type Can be null (or no parameter), a string type name, or an array of types * @return mixed If a single type is supplied a boolean will be returned. If no type is provided * The mapped value of CONTENT_TYPE will be returned. If an array is supplied the first type * in the request content type will be returned. */ public function requestedWith($type = null) { if (!$this->request->is('post') && !$this->request->is('put') && !$this->request->is('delete')) { return null; } if (is_array($type)) { foreach ($type as $t) { if ($this->requestedWith($t)) { return $t; } } return false; } list($contentType) = explode(';', env('CONTENT_TYPE')); if ($contentType === '') { list($contentType) = explode(';', CakeRequest::header('CONTENT_TYPE')); } if (!$type) { return $this->mapType($contentType); } if (is_string($type)) { return ($type === $this->mapType($contentType)); } } /** * Determines which content-types the client prefers. If no parameters are given, * the single content-type that the client most likely prefers is returned. If $type is * an array, the first item in the array that the client accepts is returned. * Preference is determined primarily by the file extension parsed by the Router * if provided, and secondarily by the list of content-types provided in * HTTP_ACCEPT. * * @param string|array $type An optional array of 'friendly' content-type names, i.e. * 'html', 'xml', 'js', etc. * @return mixed If $type is null or not provided, the first content-type in the * list, based on preference, is returned. If a single type is provided * a boolean will be returned if that type is preferred. * If an array of types are provided then the first preferred type is returned. * If no type is provided the first preferred type is returned. * @see RequestHandlerComponent::setContent() */ public function prefers($type = null) { $acceptRaw = $this->request->parseAccept(); if (empty($acceptRaw)) { return $this->ext; } $accepts = $this->mapType(array_shift($acceptRaw)); if (!$type) { if (empty($this->ext) && !empty($accepts)) { return $accepts[0]; } return $this->ext; } $types = (array)$type; if (count($types) === 1) { if (!empty($this->ext)) { return in_array($this->ext, $types); } return in_array($types[0], $accepts); } $intersect = array_values(array_intersect($accepts, $types)); if (empty($intersect)) { return false; } return $intersect[0]; } /** * Sets the layout and template paths for the content type defined by $type. * * ### Usage: * * Render the response as an 'ajax' response. * * `$this->RequestHandler->renderAs($this, 'ajax');` * * Render the response as an xml file and force the result as a file download. * * `$this->RequestHandler->renderAs($this, 'xml', array('attachment' => 'myfile.xml');` * * @param Controller $controller A reference to a controller object * @param string $type Type of response to send (e.g: 'ajax') * @param array $options Array of options to use * @return void * @see RequestHandlerComponent::setContent() * @see RequestHandlerComponent::respondAs() */ public function renderAs(Controller $controller, $type, $options = array()) { $defaults = array('charset' => 'UTF-8'); if (Configure::read('App.encoding') !== null) { $defaults['charset'] = Configure::read('App.encoding'); } $options += $defaults; if ($type === 'ajax') { $controller->layout = $this->ajaxLayout; return $this->respondAs('html', $options); } $pluginDot = null; $viewClassMap = $this->viewClassMap(); if (array_key_exists($type, $viewClassMap)) { list($pluginDot, $viewClass) = pluginSplit($viewClassMap[$type], true); } else { $viewClass = Inflector::classify($type); } $viewName = $viewClass . 'View'; if (!class_exists($viewName)) { App::uses($viewName, $pluginDot . 'View'); } if (class_exists($viewName)) { $controller->viewClass = $viewClass; } elseif (empty($this->_renderType)) { $controller->viewPath .= DS . $type; } else { $controller->viewPath = preg_replace( "/([\/\\\\]{$this->_renderType})$/", DS . $type, $controller->viewPath ); } $this->_renderType = $type; $controller->layoutPath = $type; if ($this->response->getMimeType($type)) { $this->respondAs($type, $options); } $helper = ucfirst($type); if (!in_array($helper, $controller->helpers) && empty($controller->helpers[$helper])) { App::uses('AppHelper', 'View/Helper'); App::uses($helper . 'Helper', 'View/Helper'); if (class_exists($helper . 'Helper')) { $controller->helpers[] = $helper; } } } /** * Sets the response header based on type map index name. This wraps several methods * available on CakeResponse. It also allows you to use Content-Type aliases. * * @param string|array $type Friendly type name, i.e. 'html' or 'xml', or a full content-type, * like 'application/x-shockwave'. * @param array $options If $type is a friendly type name that is associated with * more than one type of content, $index is used to select which content-type to use. * @return bool Returns false if the friendly type name given in $type does * not exist in the type map, or if the Content-type header has * already been set by this method. * @see RequestHandlerComponent::setContent() */ public function respondAs($type, $options = array()) { $defaults = array('index' => null, 'charset' => null, 'attachment' => false); $options = $options + $defaults; $cType = $type; if (strpos($type, '/') === false) { $cType = $this->response->getMimeType($type); } if (is_array($cType)) { if (isset($cType[$options['index']])) { $cType = $cType[$options['index']]; } if ($this->prefers($cType)) { $cType = $this->prefers($cType); } else { $cType = $cType[0]; } } if (!$type) { return false; } if (empty($this->request->params['requested'])) { $this->response->type($cType); } if (!empty($options['charset'])) { $this->response->charset($options['charset']); } if (!empty($options['attachment'])) { $this->response->download($options['attachment']); } return true; } /** * Returns the current response type (Content-type header), or null if not alias exists * * @return mixed A string content type alias, or raw content type if no alias map exists, * otherwise null */ public function responseType() { return $this->mapType($this->response->type()); } /** * Maps a content-type back to an alias * * @param string|array $cType Either a string content type to map, or an array of types. * @return string|array Aliases for the types provided. * @deprecated 3.0.0 Use $this->response->mapType() in your controller instead. */ public function mapType($cType) { return $this->response->mapType($cType); } /** * Maps a content type alias back to its mime-type(s) * * @param string|array $alias String alias to convert back into a content type. Or an array of aliases to map. * @return string|null Null on an undefined alias. String value of the mapped alias type. If an * alias maps to more than one content type, the first one will be returned. */ public function mapAlias($alias) { if (is_array($alias)) { return array_map(array($this, 'mapAlias'), $alias); } $type = $this->response->getMimeType($alias); if ($type) { if (is_array($type)) { return $type[0]; } return $type; } return null; } /** * Add a new mapped input type. Mapped input types are automatically * converted by RequestHandlerComponent during the startup() callback. * * @param string $type The type alias being converted, ie. json * @param array $handler The handler array for the type. The first index should * be the handling callback, all other arguments should be additional parameters * for the handler. * @return void * @throws CakeException */ public function addInputType($type, $handler) { if (!is_array($handler) || !isset($handler[0]) || !is_callable($handler[0])) { throw new CakeException(__d('cake_dev', 'You must give a handler callback.')); } $this->_inputTypeMap[$type] = $handler; } /** * Getter/setter for viewClassMap * * @param array|string $type The type string or array with format `array('type' => 'viewClass')` to map one or more * @param array $viewClass The viewClass to be used for the type without `View` appended * @return array|string Returns viewClass when only string $type is set, else array with viewClassMap */ public function viewClassMap($type = null, $viewClass = null) { if (!$viewClass && is_string($type) && isset($this->_viewClassMap[$type])) { return $this->_viewClassMap[$type]; } if (is_string($type)) { $this->_viewClassMap[$type] = $viewClass; } elseif (is_array($type)) { foreach ($type as $key => $value) { $this->viewClassMap($key, $value); } } return $this->_viewClassMap; } } cakephp-2.8.0/lib/Cake/Controller/Component/SecurityComponent.php000066400000000000000000000436071265552240500250550ustar00rootroot00000000000000request = $controller->request; $this->_action = $this->request->params['action']; $this->_methodsRequired($controller); $this->_secureRequired($controller); $this->_authRequired($controller); $hasData = !empty($this->request->data); $isNotRequestAction = ( !isset($controller->request->params['requested']) || $controller->request->params['requested'] != 1 ); if ($this->_action === $this->blackHoleCallback) { return $this->blackHole($controller, 'auth'); } if (!in_array($this->_action, (array)$this->unlockedActions) && $hasData && $isNotRequestAction) { if ($this->validatePost && $this->_validatePost($controller) === false) { return $this->blackHole($controller, 'auth'); } if ($this->csrfCheck && $this->_validateCsrf($controller) === false) { return $this->blackHole($controller, 'csrf'); } } $this->generateToken($controller->request); if ($hasData && is_array($controller->request->data)) { unset($controller->request->data['_Token']); } } /** * Sets the actions that require a POST request, or empty for all actions * * @return void * @deprecated 3.0.0 Use CakeRequest::onlyAllow() instead. * @link http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html#SecurityComponent::requirePost */ public function requirePost() { $args = func_get_args(); $this->_requireMethod('Post', $args); } /** * Sets the actions that require a GET request, or empty for all actions * * @deprecated 3.0.0 Use CakeRequest::onlyAllow() instead. * @return void */ public function requireGet() { $args = func_get_args(); $this->_requireMethod('Get', $args); } /** * Sets the actions that require a PUT request, or empty for all actions * * @deprecated 3.0.0 Use CakeRequest::onlyAllow() instead. * @return void */ public function requirePut() { $args = func_get_args(); $this->_requireMethod('Put', $args); } /** * Sets the actions that require a DELETE request, or empty for all actions * * @deprecated 3.0.0 Use CakeRequest::onlyAllow() instead. * @return void */ public function requireDelete() { $args = func_get_args(); $this->_requireMethod('Delete', $args); } /** * Sets the actions that require a request that is SSL-secured, or empty for all actions * * @return void * @link http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html#SecurityComponent::requireSecure */ public function requireSecure() { $args = func_get_args(); $this->_requireMethod('Secure', $args); } /** * Sets the actions that require whitelisted form submissions. * * Adding actions with this method will enforce the restrictions * set in SecurityComponent::$allowedControllers and * SecurityComponent::$allowedActions. * * @return void * @link http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html#SecurityComponent::requireAuth */ public function requireAuth() { $args = func_get_args(); $this->_requireMethod('Auth', $args); } /** * Black-hole an invalid request with a 400 error or custom callback. If SecurityComponent::$blackHoleCallback * is specified, it will use this callback by executing the method indicated in $error * * @param Controller $controller Instantiating controller * @param string $error Error method * @return mixed If specified, controller blackHoleCallback's response, or no return otherwise * @see SecurityComponent::$blackHoleCallback * @link http://book.cakephp.org/2.0/en/core-libraries/components/security-component.html#handling-blackhole-callbacks * @throws BadRequestException */ public function blackHole(Controller $controller, $error = '') { if (!$this->blackHoleCallback) { throw new BadRequestException(__d('cake_dev', 'The request has been black-holed')); } return $this->_callback($controller, $this->blackHoleCallback, array($error)); } /** * Sets the actions that require a $method HTTP request, or empty for all actions * * @param string $method The HTTP method to assign controller actions to * @param array $actions Controller actions to set the required HTTP method to. * @return void */ protected function _requireMethod($method, $actions = array()) { if (isset($actions[0]) && is_array($actions[0])) { $actions = $actions[0]; } $this->{'require' . $method} = (empty($actions)) ? array('*') : $actions; } /** * Check if HTTP methods are required * * @param Controller $controller Instantiating controller * @return bool True if $method is required */ protected function _methodsRequired(Controller $controller) { foreach (array('Post', 'Get', 'Put', 'Delete') as $method) { $property = 'require' . $method; if (is_array($this->$property) && !empty($this->$property)) { $require = $this->$property; if (in_array($this->_action, $require) || $this->$property === array('*')) { if (!$this->request->is($method)) { if (!$this->blackHole($controller, $method)) { return false; } } } } } return true; } /** * Check if access requires secure connection * * @param Controller $controller Instantiating controller * @return bool True if secure connection required */ protected function _secureRequired(Controller $controller) { if (is_array($this->requireSecure) && !empty($this->requireSecure)) { $requireSecure = $this->requireSecure; if (in_array($this->_action, $requireSecure) || $this->requireSecure === array('*')) { if (!$this->request->is('ssl')) { if (!$this->blackHole($controller, 'secure')) { return false; } } } } return true; } /** * Check if authentication is required * * @param Controller $controller Instantiating controller * @return bool|null True if authentication required */ protected function _authRequired(Controller $controller) { if (is_array($this->requireAuth) && !empty($this->requireAuth) && !empty($this->request->data)) { $requireAuth = $this->requireAuth; if (in_array($this->request->params['action'], $requireAuth) || $this->requireAuth === array('*')) { if (!isset($controller->request->data['_Token'])) { if (!$this->blackHole($controller, 'auth')) { return null; } } if ($this->Session->check('_Token')) { $tData = $this->Session->read('_Token'); if (!empty($tData['allowedControllers']) && !in_array($this->request->params['controller'], $tData['allowedControllers']) || !empty($tData['allowedActions']) && !in_array($this->request->params['action'], $tData['allowedActions']) ) { if (!$this->blackHole($controller, 'auth')) { return null; } } } else { if (!$this->blackHole($controller, 'auth')) { return null; } } } } return true; } /** * Validate submitted form * * @param Controller $controller Instantiating controller * @return bool true if submitted form is valid */ protected function _validatePost(Controller $controller) { if (empty($controller->request->data)) { return true; } $data = $controller->request->data; if (!isset($data['_Token']) || !isset($data['_Token']['fields']) || !isset($data['_Token']['unlocked'])) { return false; } $locked = ''; $check = $controller->request->data; $token = urldecode($check['_Token']['fields']); $unlocked = urldecode($check['_Token']['unlocked']); if (strpos($token, ':')) { list($token, $locked) = explode(':', $token, 2); } unset($check['_Token']); $locked = explode('|', $locked); $unlocked = explode('|', $unlocked); $lockedFields = array(); $fields = Hash::flatten($check); $fieldList = array_keys($fields); $multi = array(); foreach ($fieldList as $i => $key) { if (preg_match('/(\.\d+){1,10}$/', $key)) { $multi[$i] = preg_replace('/(\.\d+){1,10}$/', '', $key); unset($fieldList[$i]); } } if (!empty($multi)) { $fieldList += array_unique($multi); } $unlockedFields = array_unique( array_merge((array)$this->disabledFields, (array)$this->unlockedFields, $unlocked) ); foreach ($fieldList as $i => $key) { $isLocked = (is_array($locked) && in_array($key, $locked)); if (!empty($unlockedFields)) { foreach ($unlockedFields as $off) { $off = explode('.', $off); $field = array_values(array_intersect(explode('.', $key), $off)); $isUnlocked = ($field === $off); if ($isUnlocked) { break; } } } if ($isUnlocked || $isLocked) { unset($fieldList[$i]); if ($isLocked) { $lockedFields[$key] = $fields[$key]; } } } sort($unlocked, SORT_STRING); sort($fieldList, SORT_STRING); ksort($lockedFields, SORT_STRING); $fieldList += $lockedFields; $unlocked = implode('|', $unlocked); $hashParts = array( $this->request->here(), serialize($fieldList), $unlocked, Configure::read('Security.salt') ); $check = Security::hash(implode('', $hashParts), 'sha1'); return ($token === $check); } /** * Manually add CSRF token information into the provided request object. * * @param CakeRequest $request The request object to add into. * @return bool */ public function generateToken(CakeRequest $request) { if (isset($request->params['requested']) && $request->params['requested'] === 1) { if ($this->Session->check('_Token')) { $request->params['_Token'] = $this->Session->read('_Token'); } return false; } $authKey = Security::generateAuthKey(); $token = array( 'key' => $authKey, 'allowedControllers' => $this->allowedControllers, 'allowedActions' => $this->allowedActions, 'unlockedFields' => array_merge($this->disabledFields, $this->unlockedFields), 'csrfTokens' => array() ); $tokenData = array(); if ($this->Session->check('_Token')) { $tokenData = $this->Session->read('_Token'); if (!empty($tokenData['csrfTokens']) && is_array($tokenData['csrfTokens'])) { $token['csrfTokens'] = $this->_expireTokens($tokenData['csrfTokens']); } } if ($this->csrfUseOnce || empty($token['csrfTokens'])) { $token['csrfTokens'][$authKey] = strtotime($this->csrfExpires); } if (!$this->csrfUseOnce) { $csrfTokens = array_keys($token['csrfTokens']); $authKey = $csrfTokens[0]; $token['key'] = $authKey; $token['csrfTokens'][$authKey] = strtotime($this->csrfExpires); } $this->Session->write('_Token', $token); $request->params['_Token'] = array( 'key' => $token['key'], 'unlockedFields' => $token['unlockedFields'] ); return true; } /** * Validate that the controller has a CSRF token in the POST data * and that the token is legit/not expired. If the token is valid * it will be removed from the list of valid tokens. * * @param Controller $controller A controller to check * @return bool Valid csrf token. */ protected function _validateCsrf(Controller $controller) { $token = $this->Session->read('_Token'); $requestToken = $controller->request->data('_Token.key'); if (isset($token['csrfTokens'][$requestToken]) && $token['csrfTokens'][$requestToken] >= time()) { if ($this->csrfUseOnce) { $this->Session->delete('_Token.csrfTokens.' . $requestToken); } return true; } return false; } /** * Expire CSRF nonces and remove them from the valid tokens. * Uses a simple timeout to expire the tokens. * * @param array $tokens An array of nonce => expires. * @return array An array of nonce => expires. */ protected function _expireTokens($tokens) { $now = time(); foreach ($tokens as $nonce => $expires) { if ($expires < $now) { unset($tokens[$nonce]); } } $overflow = count($tokens) - $this->csrfLimit; if ($overflow > 0) { $tokens = array_slice($tokens, $overflow + 1, null, true); } return $tokens; } /** * Calls a controller callback method * * @param Controller $controller Controller to run callback on * @param string $method Method to execute * @param array $params Parameters to send to method * @return mixed Controller callback method's response * @throws BadRequestException When a the blackholeCallback is not callable. */ protected function _callback(Controller $controller, $method, $params = array()) { if (!is_callable(array($controller, $method))) { throw new BadRequestException(__d('cake_dev', 'The request has been black-holed')); } return call_user_func_array(array(&$controller, $method), empty($params) ? null : $params); } } cakephp-2.8.0/lib/Cake/Controller/Component/SessionComponent.php000066400000000000000000000142121265552240500246570ustar00rootroot00000000000000Session->write('Controller.sessKey', 'session value'); * * @param string $name The name of the key your are setting in the session. * This should be in a Controller.key format for better organizing * @param string $value The value you want to store in a session. * @return bool Success * @link http://book.cakephp.org/2.0/en/core-libraries/components/sessions.html#SessionComponent::write */ public function write($name, $value = null) { return CakeSession::write($name, $value); } /** * Reads a session value for a key or returns values for all keys. * * In your controller: $this->Session->read('Controller.sessKey'); * Calling the method without a param will return all session vars * * @param string $name the name of the session key you want to read * @return mixed value from the session vars * @link http://book.cakephp.org/2.0/en/core-libraries/components/sessions.html#SessionComponent::read */ public function read($name = null) { return CakeSession::read($name); } /** * Deletes a session value for a key. * * In your controller: $this->Session->delete('Controller.sessKey'); * * @param string $name the name of the session key you want to delete * @return bool true is session variable is set and can be deleted, false is variable was not set. * @link http://book.cakephp.org/2.0/en/core-libraries/components/sessions.html#SessionComponent::delete */ public function delete($name) { return CakeSession::delete($name); } /** * Reads and deletes a session value for a key. * * In your controller: `$this->Session->consume('Controller.sessKey');` * * @param string $name the name of the session key you want to read * @return mixed values from the session vars */ public function consume($name) { return CakeSession::consume($name); } /** * Checks if a session variable is set. * * In your controller: $this->Session->check('Controller.sessKey'); * * @param string $name the name of the session key you want to check * @return bool true is session variable is set, false if not * @link http://book.cakephp.org/2.0/en/core-libraries/components/sessions.html#SessionComponent::check */ public function check($name) { return CakeSession::check($name); } /** * Used to determine the last error in a session. * * In your controller: $this->Session->error(); * * @return string Last session error */ public function error() { return CakeSession::error(); } /** * Used to set a session variable that can be used to output messages in the view. * * In your controller: $this->Session->setFlash('This has been saved'); * * Additional params below can be passed to customize the output, or the Message.[key]. * You can also set additional parameters when rendering flash messages. See SessionHelper::flash() * for more information on how to do that. * * @param string $message Message to be flashed * @param string $element Element to wrap flash message in. * @param array $params Parameters to be sent to layout as view variables * @param string $key Message key, default is 'flash' * @return void * @link http://book.cakephp.org/2.0/en/core-libraries/components/sessions.html#creating-notification-messages * @deprecated 3.0.0 Since 2.7, use the FlashComponent instead. */ public function setFlash($message, $element = 'default', $params = array(), $key = 'flash') { CakeSession::write('Message.' . $key, compact('message', 'element', 'params')); } /** * Used to renew a session id * * In your controller: $this->Session->renew(); * * @return void */ public function renew() { return CakeSession::renew(); } /** * Used to check for a valid session. * * In your controller: $this->Session->valid(); * * @return bool true is session is valid, false is session is invalid */ public function valid() { return CakeSession::valid(); } /** * Used to destroy sessions * * In your controller: $this->Session->destroy(); * * @return void * @link http://book.cakephp.org/2.0/en/core-libraries/components/sessions.html#SessionComponent::destroy */ public function destroy() { return CakeSession::destroy(); } /** * Get/Set the session id. * * When fetching the session id, the session will be started * if it has not already been started. When setting the session id, * the session will not be started. * * @param string $id Id to use (optional) * @return string The current session id. */ public function id($id = null) { if (empty($id)) { CakeSession::start(); } return CakeSession::id($id); } /** * Returns a bool, whether or not the session has been started. * * @return bool */ public function started() { return CakeSession::started(); } } cakephp-2.8.0/lib/Cake/Controller/ComponentCollection.php000066400000000000000000000106431265552240500233710ustar00rootroot00000000000000components)) { return; } $this->_Controller = $Controller; $components = ComponentCollection::normalizeObjectArray($Controller->components); foreach ($components as $name => $properties) { $Controller->{$name} = $this->load($properties['class'], $properties['settings']); } } /** * Set the controller associated with the collection. * * @param Controller $Controller Controller to set * @return void */ public function setController(Controller $Controller) { $this->_Controller = $Controller; } /** * Get the controller associated with the collection. * * @return Controller Controller instance */ public function getController() { return $this->_Controller; } /** * Loads/constructs a component. Will return the instance in the registry if it already exists. * You can use `$settings['enabled'] = false` to disable callbacks on a component when loading it. * Callbacks default to on. Disabled component methods work as normal, only callbacks are disabled. * * You can alias your component as an existing component by setting the 'className' key, i.e., * ``` * public $components = array( * 'Email' => array( * 'className' => 'AliasedEmail' * ); * ); * ``` * All calls to the `Email` component would use `AliasedEmail` instead. * * @param string $component Component name to load * @param array $settings Settings for the component. * @return Component A component object, Either the existing loaded component or a new one. * @throws MissingComponentException when the component could not be found */ public function load($component, $settings = array()) { if (isset($settings['className'])) { $alias = $component; $component = $settings['className']; } list($plugin, $name) = pluginSplit($component, true); if (!isset($alias)) { $alias = $name; } if (isset($this->_loaded[$alias])) { return $this->_loaded[$alias]; } $componentClass = $name . 'Component'; App::uses($componentClass, $plugin . 'Controller/Component'); if (!class_exists($componentClass)) { throw new MissingComponentException(array( 'class' => $componentClass, 'plugin' => substr($plugin, 0, -1) )); } $this->_loaded[$alias] = new $componentClass($this, $settings); $enable = isset($settings['enabled']) ? $settings['enabled'] : true; if ($enable) { $this->enable($alias); } return $this->_loaded[$alias]; } /** * Returns the implemented events that will get routed to the trigger function * in order to dispatch them separately on each component * * @return array */ public function implementedEvents() { return array( 'Controller.initialize' => array('callable' => 'trigger'), 'Controller.startup' => array('callable' => 'trigger'), 'Controller.beforeRender' => array('callable' => 'trigger'), 'Controller.beforeRedirect' => array('callable' => 'trigger'), 'Controller.shutdown' => array('callable' => 'trigger'), ); } } cakephp-2.8.0/lib/Cake/Controller/Controller.php000066400000000000000000001113361265552240500215370ustar00rootroot00000000000000request`. The request object contains all the POST, GET and FILES * that were part of the request. * * After performing the required actions, controllers are responsible for creating a response. This usually * takes the form of a generated View, or possibly a redirection to another controller action. In either case * `$this->response` allows you to manipulate all aspects of the response. * * Controllers are created by Dispatcher based on request parameters and routing. By default controllers and actions * use conventional names. For example `/posts/index` maps to `PostsController::index()`. You can re-map URLs * using Router::connect(). * * @package Cake.Controller * @property AclComponent $Acl * @property AuthComponent $Auth * @property CookieComponent $Cookie * @property EmailComponent $Email * @property PaginatorComponent $Paginator * @property RequestHandlerComponent $RequestHandler * @property SecurityComponent $Security * @property SessionComponent $Session * @property FlashComponent $Flash * @link http://book.cakephp.org/2.0/en/controllers.html */ class Controller extends Object implements CakeEventListener { /** * The name of this controller. Controller names are plural, named after the model they manipulate. * * @var string * @link http://book.cakephp.org/2.0/en/controllers.html#controller-attributes */ public $name = null; /** * An array containing the class names of models this controller uses. * * Example: `public $uses = array('Product', 'Post', 'Comment');` * * Can be set to several values to express different options: * * - `true` Use the default inflected model name. * - `array()` Use only models defined in the parent class. * - `false` Use no models at all, do not merge with parent class either. * - `array('Post', 'Comment')` Use only the Post and Comment models. Models * Will also be merged with the parent class. * * The default value is `true`. * * @var mixed * @link http://book.cakephp.org/2.0/en/controllers.html#components-helpers-and-uses */ public $uses = true; /** * An array containing the names of helpers this controller uses. The array elements should * not contain the "Helper" part of the class name. * * Example: `public $helpers = array('Html', 'Js', 'Time', 'Ajax');` * * @var mixed * @link http://book.cakephp.org/2.0/en/controllers.html#components-helpers-and-uses */ public $helpers = array(); /** * An instance of a CakeRequest object that contains information about the current request. * This object contains all the information about a request and several methods for reading * additional information about the request. * * @var CakeRequest * @link http://book.cakephp.org/2.0/en/controllers/request-response.html#cakerequest */ public $request; /** * An instance of a CakeResponse object that contains information about the impending response * * @var CakeResponse * @link http://book.cakephp.org/2.0/en/controllers/request-response.html#cakeresponse */ public $response; /** * The class name to use for creating the response object. * * @var string */ protected $_responseClass = 'CakeResponse'; /** * The name of the views subfolder containing views for this controller. * * @var string */ public $viewPath = null; /** * The name of the layouts subfolder containing layouts for this controller. * * @var string */ public $layoutPath = null; /** * Contains variables to be handed to the view. * * @var array */ public $viewVars = array(); /** * The name of the view file to render. The name specified * is the filename in /app/View/ without the .ctp extension. * * @var string */ public $view = null; /** * The name of the layout file to render the view inside of. The name specified * is the filename of the layout in /app/View/Layouts without the .ctp * extension. * * @var string */ public $layout = 'default'; /** * Set to true to automatically render the view * after action logic. * * @var bool */ public $autoRender = true; /** * Set to true to automatically render the layout around views. * * @var bool */ public $autoLayout = true; /** * Instance of ComponentCollection used to handle callbacks. * * @var ComponentCollection */ public $Components = null; /** * Array containing the names of components this controller uses. Component names * should not contain the "Component" portion of the class name. * * Example: `public $components = array('Session', 'RequestHandler', 'Acl');` * * @var array * @link http://book.cakephp.org/2.0/en/controllers/components.html */ public $components = array('Session', 'Flash'); /** * The name of the View class this controller sends output to. * * @var string */ public $viewClass = 'View'; /** * Instance of the View created during rendering. Won't be set until after * Controller::render() is called. * * @var View */ public $View; /** * File extension for view templates. Defaults to CakePHP's conventional ".ctp". * * @var string */ public $ext = '.ctp'; /** * Automatically set to the name of a plugin. * * @var string */ public $plugin = null; /** * Used to define methods a controller that will be cached. To cache a * single action, the value is set to an array containing keys that match * action names and values that denote cache expiration times (in seconds). * * Example: * * ``` * public $cacheAction = array( * 'view/23/' => 21600, * 'recalled/' => 86400 * ); * ``` * * $cacheAction can also be set to a strtotime() compatible string. This * marks all the actions in the controller for view caching. * * @var mixed * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/cache.html#additional-configuration-options */ public $cacheAction = false; /** * Holds all params passed and named. * * @var mixed */ public $passedArgs = array(); /** * Triggers Scaffolding * * @var mixed * @link http://book.cakephp.org/2.0/en/controllers/scaffolding.html */ public $scaffold = false; /** * Holds current methods of the controller. This is a list of all the methods reachable * via URL. Modifying this array will allow you to change which methods can be reached. * * @var array */ public $methods = array(); /** * This controller's primary model class name, the Inflector::singularize()'ed version of * the controller's $name property. * * Example: For a controller named 'Comments', the modelClass would be 'Comment' * * @var string */ public $modelClass = null; /** * This controller's model key name, an underscored version of the controller's $modelClass property. * * Example: For a controller named 'ArticleComments', the modelKey would be 'article_comment' * * @var string */ public $modelKey = null; /** * Holds any validation errors produced by the last call of the validateErrors() method. * * @var array */ public $validationErrors = null; /** * The class name of the parent class you wish to merge with. * Typically this is AppController, but you may wish to merge vars with a different * parent class. * * @var string */ protected $_mergeParent = 'AppController'; /** * Instance of the CakeEventManager this controller is using * to dispatch inner events. * * @var CakeEventManager */ protected $_eventManager = null; /** * Constructor. * * @param CakeRequest $request Request object for this controller. Can be null for testing, * but expect that features that use the request parameters will not work. * @param CakeResponse $response Response object for this controller. */ public function __construct($request = null, $response = null) { if ($this->name === null) { $this->name = substr(get_class($this), 0, -10); } if (!$this->viewPath) { $this->viewPath = $this->name; } $this->modelClass = Inflector::singularize($this->name); $this->modelKey = Inflector::underscore($this->modelClass); $this->Components = new ComponentCollection(); $childMethods = get_class_methods($this); $parentMethods = get_class_methods('Controller'); $this->methods = array_diff($childMethods, $parentMethods); if ($request instanceof CakeRequest) { $this->setRequest($request); } if ($response instanceof CakeResponse) { $this->response = $response; } parent::__construct(); } /** * Provides backwards compatibility to avoid problems with empty and isset to alias properties. * Lazy loads models using the loadModel() method if declared in $uses * * @param string $name Property name to check. * @return bool */ public function __isset($name) { switch ($name) { case 'base': case 'here': case 'webroot': case 'data': case 'action': case 'params': return true; } if (is_array($this->uses)) { foreach ($this->uses as $modelClass) { list($plugin, $class) = pluginSplit($modelClass, true); if ($name === $class) { return $this->loadModel($modelClass); } } } if ($name === $this->modelClass) { list($plugin, $class) = pluginSplit($name, true); if (!$plugin) { $plugin = $this->plugin ? $this->plugin . '.' : null; } return $this->loadModel($plugin . $this->modelClass); } return false; } /** * Provides backwards compatibility access to the request object properties. * Also provides the params alias. * * @param string $name The name of the requested value * @return mixed The requested value for valid variables/aliases else null */ public function __get($name) { switch ($name) { case 'base': case 'here': case 'webroot': case 'data': return $this->request->{$name}; case 'action': return isset($this->request->params['action']) ? $this->request->params['action'] : ''; case 'params': return $this->request; case 'paginate': return $this->Components->load('Paginator')->settings; } if (isset($this->{$name})) { return $this->{$name}; } return null; } /** * Provides backwards compatibility access for setting values to the request object. * * @param string $name Property name to set. * @param mixed $value Value to set. * @return void */ public function __set($name, $value) { switch ($name) { case 'base': case 'here': case 'webroot': case 'data': $this->request->{$name} = $value; return; case 'action': $this->request->params['action'] = $value; return; case 'params': $this->request->params = $value; return; case 'paginate': $this->Components->load('Paginator')->settings = $value; return; } $this->{$name} = $value; } /** * Sets the request objects and configures a number of controller properties * based on the contents of the request. The properties that get set are * * - $this->request - To the $request parameter * - $this->plugin - To the $request->params['plugin'] * - $this->view - To the $request->params['action'] * - $this->autoLayout - To the false if $request->params['bare']; is set. * - $this->autoRender - To false if $request->params['return'] == 1 * - $this->passedArgs - The the combined results of params['named'] and params['pass] * * @param CakeRequest $request Request instance. * @return void */ public function setRequest(CakeRequest $request) { $this->request = $request; $this->plugin = isset($request->params['plugin']) ? Inflector::camelize($request->params['plugin']) : null; $this->view = isset($request->params['action']) ? $request->params['action'] : null; if (isset($request->params['pass']) && isset($request->params['named'])) { $this->passedArgs = array_merge($request->params['pass'], $request->params['named']); } if (!empty($request->params['return']) && $request->params['return'] == 1) { $this->autoRender = false; } if (!empty($request->params['bare'])) { $this->autoLayout = false; } } /** * Dispatches the controller action. Checks that the action * exists and isn't private. * * @param CakeRequest $request Request instance. * @return mixed The resulting response. * @throws PrivateActionException When actions are not public or prefixed by _ * @throws MissingActionException When actions are not defined and scaffolding is * not enabled. */ public function invokeAction(CakeRequest $request) { try { $method = new ReflectionMethod($this, $request->params['action']); if ($this->_isPrivateAction($method, $request)) { throw new PrivateActionException(array( 'controller' => $this->name . "Controller", 'action' => $request->params['action'] )); } return $method->invokeArgs($this, $request->params['pass']); } catch (ReflectionException $e) { if ($this->scaffold !== false) { return $this->_getScaffold($request); } throw new MissingActionException(array( 'controller' => $this->name . "Controller", 'action' => $request->params['action'] )); } } /** * Check if the request's action is marked as private, with an underscore, * or if the request is attempting to directly accessing a prefixed action. * * @param ReflectionMethod $method The method to be invoked. * @param CakeRequest $request The request to check. * @return bool */ protected function _isPrivateAction(ReflectionMethod $method, CakeRequest $request) { $privateAction = ( $method->name[0] === '_' || !$method->isPublic() || !in_array($method->name, $this->methods) ); $prefixes = array_map('strtolower', Router::prefixes()); if (!$privateAction && !empty($prefixes)) { if (empty($request->params['prefix']) && strpos($request->params['action'], '_') > 0) { list($prefix) = explode('_', $request->params['action']); $privateAction = in_array(strtolower($prefix), $prefixes); } } return $privateAction; } /** * Returns a scaffold object to use for dynamically scaffolded controllers. * * @param CakeRequest $request Request instance. * @return Scaffold */ protected function _getScaffold(CakeRequest $request) { return new Scaffold($this, $request); } /** * Merge components, helpers, and uses vars from * Controller::$_mergeParent and PluginAppController. * * @return void */ protected function _mergeControllerVars() { $pluginController = $pluginDot = null; $mergeParent = is_subclass_of($this, $this->_mergeParent); $pluginVars = array(); $appVars = array(); if (!empty($this->plugin)) { $pluginController = $this->plugin . 'AppController'; if (!is_subclass_of($this, $pluginController)) { $pluginController = null; } $pluginDot = $this->plugin . '.'; } if ($pluginController) { $merge = array('components', 'helpers'); $this->_mergeVars($merge, $pluginController); } if ($mergeParent || !empty($pluginController)) { $appVars = get_class_vars($this->_mergeParent); $merge = array('components', 'helpers'); $this->_mergeVars($merge, $this->_mergeParent, true); } if ($this->uses === null) { $this->uses = false; } if ($this->uses === true) { $this->uses = array($pluginDot . $this->modelClass); } if (isset($appVars['uses']) && $appVars['uses'] === $this->uses) { array_unshift($this->uses, $pluginDot . $this->modelClass); } if ($pluginController) { $pluginVars = get_class_vars($pluginController); } if ($this->uses !== false) { $this->_mergeUses($pluginVars); $this->_mergeUses($appVars); } else { $this->uses = array(); $this->modelClass = ''; } } /** * Helper method for merging the $uses property together. * * Merges the elements not already in $this->uses into * $this->uses. * * @param array $merge The data to merge in. * @return void */ protected function _mergeUses($merge) { if (!isset($merge['uses'])) { return; } if ($merge['uses'] === true) { return; } $this->uses = array_merge( $this->uses, array_diff($merge['uses'], $this->uses) ); } /** * Returns a list of all events that will fire in the controller during its lifecycle. * You can override this function to add your own listener callbacks * * @return array */ public function implementedEvents() { return array( 'Controller.initialize' => 'beforeFilter', 'Controller.beforeRender' => 'beforeRender', 'Controller.beforeRedirect' => array('callable' => 'beforeRedirect', 'passParams' => true), 'Controller.shutdown' => 'afterFilter' ); } /** * Loads Model classes based on the uses property * see Controller::loadModel(); for more info. * Loads Components and prepares them for initialization. * * @return mixed true if models found and instance created. * @see Controller::loadModel() * @link http://book.cakephp.org/2.0/en/controllers.html#Controller::constructClasses * @throws MissingModelException */ public function constructClasses() { $this->_mergeControllerVars(); if ($this->uses) { $this->uses = (array)$this->uses; list(, $this->modelClass) = pluginSplit(reset($this->uses)); } $this->Components->init($this); return true; } /** * Returns the CakeEventManager manager instance that is handling any callbacks. * You can use this instance to register any new listeners or callbacks to the * controller events, or create your own events and trigger them at will. * * @return CakeEventManager */ public function getEventManager() { if (empty($this->_eventManager)) { $this->_eventManager = new CakeEventManager(); $this->_eventManager->attach($this->Components); $this->_eventManager->attach($this); } return $this->_eventManager; } /** * Perform the startup process for this controller. * Fire the Components and Controller callbacks in the correct order. * * - Initializes components, which fires their `initialize` callback * - Calls the controller `beforeFilter`. * - triggers Component `startup` methods. * * @return void * @triggers Controller.initialize $this * @triggers Controller.startup $this */ public function startupProcess() { $this->getEventManager()->dispatch(new CakeEvent('Controller.initialize', $this)); $this->getEventManager()->dispatch(new CakeEvent('Controller.startup', $this)); } /** * Perform the various shutdown processes for this controller. * Fire the Components and Controller callbacks in the correct order. * * - triggers the component `shutdown` callback. * - calls the Controller's `afterFilter` method. * * @return void * @triggers Controller.shutdown $this */ public function shutdownProcess() { $this->getEventManager()->dispatch(new CakeEvent('Controller.shutdown', $this)); } /** * Queries & sets valid HTTP response codes & messages. * * @param int|array $code If $code is an integer, then the corresponding code/message is * returned if it exists, null if it does not exist. If $code is an array, * then the 'code' and 'message' keys of each nested array are added to the default * HTTP codes. Example: * * httpCodes(404); // returns array(404 => 'Not Found') * * httpCodes(array( * 701 => 'Unicorn Moved', * 800 => 'Unexpected Minotaur' * )); // sets these new values, and returns true * * @return array Associative array of the HTTP codes as keys, and the message * strings as values, or null of the given $code does not exist. * @deprecated 3.0.0 Since 2.4. Will be removed in 3.0. Use CakeResponse::httpCodes(). */ public function httpCodes($code = null) { return $this->response->httpCodes($code); } /** * Loads and instantiates models required by this controller. * If the model is non existent, it will throw a missing database table error, as CakePHP generates * dynamic models for the time being. * * @param string $modelClass Name of model class to load * @param int|string $id Initial ID the instanced model class should have * @return bool True if the model was found * @throws MissingModelException if the model class cannot be found. */ public function loadModel($modelClass = null, $id = null) { if ($modelClass === null) { $modelClass = $this->modelClass; } $this->uses = ($this->uses) ? (array)$this->uses : array(); if (!in_array($modelClass, $this->uses, true)) { $this->uses[] = $modelClass; } list($plugin, $modelClass) = pluginSplit($modelClass, true); $this->{$modelClass} = ClassRegistry::init(array( 'class' => $plugin . $modelClass, 'alias' => $modelClass, 'id' => $id )); if (!$this->{$modelClass}) { throw new MissingModelException($modelClass); } return true; } /** * Redirects to given $url, after turning off $this->autoRender. * Script execution is halted after the redirect. * * @param string|array $url A string or array-based URL pointing to another location within the app, * or an absolute URL * @param int|array|null $status HTTP status code (eg: 301). Defaults to 302 when null is passed. * @param bool $exit If true, exit() will be called after the redirect * @return \Cake\Network\Response|null * @triggers Controller.beforeRedirect $this, array($url, $status, $exit) * @link http://book.cakephp.org/2.0/en/controllers.html#Controller::redirect */ public function redirect($url, $status = null, $exit = true) { $this->autoRender = false; if (is_array($status)) { extract($status, EXTR_OVERWRITE); } $event = new CakeEvent('Controller.beforeRedirect', $this, array($url, $status, $exit)); list($event->break, $event->breakOn, $event->collectReturn) = array(true, false, true); $this->getEventManager()->dispatch($event); if ($event->isStopped()) { return null; } $response = $event->result; extract($this->_parseBeforeRedirect($response, $url, $status, $exit), EXTR_OVERWRITE); if ($url !== null) { $this->response->header('Location', Router::url($url, true)); } if (is_string($status)) { $codes = array_flip($this->response->httpCodes()); if (isset($codes[$status])) { $status = $codes[$status]; } } if ($status === null) { $status = 302; } $this->response->statusCode($status); if ($exit) { $this->response->send(); $this->_stop(); } return $this->response; } /** * Parse beforeRedirect Response * * @param mixed $response Response from beforeRedirect callback * @param string|array $url The same value of beforeRedirect * @param int $status The same value of beforeRedirect * @param bool $exit The same value of beforeRedirect * @return array Array with keys url, status and exit */ protected function _parseBeforeRedirect($response, $url, $status, $exit) { if (is_array($response) && array_key_exists(0, $response)) { foreach ($response as $resp) { if (is_array($resp) && isset($resp['url'])) { extract($resp, EXTR_OVERWRITE); } elseif ($resp !== null) { $url = $resp; } } } elseif (is_array($response)) { extract($response, EXTR_OVERWRITE); } return compact('url', 'status', 'exit'); } /** * Convenience and object wrapper method for CakeResponse::header(). * * @param string $status The header message that is being set. * @return void * @deprecated 3.0.0 Will be removed in 3.0. Use CakeResponse::header(). */ public function header($status) { $this->response->header($status); } /** * Saves a variable for use inside a view template. * * @param string|array $one A string or an array of data. * @param string|array $two Value in case $one is a string (which then works as the key). * Unused if $one is an associative array, otherwise serves as the values to $one's keys. * @return void * @link http://book.cakephp.org/2.0/en/controllers.html#interacting-with-views */ public function set($one, $two = null) { if (is_array($one)) { if (is_array($two)) { $data = array_combine($one, $two); } else { $data = $one; } } else { $data = array($one => $two); } $this->viewVars = $data + $this->viewVars; } /** * Internally redirects one action to another. Does not perform another HTTP request unlike Controller::redirect() * * Examples: * * ``` * setAction('another_action'); * setAction('action_with_parameters', $parameter1); * ``` * * @param string $action The new action to be 'redirected' to. * Any other parameters passed to this method will be passed as parameters to the new action. * @return mixed Returns the return value of the called action */ public function setAction($action) { $this->request->params['action'] = $action; $this->view = $action; $args = func_get_args(); unset($args[0]); return call_user_func_array(array(&$this, $action), $args); } /** * Returns number of errors in a submitted FORM. * * @return int Number of errors * @deprecated 3.0.0 This method will be removed in 3.0 */ public function validate() { $args = func_get_args(); $errors = call_user_func_array(array(&$this, 'validateErrors'), $args); if ($errors === false) { return 0; } return count($errors); } /** * Validates models passed by parameters. Takes a list of models as a variable argument. * Example: * * `$errors = $this->validateErrors($this->Article, $this->User);` * * @return array Validation errors, or false if none * @deprecated 3.0.0 This method will be removed in 3.0 */ public function validateErrors() { $objects = func_get_args(); if (empty($objects)) { return false; } $errors = array(); foreach ($objects as $object) { if (isset($this->{$object->alias})) { $object = $this->{$object->alias}; } $object->set($object->data); $errors = array_merge($errors, $object->invalidFields()); } return $this->validationErrors = (!empty($errors) ? $errors : false); } /** * Instantiates the correct view class, hands it its data, and uses it to render the view output. * * @param string $view View to use for rendering * @param string $layout Layout to use * @return CakeResponse A response object containing the rendered view. * @triggers Controller.beforeRender $this * @link http://book.cakephp.org/2.0/en/controllers.html#Controller::render */ public function render($view = null, $layout = null) { $event = new CakeEvent('Controller.beforeRender', $this); $this->getEventManager()->dispatch($event); if ($event->isStopped()) { $this->autoRender = false; return $this->response; } if (!empty($this->uses) && is_array($this->uses)) { foreach ($this->uses as $model) { list($plugin, $className) = pluginSplit($model); $this->request->params['models'][$className] = compact('plugin', 'className'); } } $this->View = $this->_getViewObject(); $models = ClassRegistry::keys(); foreach ($models as $currentModel) { $currentObject = ClassRegistry::getObject($currentModel); if ($currentObject instanceof Model) { $className = get_class($currentObject); list($plugin) = pluginSplit(App::location($className)); $this->request->params['models'][$currentObject->alias] = compact('plugin', 'className'); $this->View->validationErrors[$currentObject->alias] =& $currentObject->validationErrors; } } $this->autoRender = false; $this->response->body($this->View->render($view, $layout)); return $this->response; } /** * Returns the referring URL for this request. * * @param string $default Default URL to use if HTTP_REFERER cannot be read from headers * @param bool $local If true, restrict referring URLs to local server * @return string Referring URL * @link http://book.cakephp.org/2.0/en/controllers.html#Controller::referer */ public function referer($default = null, $local = false) { if (!$this->request) { return '/'; } $referer = $this->request->referer($local); if ($referer === '/' && $default && $default !== $referer) { return Router::url($default, !$local); } return $referer; } /** * Forces the user's browser not to cache the results of the current request. * * @return void * @link http://book.cakephp.org/2.0/en/controllers.html#Controller::disableCache * @deprecated 3.0.0 Will be removed in 3.0. Use CakeResponse::disableCache(). */ public function disableCache() { $this->response->disableCache(); } /** * Shows a message to the user for $pause seconds, then redirects to $url. * Uses flash.ctp as the default layout for the message. * Does not work if the current debug level is higher than 0. * * @param string $message Message to display to the user * @param string|array $url Relative string or array-based URL to redirect to after the time expires * @param int $pause Time to show the message * @param string $layout Layout you want to use, defaults to 'flash' * @return void * @link http://book.cakephp.org/2.0/en/controllers.html#Controller::flash * @deprecated 3.0.0 Will be removed in 3.0. Use Session::setFlash(). */ public function flash($message, $url, $pause = 1, $layout = 'flash') { $this->autoRender = false; $this->set('url', Router::url($url)); $this->set('message', $message); $this->set('pause', $pause); $this->set('pageTitle', $message); $this->render(false, $layout); } /** * Converts POST'ed form data to a model conditions array, suitable for use in a Model::find() call. * * @param array $data POST'ed data organized by model and field * @param string|array $op A string containing an SQL comparison operator, or an array matching operators * to fields * @param string $bool SQL boolean operator: AND, OR, XOR, etc. * @param bool $exclusive If true, and $op is an array, fields not included in $op will not be * included in the returned conditions * @return array|null An array of model conditions * @deprecated 3.0.0 Will be removed in 3.0. */ public function postConditions($data = array(), $op = null, $bool = 'AND', $exclusive = false) { if (!is_array($data) || empty($data)) { if (!empty($this->request->data)) { $data = $this->request->data; } else { return null; } } $cond = array(); if ($op === null) { $op = ''; } $arrayOp = is_array($op); foreach ($data as $model => $fields) { foreach ($fields as $field => $value) { $key = $model . '.' . $field; $fieldOp = $op; if ($arrayOp) { if (array_key_exists($key, $op)) { $fieldOp = $op[$key]; } elseif (array_key_exists($field, $op)) { $fieldOp = $op[$field]; } else { $fieldOp = false; } } if ($exclusive && $fieldOp === false) { continue; } $fieldOp = strtoupper(trim($fieldOp)); if ($fieldOp === 'LIKE') { $key = $key . ' LIKE'; $value = '%' . $value . '%'; } elseif ($fieldOp && $fieldOp !== '=') { $key = $key . ' ' . $fieldOp; } $cond[$key] = $value; } } if ($bool && strtoupper($bool) !== 'AND') { $cond = array($bool => $cond); } return $cond; } /** * Handles automatic pagination of model records. * * @param Model|string $object Model to paginate (e.g: model instance, or 'Model', or 'Model.InnerModel') * @param string|array $scope Conditions to use while paginating * @param array $whitelist List of allowed options for paging * @return array Model query results * @link http://book.cakephp.org/2.0/en/controllers.html#Controller::paginate */ public function paginate($object = null, $scope = array(), $whitelist = array()) { return $this->Components->load('Paginator', $this->paginate)->paginate($object, $scope, $whitelist); } /** * Called before the controller action. You can use this method to configure and customize components * or perform logic that needs to happen before each controller action. * * @return void * @link http://book.cakephp.org/2.0/en/controllers.html#request-life-cycle-callbacks */ public function beforeFilter() { } /** * Called after the controller action is run, but before the view is rendered. You can use this method * to perform logic or set view variables that are required on every request. * * @return void * @link http://book.cakephp.org/2.0/en/controllers.html#request-life-cycle-callbacks */ public function beforeRender() { } /** * The beforeRedirect method is invoked when the controller's redirect method is called but before any * further action. * * If this method returns false the controller will not continue on to redirect the request. * The $url, $status and $exit variables have same meaning as for the controller's method. You can also * return a string which will be interpreted as the URL to redirect to or return associative array with * key 'url' and optionally 'status' and 'exit'. * * @param string|array $url A string or array-based URL pointing to another location within the app, * or an absolute URL * @param int $status Optional HTTP status code (eg: 404) * @param bool $exit If true, exit() will be called after the redirect * @return mixed * false to stop redirection event, * string controllers a new redirection URL or * array with the keys url, status and exit to be used by the redirect method. * @link http://book.cakephp.org/2.0/en/controllers.html#request-life-cycle-callbacks */ public function beforeRedirect($url, $status = null, $exit = true) { } /** * Called after the controller action is run and rendered. * * @return void * @link http://book.cakephp.org/2.0/en/controllers.html#request-life-cycle-callbacks */ public function afterFilter() { } /** * This method should be overridden in child classes. * * @param string $method name of method called example index, edit, etc. * @return bool Success * @link http://book.cakephp.org/2.0/en/controllers.html#callbacks */ public function beforeScaffold($method) { return true; } /** * Alias to beforeScaffold() * * @param string $method Method name. * @return bool * @see Controller::beforeScaffold() * @deprecated 3.0.0 Will be removed in 3.0. */ protected function _beforeScaffold($method) { return $this->beforeScaffold($method); } /** * This method should be overridden in child classes. * * @param string $method name of method called either edit or update. * @return bool Success * @link http://book.cakephp.org/2.0/en/controllers.html#callbacks */ public function afterScaffoldSave($method) { return true; } /** * Alias to afterScaffoldSave() * * @param string $method Method name. * @return bool * @see Controller::afterScaffoldSave() * @deprecated 3.0.0 Will be removed in 3.0. */ protected function _afterScaffoldSave($method) { return $this->afterScaffoldSave($method); } /** * This method should be overridden in child classes. * * @param string $method name of method called either edit or update. * @return bool Success * @link http://book.cakephp.org/2.0/en/controllers.html#callbacks */ public function afterScaffoldSaveError($method) { return true; } /** * Alias to afterScaffoldSaveError() * * @param string $method Method name. * @return bool * @see Controller::afterScaffoldSaveError() * @deprecated 3.0.0 Will be removed in 3.0. */ protected function _afterScaffoldSaveError($method) { return $this->afterScaffoldSaveError($method); } /** * This method should be overridden in child classes. * If not it will render a scaffold error. * Method MUST return true in child classes * * @param string $method name of method called example index, edit, etc. * @return bool Success * @link http://book.cakephp.org/2.0/en/controllers.html#callbacks */ public function scaffoldError($method) { return false; } /** * Alias to scaffoldError() * * @param string $method Method name. * @return bool * @see Controller::scaffoldError() * @deprecated 3.0.0 Will be removed in 3.0. */ protected function _scaffoldError($method) { return $this->scaffoldError($method); } /** * Constructs the view class instance based on the controller property * * @return View */ protected function _getViewObject() { $viewClass = $this->viewClass; if ($this->viewClass !== 'View') { list($plugin, $viewClass) = pluginSplit($viewClass, true); $viewClass = $viewClass . 'View'; App::uses($viewClass, $plugin . 'View'); } return new $viewClass($this); } } cakephp-2.8.0/lib/Cake/Controller/Scaffold.php000066400000000000000000000331551265552240500211370ustar00rootroot00000000000000controller = $controller; $count = count($this->_passedVars); for ($j = 0; $j < $count; $j++) { $var = $this->_passedVars[$j]; $this->{$var} = $controller->{$var}; } $this->redirect = array('action' => 'index'); $this->modelClass = $controller->modelClass; $this->modelKey = $controller->modelKey; if (!is_object($this->controller->{$this->modelClass})) { throw new MissingModelException($this->modelClass); } $this->ScaffoldModel = $this->controller->{$this->modelClass}; $this->scaffoldTitle = Inflector::humanize(Inflector::underscore($this->viewPath)); $this->scaffoldActions = $controller->scaffold; $title = __d('cake', 'Scaffold :: ') . Inflector::humanize($request->action) . ' :: ' . $this->scaffoldTitle; $modelClass = $this->controller->modelClass; $primaryKey = $this->ScaffoldModel->primaryKey; $displayField = $this->ScaffoldModel->displayField; $singularVar = Inflector::variable($modelClass); $pluralVar = Inflector::variable($this->controller->name); $singularHumanName = Inflector::humanize(Inflector::underscore($modelClass)); $pluralHumanName = Inflector::humanize(Inflector::underscore($this->controller->name)); $scaffoldFields = array_keys($this->ScaffoldModel->schema()); $associations = $this->_associations(); $this->controller->set(compact( 'modelClass', 'primaryKey', 'displayField', 'singularVar', 'pluralVar', 'singularHumanName', 'pluralHumanName', 'scaffoldFields', 'associations' )); $this->controller->set('title_for_layout', $title); if ($this->controller->viewClass) { $this->controller->viewClass = 'Scaffold'; } $this->_validSession = ( isset($this->controller->Session) && $this->controller->Session->valid() && isset($this->controller->Flash) ); $this->_scaffold($request); } /** * Renders a view action of scaffolded model. * * @param CakeRequest $request Request Object for scaffolding * @return mixed A rendered view of a row from Models database table * @throws NotFoundException */ protected function _scaffoldView(CakeRequest $request) { if ($this->controller->beforeScaffold('view')) { if (isset($request->params['pass'][0])) { $this->ScaffoldModel->id = $request->params['pass'][0]; } if (!$this->ScaffoldModel->exists()) { throw new NotFoundException(__d('cake', 'Invalid %s', Inflector::humanize($this->modelKey))); } $this->ScaffoldModel->recursive = 1; $this->controller->request->data = $this->ScaffoldModel->read(); $this->controller->set( Inflector::variable($this->controller->modelClass), $this->request->data ); $this->controller->render($this->request['action'], $this->layout); } elseif ($this->controller->scaffoldError('view') === false) { return $this->_scaffoldError(); } } /** * Renders index action of scaffolded model. * * @param array $params Parameters for scaffolding * @return mixed A rendered view listing rows from Models database table */ protected function _scaffoldIndex($params) { if ($this->controller->beforeScaffold('index')) { $this->ScaffoldModel->recursive = 0; $this->controller->set( Inflector::variable($this->controller->name), $this->controller->paginate() ); $this->controller->render($this->request['action'], $this->layout); } elseif ($this->controller->scaffoldError('index') === false) { return $this->_scaffoldError(); } } /** * Renders an add or edit action for scaffolded model. * * @param string $action Action (add or edit) * @return void */ protected function _scaffoldForm($action = 'edit') { $this->controller->viewVars['scaffoldFields'] = array_merge( $this->controller->viewVars['scaffoldFields'], array_keys($this->ScaffoldModel->hasAndBelongsToMany) ); $this->controller->render($action, $this->layout); } /** * Saves or updates the scaffolded model. * * @param CakeRequest $request Request Object for scaffolding * @param string $action add or edit * @return mixed Success on save/update, add/edit form if data is empty or error if save or update fails * @throws NotFoundException */ protected function _scaffoldSave(CakeRequest $request, $action = 'edit') { $formAction = 'edit'; $success = __d('cake', 'updated'); if ($action === 'add') { $formAction = 'add'; $success = __d('cake', 'saved'); } if ($this->controller->beforeScaffold($action)) { if ($action === 'edit') { if (isset($request->params['pass'][0])) { $this->ScaffoldModel->id = $request['pass'][0]; } if (!$this->ScaffoldModel->exists()) { throw new NotFoundException(__d('cake', 'Invalid %s', Inflector::humanize($this->modelKey))); } } if (!empty($request->data)) { if ($action === 'create') { $this->ScaffoldModel->create(); } if ($this->ScaffoldModel->save($request->data)) { if ($this->controller->afterScaffoldSave($action)) { $message = __d('cake', 'The %1$s has been %2$s', Inflector::humanize($this->modelKey), $success ); return $this->_sendMessage($message, 'success'); } return $this->controller->afterScaffoldSaveError($action); } if ($this->_validSession) { $this->controller->Flash->set(__d('cake', 'Please correct errors below.')); } } if (empty($request->data)) { if ($this->ScaffoldModel->id) { $this->controller->data = $request->data = $this->ScaffoldModel->read(); } else { $this->controller->data = $request->data = $this->ScaffoldModel->create(); } } foreach ($this->ScaffoldModel->belongsTo as $assocName => $assocData) { $varName = Inflector::variable(Inflector::pluralize( preg_replace('/(?:_id)$/', '', $assocData['foreignKey']) )); $this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list')); } foreach ($this->ScaffoldModel->hasAndBelongsToMany as $assocName => $assocData) { $varName = Inflector::variable(Inflector::pluralize($assocName)); $this->controller->set($varName, $this->ScaffoldModel->{$assocName}->find('list')); } return $this->_scaffoldForm($formAction); } elseif ($this->controller->scaffoldError($action) === false) { return $this->_scaffoldError(); } } /** * Performs a delete on given scaffolded Model. * * @param CakeRequest $request Request for scaffolding * @return mixed Success on delete, error if delete fails * @throws MethodNotAllowedException When HTTP method is not a DELETE * @throws NotFoundException When id being deleted does not exist. */ protected function _scaffoldDelete(CakeRequest $request) { if ($this->controller->beforeScaffold('delete')) { if (!$request->is('post')) { throw new MethodNotAllowedException(); } $id = false; if (isset($request->params['pass'][0])) { $id = $request->params['pass'][0]; } $this->ScaffoldModel->id = $id; if (!$this->ScaffoldModel->exists()) { throw new NotFoundException(__d('cake', 'Invalid %s', Inflector::humanize($this->modelClass))); } if ($this->ScaffoldModel->delete()) { $message = __d('cake', 'The %1$s with id: %2$s has been deleted.', Inflector::humanize($this->modelClass), $id); return $this->_sendMessage($message, 'success'); } $message = __d('cake', 'There was an error deleting the %1$s with id: %2$s', Inflector::humanize($this->modelClass), $id ); return $this->_sendMessage($message); } elseif ($this->controller->scaffoldError('delete') === false) { return $this->_scaffoldError(); } } /** * Sends a message to the user. Either uses Sessions or flash messages depending * on the availability of a session * * @param string $message Message to display * @param string $element Flash template to use * @return \Cake\Network\Response|null */ protected function _sendMessage($message, $element = 'default') { if ($this->_validSession) { $this->controller->Flash->set($message, compact('element')); return $this->controller->redirect($this->redirect); } $this->controller->flash($message, $this->redirect); } /** * Show a scaffold error * * @return mixed A rendered view showing the error */ protected function _scaffoldError() { return $this->controller->render('error', $this->layout); } /** * When methods are now present in a controller * scaffoldView is used to call default Scaffold methods if: * `public $scaffold;` is placed in the controller's class definition. * * @param CakeRequest $request Request object for scaffolding * @return void * @throws MissingActionException When methods are not scaffolded. * @throws MissingDatabaseException When the database connection is undefined. */ protected function _scaffold(CakeRequest $request) { $db = ConnectionManager::getDataSource($this->ScaffoldModel->useDbConfig); $prefixes = Configure::read('Routing.prefixes'); $scaffoldPrefix = $this->scaffoldActions; if (isset($db)) { if (empty($this->scaffoldActions)) { $this->scaffoldActions = array( 'index', 'list', 'view', 'add', 'create', 'edit', 'update', 'delete' ); } elseif (!empty($prefixes) && in_array($scaffoldPrefix, $prefixes)) { $this->scaffoldActions = array( $scaffoldPrefix . '_index', $scaffoldPrefix . '_list', $scaffoldPrefix . '_view', $scaffoldPrefix . '_add', $scaffoldPrefix . '_create', $scaffoldPrefix . '_edit', $scaffoldPrefix . '_update', $scaffoldPrefix . '_delete' ); } if (in_array($request->params['action'], $this->scaffoldActions)) { if (!empty($prefixes)) { $request->params['action'] = str_replace($scaffoldPrefix . '_', '', $request->params['action']); } switch ($request->params['action']) { case 'index': case 'list': $this->_scaffoldIndex($request); break; case 'view': $this->_scaffoldView($request); break; case 'add': case 'create': $this->_scaffoldSave($request, 'add'); break; case 'edit': case 'update': $this->_scaffoldSave($request, 'edit'); break; case 'delete': $this->_scaffoldDelete($request); break; } } else { throw new MissingActionException(array( 'controller' => get_class($this->controller), 'action' => $request->action )); } } else { throw new MissingDatabaseException(array('connection' => $this->ScaffoldModel->useDbConfig)); } } /** * Returns associations for controllers models. * * @return array Associations for model */ protected function _associations() { $keys = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'); $associations = array(); foreach ($keys as $type) { foreach ($this->ScaffoldModel->{$type} as $assocKey => $assocData) { $associations[$type][$assocKey]['primaryKey'] = $this->ScaffoldModel->{$assocKey}->primaryKey; $associations[$type][$assocKey]['displayField'] = $this->ScaffoldModel->{$assocKey}->displayField; $associations[$type][$assocKey]['foreignKey'] = $assocData['foreignKey']; list($plugin, $model) = pluginSplit($assocData['className']); if ($plugin) { $plugin = Inflector::underscore($plugin); } $associations[$type][$assocKey]['plugin'] = $plugin; $associations[$type][$assocKey]['controller'] = Inflector::pluralize(Inflector::underscore($model)); if ($type === 'hasAndBelongsToMany') { $associations[$type][$assocKey]['with'] = $assocData['with']; } } } return $associations; } } cakephp-2.8.0/lib/Cake/Core/000077500000000000000000000000001265552240500154435ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Core/App.php000066400000000000000000000706421265552240500167050ustar00rootroot00000000000000 array('extends' => null, 'core' => true), 'file' => array('extends' => null, 'core' => true), 'model' => array('extends' => 'AppModel', 'core' => false), 'behavior' => array('suffix' => 'Behavior', 'extends' => 'Model/ModelBehavior', 'core' => true), 'controller' => array('suffix' => 'Controller', 'extends' => 'AppController', 'core' => true), 'component' => array('suffix' => 'Component', 'extends' => null, 'core' => true), 'lib' => array('extends' => null, 'core' => true), 'view' => array('suffix' => 'View', 'extends' => null, 'core' => true), 'helper' => array('suffix' => 'Helper', 'extends' => 'AppHelper', 'core' => true), 'vendor' => array('extends' => null, 'core' => true), 'shell' => array('suffix' => 'Shell', 'extends' => 'AppShell', 'core' => true), 'plugin' => array('extends' => null, 'core' => true) ); /** * Paths to search for files. * * @var array */ public static $search = array(); /** * Whether or not to return the file that is loaded. * * @var bool */ public static $return = false; /** * Holds key/value pairs of $type => file path. * * @var array */ protected static $_map = array(); /** * Holds and key => value array of object types. * * @var array */ protected static $_objects = array(); /** * Holds the location of each class * * @var array */ protected static $_classMap = array(); /** * Holds the possible paths for each package name * * @var array */ protected static $_packages = array(); /** * Holds the templates for each customizable package path in the application * * @var array */ protected static $_packageFormat = array(); /** * Maps an old style CakePHP class type to the corresponding package * * @var array */ public static $legacy = array( 'models' => 'Model', 'behaviors' => 'Model/Behavior', 'datasources' => 'Model/Datasource', 'controllers' => 'Controller', 'components' => 'Controller/Component', 'views' => 'View', 'helpers' => 'View/Helper', 'shells' => 'Console/Command', 'libs' => 'Lib', 'vendors' => 'Vendor', 'plugins' => 'Plugin', 'locales' => 'Locale' ); /** * Indicates whether the class cache should be stored again because of an addition to it * * @var bool */ protected static $_cacheChange = false; /** * Indicates whether the object cache should be stored again because of an addition to it * * @var bool */ protected static $_objectCacheChange = false; /** * Indicates the the Application is in the bootstrapping process. Used to better cache * loaded classes while the cache libraries have not been yet initialized * * @var bool */ public static $bootstrapping = false; /** * Used to read information stored path * * Usage: * * `App::path('Model'); will return all paths for models` * * `App::path('Model/Datasource', 'MyPlugin'); will return the path for datasources under the 'MyPlugin' plugin` * * @param string $type type of path * @param string $plugin name of plugin * @return array * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::path */ public static function path($type, $plugin = null) { if (!empty(static::$legacy[$type])) { $type = static::$legacy[$type]; } if (!empty($plugin)) { $path = array(); $pluginPath = CakePlugin::path($plugin); $packageFormat = static::_packageFormat(); if (!empty($packageFormat[$type])) { foreach ($packageFormat[$type] as $f) { $path[] = sprintf($f, $pluginPath); } } return $path; } if (!isset(static::$_packages[$type])) { return array(); } return static::$_packages[$type]; } /** * Get all the currently loaded paths from App. Useful for inspecting * or storing all paths App knows about. For a paths to a specific package * use App::path() * * @return array An array of packages and their associated paths. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::paths */ public static function paths() { return static::$_packages; } /** * Sets up each package location on the file system. You can configure multiple search paths * for each package, those will be used to look for files one folder at a time in the specified order * All paths should be terminated with a Directory separator * * Usage: * * `App::build(array('Model' => array('/a/full/path/to/models/'))); will setup a new search path for the Model package` * * `App::build(array('Model' => array('/path/to/models/')), App::RESET); will setup the path as the only valid path for searching models` * * `App::build(array('View/Helper' => array('/path/to/helpers/', '/another/path/'))); will setup multiple search paths for helpers` * * `App::build(array('Service' => array('%s' . 'Service' . DS)), App::REGISTER); will register new package 'Service'` * * If reset is set to true, all loaded plugins will be forgotten and they will be needed to be loaded again. * * @param array $paths associative array with package names as keys and a list of directories for new search paths * @param bool|string $mode App::RESET will set paths, App::APPEND with append paths, App::PREPEND will prepend paths (default) * App::REGISTER will register new packages and their paths, %s in path will be replaced by APP path * @return void * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::build */ public static function build($paths = array(), $mode = App::PREPEND) { //Provides Backwards compatibility for old-style package names $legacyPaths = array(); foreach ($paths as $type => $path) { if (!empty(static::$legacy[$type])) { $type = static::$legacy[$type]; } $legacyPaths[$type] = $path; } $paths = $legacyPaths; if ($mode === App::RESET) { foreach ($paths as $type => $new) { static::$_packages[$type] = (array)$new; static::objects($type, null, false); } return; } if (empty($paths)) { static::$_packageFormat = null; } $packageFormat = static::_packageFormat(); if ($mode === App::REGISTER) { foreach ($paths as $package => $formats) { if (empty($packageFormat[$package])) { $packageFormat[$package] = $formats; } else { $formats = array_merge($packageFormat[$package], $formats); $packageFormat[$package] = array_values(array_unique($formats)); } } static::$_packageFormat = $packageFormat; } $defaults = array(); foreach ($packageFormat as $package => $format) { foreach ($format as $f) { $defaults[$package][] = sprintf($f, APP); } } if (empty($paths)) { static::$_packages = $defaults; return; } if ($mode === App::REGISTER) { $paths = array(); } foreach ($defaults as $type => $default) { if (!empty(static::$_packages[$type])) { $path = static::$_packages[$type]; } else { $path = $default; } if (!empty($paths[$type])) { $newPath = (array)$paths[$type]; if ($mode === App::PREPEND) { $path = array_merge($newPath, $path); } else { $path = array_merge($path, $newPath); } $path = array_values(array_unique($path)); } static::$_packages[$type] = $path; } } /** * Gets the path that a plugin is on. Searches through the defined plugin paths. * * Usage: * * `App::pluginPath('MyPlugin'); will return the full path to 'MyPlugin' plugin'` * * @param string $plugin CamelCased/lower_cased plugin name to find the path of. * @return string full path to the plugin. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::pluginPath * @deprecated 3.0.0 Use `CakePlugin::path()` instead. */ public static function pluginPath($plugin) { return CakePlugin::path($plugin); } /** * Finds the path that a theme is on. Searches through the defined theme paths. * * Usage: * * `App::themePath('MyTheme'); will return the full path to the 'MyTheme' theme` * * @param string $theme theme name to find the path of. * @return string full path to the theme. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::themePath */ public static function themePath($theme) { $themeDir = 'Themed' . DS . Inflector::camelize($theme); foreach (static::$_packages['View'] as $path) { if (is_dir($path . $themeDir)) { return $path . $themeDir . DS; } } return static::$_packages['View'][0] . $themeDir . DS; } /** * Returns the full path to a package inside the CakePHP core * * Usage: * * `App::core('Cache/Engine'); will return the full path to the cache engines package` * * @param string $type Package type. * @return array full path to package * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::core */ public static function core($type) { return array(CAKE . str_replace('/', DS, $type) . DS); } /** * Returns an array of objects of the given type. * * Example usage: * * `App::objects('plugin');` returns `array('DebugKit', 'Blog', 'User');` * * `App::objects('Controller');` returns `array('PagesController', 'BlogController');` * * You can also search only within a plugin's objects by using the plugin dot * syntax. * * `App::objects('MyPlugin.Model');` returns `array('MyPluginPost', 'MyPluginComment');` * * When scanning directories, files and directories beginning with `.` will be excluded as these * are commonly used by version control systems. * * @param string $type Type of object, i.e. 'Model', 'Controller', 'View/Helper', 'file', 'class' or 'plugin' * @param string|array $path Optional Scan only the path given. If null, paths for the chosen type will be used. * @param bool $cache Set to false to rescan objects of the chosen type. Defaults to true. * @return mixed Either false on incorrect / miss. Or an array of found objects. * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::objects */ public static function objects($type, $path = null, $cache = true) { if (empty(static::$_objects) && $cache === true) { static::$_objects = (array)Cache::read('object_map', '_cake_core_'); } $extension = '/\.php$/'; $includeDirectories = false; $name = $type; if ($type === 'plugin') { $type = 'plugins'; } if ($type === 'plugins') { $extension = '/.*/'; $includeDirectories = true; } list($plugin, $type) = pluginSplit($type); if (isset(static::$legacy[$type . 's'])) { $type = static::$legacy[$type . 's']; } if ($type === 'file' && !$path) { return false; } elseif ($type === 'file') { $extension = '/\.php$/'; $name = $type . str_replace(DS, '', $path); } $cacheLocation = empty($plugin) ? 'app' : $plugin; if ($cache !== true || !isset(static::$_objects[$cacheLocation][$name])) { $objects = array(); if (empty($path)) { $path = static::path($type, $plugin); } foreach ((array)$path as $dir) { if ($dir != APP && is_dir($dir)) { $files = new RegexIterator(new DirectoryIterator($dir), $extension); foreach ($files as $file) { $fileName = basename($file); if (!$file->isDot() && $fileName[0] !== '.') { $isDir = $file->isDir(); if ($isDir && $includeDirectories) { $objects[] = $fileName; } elseif (!$includeDirectories && !$isDir) { $objects[] = substr($fileName, 0, -4); } } } } } if ($type !== 'file') { foreach ($objects as $key => $value) { $objects[$key] = Inflector::camelize($value); } } sort($objects); if ($plugin) { return $objects; } static::$_objects[$cacheLocation][$name] = $objects; if ($cache) { static::$_objectCacheChange = true; } } return static::$_objects[$cacheLocation][$name]; } /** * Declares a package for a class. This package location will be used * by the automatic class loader if the class is tried to be used * * Usage: * * `App::uses('MyCustomController', 'Controller');` will setup the class to be found under Controller package * * `App::uses('MyHelper', 'MyPlugin.View/Helper');` will setup the helper class to be found in plugin's helper package * * @param string $className the name of the class to configure package for * @param string $location the package name * @return void * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::uses */ public static function uses($className, $location) { static::$_classMap[$className] = $location; } /** * Method to handle the automatic class loading. It will look for each class' package * defined using App::uses() and with this information it will resolve the package name to a full path * to load the class from. File name for each class should follow the class name. For instance, * if a class is name `MyCustomClass` the file name should be `MyCustomClass.php` * * @param string $className the name of the class to load * @return bool */ public static function load($className) { if (!isset(static::$_classMap[$className])) { return false; } if (strpos($className, '..') !== false) { return false; } $parts = explode('.', static::$_classMap[$className], 2); list($plugin, $package) = count($parts) > 1 ? $parts : array(null, current($parts)); $file = static::_mapped($className, $plugin); if ($file) { return include $file; } $paths = static::path($package, $plugin); if (empty($plugin)) { $appLibs = empty(static::$_packages['Lib']) ? APPLIBS : current(static::$_packages['Lib']); $paths[] = $appLibs . $package . DS; $paths[] = APP . $package . DS; $paths[] = CAKE . $package . DS; } else { $pluginPath = CakePlugin::path($plugin); $paths[] = $pluginPath . 'Lib' . DS . $package . DS; $paths[] = $pluginPath . $package . DS; } $normalizedClassName = str_replace('\\', DS, $className); foreach ($paths as $path) { $file = $path . $normalizedClassName . '.php'; if (file_exists($file)) { static::_map($file, $className, $plugin); return include $file; } } return false; } /** * Returns the package name where a class was defined to be located at * * @param string $className name of the class to obtain the package name from * @return string|null Package name, or null if not declared * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#App::location */ public static function location($className) { if (!empty(static::$_classMap[$className])) { return static::$_classMap[$className]; } return null; } /** * Finds classes based on $name or specific file(s) to search. Calling App::import() will * not construct any classes contained in the files. It will only find and require() the file. * * @param string|array $type The type of Class if passed as a string, or all params can be passed as * a single array to $type. * @param string $name Name of the Class or a unique name for the file * @param bool|array $parent boolean true if Class Parent should be searched, accepts key => value * array('parent' => $parent, 'file' => $file, 'search' => $search, 'ext' => '$ext'); * $ext allows setting the extension of the file name * based on Inflector::underscore($name) . ".$ext"; * @param array $search paths to search for files, array('path 1', 'path 2', 'path 3'); * @param string $file full name of the file to search for including extension * @param bool $return Return the loaded file, the file must have a return * statement in it to work: return $variable; * @return bool true if Class is already in memory or if file is found and loaded, false if not * @link http://book.cakephp.org/2.0/en/core-utility-libraries/app.html#including-files-with-app-import */ public static function import($type = null, $name = null, $parent = true, $search = array(), $file = null, $return = false) { $ext = null; if (is_array($type)) { extract($type, EXTR_OVERWRITE); } if (is_array($parent)) { extract($parent, EXTR_OVERWRITE); } if (!$name && !$file) { return false; } if (is_array($name)) { foreach ($name as $class) { if (!App::import(compact('type', 'parent', 'search', 'file', 'return') + array('name' => $class))) { return false; } } return true; } $originalType = strtolower($type); $specialPackage = in_array($originalType, array('file', 'vendor')); if (!$specialPackage && isset(static::$legacy[$originalType . 's'])) { $type = static::$legacy[$originalType . 's']; } list($plugin, $name) = pluginSplit($name); if (!empty($plugin)) { if (!CakePlugin::loaded($plugin)) { return false; } } if (!$specialPackage) { return static::_loadClass($name, $plugin, $type, $originalType, $parent); } if ($originalType === 'file' && !empty($file)) { return static::_loadFile($name, $plugin, $search, $file, $return); } if ($originalType === 'vendor') { return static::_loadVendor($name, $plugin, $file, $ext); } return false; } /** * Helper function to include classes * This is a compatibility wrapper around using App::uses() and automatic class loading * * @param string $name unique name of the file for identifying it inside the application * @param string $plugin camel cased plugin name if any * @param string $type name of the packed where the class is located * @param string $originalType type name as supplied initially by the user * @param bool $parent whether to load the class parent or not * @return bool true indicating the successful load and existence of the class */ protected static function _loadClass($name, $plugin, $type, $originalType, $parent) { if ($type === 'Console/Command' && $name === 'Shell') { $type = 'Console'; } elseif (isset(static::$types[$originalType]['suffix'])) { $suffix = static::$types[$originalType]['suffix']; $name .= ($suffix === $name) ? '' : $suffix; } if ($parent && isset(static::$types[$originalType]['extends'])) { $extends = static::$types[$originalType]['extends']; $extendType = $type; if (strpos($extends, '/') !== false) { $parts = explode('/', $extends); $extends = array_pop($parts); $extendType = implode('/', $parts); } App::uses($extends, $extendType); if ($plugin && in_array($originalType, array('controller', 'model'))) { App::uses($plugin . $extends, $plugin . '.' . $type); } } if ($plugin) { $plugin .= '.'; } $name = Inflector::camelize($name); App::uses($name, $plugin . $type); return class_exists($name); } /** * Helper function to include single files * * @param string $name unique name of the file for identifying it inside the application * @param string $plugin camel cased plugin name if any * @param array $search list of paths to search the file into * @param string $file filename if known, the $name param will be used otherwise * @param bool $return whether this function should return the contents of the file after being parsed by php or just a success notice * @return mixed if $return contents of the file after php parses it, boolean indicating success otherwise */ protected static function _loadFile($name, $plugin, $search, $file, $return) { $mapped = static::_mapped($name, $plugin); if ($mapped) { $file = $mapped; } elseif (!empty($search)) { foreach ($search as $path) { $found = false; if (file_exists($path . $file)) { $file = $path . $file; $found = true; break; } if (empty($found)) { $file = false; } } } if (!empty($file) && file_exists($file)) { static::_map($file, $name, $plugin); $returnValue = include $file; if ($return) { return $returnValue; } return (bool)$returnValue; } return false; } /** * Helper function to load files from vendors folders * * @param string $name unique name of the file for identifying it inside the application * @param string $plugin camel cased plugin name if any * @param string $file file name if known * @param string $ext file extension if known * @return bool true if the file was loaded successfully, false otherwise */ protected static function _loadVendor($name, $plugin, $file, $ext) { if ($mapped = static::_mapped($name, $plugin)) { return (bool)include_once $mapped; } $fileTries = array(); $paths = ($plugin) ? App::path('vendors', $plugin) : App::path('vendors'); if (empty($ext)) { $ext = 'php'; } if (empty($file)) { $fileTries[] = $name . '.' . $ext; $fileTries[] = Inflector::underscore($name) . '.' . $ext; } else { $fileTries[] = $file; } foreach ($fileTries as $file) { foreach ($paths as $path) { if (file_exists($path . $file)) { static::_map($path . $file, $name, $plugin); return (bool)include $path . $file; } } } return false; } /** * Initializes the cache for App, registers a shutdown function. * * @return void */ public static function init() { static::$_map += (array)Cache::read('file_map', '_cake_core_'); register_shutdown_function(array('App', 'shutdown')); } /** * Maps the $name to the $file. * * @param string $file full path to file * @param string $name unique name for this map * @param string $plugin camelized if object is from a plugin, the name of the plugin * @return void */ protected static function _map($file, $name, $plugin = null) { $key = $name; if ($plugin) { $key = 'plugin.' . $name; } if ($plugin && empty(static::$_map[$name])) { static::$_map[$key] = $file; } if (!$plugin && empty(static::$_map['plugin.' . $name])) { static::$_map[$key] = $file; } if (!static::$bootstrapping) { static::$_cacheChange = true; } } /** * Returns a file's complete path. * * @param string $name unique name * @param string $plugin camelized if object is from a plugin, the name of the plugin * @return mixed file path if found, false otherwise */ protected static function _mapped($name, $plugin = null) { $key = $name; if ($plugin) { $key = 'plugin.' . $name; } return isset(static::$_map[$key]) ? static::$_map[$key] : false; } /** * Sets then returns the templates for each customizable package path * * @return array templates for each customizable package path */ protected static function _packageFormat() { if (empty(static::$_packageFormat)) { static::$_packageFormat = array( 'Model' => array( '%s' . 'Model' . DS ), 'Model/Behavior' => array( '%s' . 'Model' . DS . 'Behavior' . DS ), 'Model/Datasource' => array( '%s' . 'Model' . DS . 'Datasource' . DS ), 'Model/Datasource/Database' => array( '%s' . 'Model' . DS . 'Datasource' . DS . 'Database' . DS ), 'Model/Datasource/Session' => array( '%s' . 'Model' . DS . 'Datasource' . DS . 'Session' . DS ), 'Controller' => array( '%s' . 'Controller' . DS ), 'Controller/Component' => array( '%s' . 'Controller' . DS . 'Component' . DS ), 'Controller/Component/Auth' => array( '%s' . 'Controller' . DS . 'Component' . DS . 'Auth' . DS ), 'Controller/Component/Acl' => array( '%s' . 'Controller' . DS . 'Component' . DS . 'Acl' . DS ), 'View' => array( '%s' . 'View' . DS ), 'View/Helper' => array( '%s' . 'View' . DS . 'Helper' . DS ), 'Console' => array( '%s' . 'Console' . DS ), 'Console/Command' => array( '%s' . 'Console' . DS . 'Command' . DS ), 'Console/Command/Task' => array( '%s' . 'Console' . DS . 'Command' . DS . 'Task' . DS ), 'Lib' => array( '%s' . 'Lib' . DS ), 'Locale' => array( '%s' . 'Locale' . DS ), 'Vendor' => array( '%s' . 'Vendor' . DS, ROOT . DS . 'vendors' . DS, dirname(dirname(CAKE)) . DS . 'vendors' . DS ), 'Plugin' => array( APP . 'Plugin' . DS, ROOT . DS . 'plugins' . DS, dirname(dirname(CAKE)) . DS . 'plugins' . DS ) ); } return static::$_packageFormat; } /** * Increases the PHP "memory_limit" ini setting by the specified amount * in kilobytes * * @param string $additionalKb Number in kilobytes * @return void */ public static function increaseMemoryLimit($additionalKb) { $limit = ini_get("memory_limit"); if (!is_string($limit) || !strlen($limit)) { return; } $limit = trim($limit); $units = strtoupper(substr($limit, -1)); $current = substr($limit, 0, strlen($limit) - 1); if ($units === "M") { $current = $current * 1024; $units = "K"; } if ($units === "G") { $current = $current * 1024 * 1024; $units = "K"; } if ($units === "K") { ini_set("memory_limit", ceil($current + $additionalKb) . "K"); } } /** * Object destructor. * * Writes cache file if changes have been made to the $_map. Also, check if a fatal * error happened and call the handler. * * @return void */ public static function shutdown() { $megabytes = Configure::read('Error.extraFatalErrorMemory'); if ($megabytes === null) { $megabytes = 4; } if ($megabytes !== false && $megabytes > 0) { static::increaseMemoryLimit($megabytes * 1024); } if (static::$_cacheChange) { Cache::write('file_map', array_filter(static::$_map), '_cake_core_'); } if (static::$_objectCacheChange) { Cache::write('object_map', static::$_objects, '_cake_core_'); } static::_checkFatalError(); } /** * Check if a fatal error happened and trigger the configured handler if configured * * @return void */ protected static function _checkFatalError() { $lastError = error_get_last(); if (!is_array($lastError)) { return; } list(, $log) = ErrorHandler::mapErrorCode($lastError['type']); if ($log !== LOG_ERR) { return; } if (PHP_SAPI === 'cli') { $errorHandler = Configure::read('Error.consoleHandler'); } else { $errorHandler = Configure::read('Error.handler'); } if (!is_callable($errorHandler)) { return; } call_user_func($errorHandler, $lastError['type'], $lastError['message'], $lastError['file'], $lastError['line'], array()); } } cakephp-2.8.0/lib/Cake/Core/CakePlugin.php000066400000000000000000000210251265552240500201760ustar00rootroot00000000000000 true, 'routes' => true))` * * will load the bootstrap.php and routes.php files * * `CakePlugin::load('DebugKit', array('bootstrap' => false, 'routes' => true))` * * will load routes.php file but not bootstrap.php * * `CakePlugin::load('DebugKit', array('bootstrap' => array('config1', 'config2')))` * * will load config1.php and config2.php files * * `CakePlugin::load('DebugKit', array('bootstrap' => 'aCallableMethod'))` * * will run the aCallableMethod function to initialize it * * Bootstrap initialization functions can be expressed as a PHP callback type, * including closures. Callbacks will receive two parameters * (plugin name, plugin configuration) * * It is also possible to load multiple plugins at once. Examples: * * `CakePlugin::load(array('DebugKit', 'ApiGenerator'))` * * will load the DebugKit and ApiGenerator plugins * * `CakePlugin::load(array('DebugKit', 'ApiGenerator'), array('bootstrap' => true))` * * will load bootstrap file for both plugins * * ``` * CakePlugin::load(array( * 'DebugKit' => array('routes' => true), * 'ApiGenerator' * ), array('bootstrap' => true)) * ``` * * Will only load the bootstrap for ApiGenerator and only the routes for DebugKit. * By using the `path` option you can specify an absolute path to the plugin. Make * sure that the path is slash terminated or your plugin will not be located properly. * * @param string|array $plugin name of the plugin to be loaded in CamelCase format or array or plugins to load * @param array $config configuration options for the plugin * @throws MissingPluginException if the folder for the plugin to be loaded is not found * @return void */ public static function load($plugin, $config = array()) { if (is_array($plugin)) { foreach ($plugin as $name => $conf) { list($name, $conf) = (is_numeric($name)) ? array($conf, $config) : array($name, $conf); static::load($name, $conf); } return; } $config += array('bootstrap' => false, 'routes' => false, 'ignoreMissing' => false); if (empty($config['path'])) { foreach (App::path('plugins') as $path) { if (is_dir($path . $plugin)) { static::$_plugins[$plugin] = $config + array('path' => $path . $plugin . DS); break; } //Backwards compatibility to make easier to migrate to 2.0 $underscored = Inflector::underscore($plugin); if (is_dir($path . $underscored)) { static::$_plugins[$plugin] = $config + array('path' => $path . $underscored . DS); break; } } } else { static::$_plugins[$plugin] = $config; } if (empty(static::$_plugins[$plugin]['path'])) { throw new MissingPluginException(array('plugin' => $plugin)); } if (!empty(static::$_plugins[$plugin]['bootstrap'])) { static::bootstrap($plugin); } } /** * Will load all the plugins located in the configured plugins folders * If passed an options array, it will be used as a common default for all plugins to be loaded * It is possible to set specific defaults for each plugins in the options array. Examples: * * ``` * CakePlugin::loadAll(array( * array('bootstrap' => true), * 'DebugKit' => array('routes' => true, 'bootstrap' => false), * )) * ``` * * The above example will load the bootstrap file for all plugins, but for DebugKit it will only load * the routes file and will not look for any bootstrap script. If you are loading * many plugins that inconsistently support routes/bootstrap files, instead of detailing * each plugin you can use the `ignoreMissing` option: * * ``` * CakePlugin::loadAll(array( * 'ignoreMissing' => true, * 'bootstrap' => true, * 'routes' => true, * )); * ``` * * The ignoreMissing option will do additional file_exists() calls but is simpler * to use. * * @param array $options Options list. See CakePlugin::load() for valid options. * @return void */ public static function loadAll($options = array()) { $plugins = App::objects('plugins'); foreach ($plugins as $p) { $opts = isset($options[$p]) ? (array)$options[$p] : array(); if (isset($options[0])) { $opts += $options[0]; } static::load($p, $opts); } } /** * Returns the filesystem path for a plugin * * @param string $plugin name of the plugin in CamelCase format * @return string path to the plugin folder * @throws MissingPluginException if the folder for plugin was not found or plugin has not been loaded */ public static function path($plugin) { if (empty(static::$_plugins[$plugin])) { throw new MissingPluginException(array('plugin' => $plugin)); } return static::$_plugins[$plugin]['path']; } /** * Loads the bootstrapping files for a plugin, or calls the initialization setup in the configuration * * @param string $plugin name of the plugin * @return mixed * @see CakePlugin::load() for examples of bootstrap configuration */ public static function bootstrap($plugin) { $config = static::$_plugins[$plugin]; if ($config['bootstrap'] === false) { return false; } if (is_callable($config['bootstrap'])) { return call_user_func_array($config['bootstrap'], array($plugin, $config)); } $path = static::path($plugin); if ($config['bootstrap'] === true) { return static::_includeFile( $path . 'Config' . DS . 'bootstrap.php', $config['ignoreMissing'] ); } $bootstrap = (array)$config['bootstrap']; foreach ($bootstrap as $file) { static::_includeFile( $path . 'Config' . DS . $file . '.php', $config['ignoreMissing'] ); } return true; } /** * Loads the routes file for a plugin, or all plugins configured to load their respective routes file * * @param string $plugin name of the plugin, if null will operate on all plugins having enabled the * loading of routes files * @return bool */ public static function routes($plugin = null) { if ($plugin === null) { foreach (static::loaded() as $p) { static::routes($p); } return true; } $config = static::$_plugins[$plugin]; if ($config['routes'] === false) { return false; } return (bool)static::_includeFile( static::path($plugin) . 'Config' . DS . 'routes.php', $config['ignoreMissing'] ); } /** * Returns true if the plugin $plugin is already loaded * If plugin is null, it will return a list of all loaded plugins * * @param string $plugin Plugin name to check. * @return mixed boolean true if $plugin is already loaded. * If $plugin is null, returns a list of plugins that have been loaded */ public static function loaded($plugin = null) { if ($plugin) { return isset(static::$_plugins[$plugin]); } $return = array_keys(static::$_plugins); sort($return); return $return; } /** * Forgets a loaded plugin or all of them if first parameter is null * * @param string $plugin name of the plugin to forget * @return void */ public static function unload($plugin = null) { if ($plugin === null) { static::$_plugins = array(); } else { unset(static::$_plugins[$plugin]); } } /** * Include file, ignoring include error if needed if file is missing * * @param string $file File to include * @param bool $ignoreMissing Whether to ignore include error for missing files * @return mixed */ protected static function _includeFile($file, $ignoreMissing = false) { if ($ignoreMissing && !is_file($file)) { return false; } return include $file; } } cakephp-2.8.0/lib/Cake/Core/Configure.php000066400000000000000000000344751265552240500201120ustar00rootroot00000000000000 0 ); /** * Configured reader classes, used to load config files from resources * * @var array * @see Configure::load() */ protected static $_readers = array(); /** * Initializes configure and runs the bootstrap process. * Bootstrapping includes the following steps: * * - Setup App array in Configure. * - Include app/Config/core.php. * - Configure core cache configurations. * - Load App cache files. * - Include app/Config/bootstrap.php. * - Setup error/exception handlers. * * @param bool $boot Whether to do bootstrapping. * @return void */ public static function bootstrap($boot = true) { if ($boot) { static::_appDefaults(); if (!include APP . 'Config' . DS . 'core.php') { trigger_error(__d('cake_dev', "Can't find application core file. Please create %s, and make sure it is readable by PHP.", APP . 'Config' . DS . 'core.php'), E_USER_ERROR ); } App::init(); App::$bootstrapping = false; App::build(); $exception = array( 'handler' => 'ErrorHandler::handleException', ); $error = array( 'handler' => 'ErrorHandler::handleError', 'level' => E_ALL & ~E_DEPRECATED, ); if (PHP_SAPI === 'cli') { App::uses('ConsoleErrorHandler', 'Console'); $console = new ConsoleErrorHandler(); $exception['handler'] = array($console, 'handleException'); $error['handler'] = array($console, 'handleError'); } static::_setErrorHandlers($error, $exception); if (!include APP . 'Config' . DS . 'bootstrap.php') { trigger_error(__d('cake_dev', "Can't find application bootstrap file. Please create %s, and make sure it is readable by PHP.", APP . 'Config' . DS . 'bootstrap.php'), E_USER_ERROR ); } restore_error_handler(); static::_setErrorHandlers( static::$_values['Error'], static::$_values['Exception'] ); // Preload Debugger + CakeText in case of E_STRICT errors when loading files. if (static::$_values['debug'] > 0) { class_exists('Debugger'); class_exists('CakeText'); } } } /** * Set app's default configs * * @return void */ protected static function _appDefaults() { static::write('App', (array)static::read('App') + array( 'base' => false, 'baseUrl' => false, 'dir' => APP_DIR, 'webroot' => WEBROOT_DIR, 'www_root' => WWW_ROOT )); } /** * Used to store a dynamic variable in Configure. * * Usage: * ``` * Configure::write('One.key1', 'value of the Configure::One[key1]'); * Configure::write(array('One.key1' => 'value of the Configure::One[key1]')); * Configure::write('One', array( * 'key1' => 'value of the Configure::One[key1]', * 'key2' => 'value of the Configure::One[key2]' * ); * * Configure::write(array( * 'One.key1' => 'value of the Configure::One[key1]', * 'One.key2' => 'value of the Configure::One[key2]' * )); * ``` * * @param string|array $config The key to write, can be a dot notation value. * Alternatively can be an array containing key(s) and value(s). * @param mixed $value Value to set for var * @return bool True if write was successful * @link http://book.cakephp.org/2.0/en/development/configuration.html#Configure::write */ public static function write($config, $value = null) { if (!is_array($config)) { $config = array($config => $value); } foreach ($config as $name => $value) { static::$_values = Hash::insert(static::$_values, $name, $value); } if (isset($config['debug']) && function_exists('ini_set')) { if (static::$_values['debug']) { ini_set('display_errors', 1); } else { ini_set('display_errors', 0); } } return true; } /** * Used to read information stored in Configure. It's not * possible to store `null` values in Configure. * * Usage: * ``` * Configure::read('Name'); will return all values for Name * Configure::read('Name.key'); will return only the value of Configure::Name[key] * ``` * * @param string|null $var Variable to obtain. Use '.' to access array elements. * @return mixed value stored in configure, or null. * @link http://book.cakephp.org/2.0/en/development/configuration.html#Configure::read */ public static function read($var = null) { if ($var === null) { return static::$_values; } return Hash::get(static::$_values, $var); } /** * Used to read and delete a variable from Configure. * * This is primarily used during bootstrapping to move configuration data * out of configure into the various other classes in CakePHP. * * @param string $var The key to read and remove. * @return array|null */ public static function consume($var) { $simple = strpos($var, '.') === false; if ($simple && !isset(static::$_values[$var])) { return null; } if ($simple) { $value = static::$_values[$var]; unset(static::$_values[$var]); return $value; } $value = Hash::get(static::$_values, $var); static::$_values = Hash::remove(static::$_values, $var); return $value; } /** * Returns true if given variable is set in Configure. * * @param string $var Variable name to check for * @return bool True if variable is there */ public static function check($var) { if (empty($var)) { return false; } return Hash::get(static::$_values, $var) !== null; } /** * Used to delete a variable from Configure. * * Usage: * ``` * Configure::delete('Name'); will delete the entire Configure::Name * Configure::delete('Name.key'); will delete only the Configure::Name[key] * ``` * * @param string $var the var to be deleted * @return void * @link http://book.cakephp.org/2.0/en/development/configuration.html#Configure::delete */ public static function delete($var) { static::$_values = Hash::remove(static::$_values, $var); } /** * Add a new reader to Configure. Readers allow you to read configuration * files in various formats/storage locations. CakePHP comes with two built-in readers * PhpReader and IniReader. You can also implement your own reader classes in your application. * * To add a new reader to Configure: * * `Configure::config('ini', new IniReader());` * * @param string $name The name of the reader being configured. This alias is used later to * read values from a specific reader. * @param ConfigReaderInterface $reader The reader to append. * @return void */ public static function config($name, ConfigReaderInterface $reader) { static::$_readers[$name] = $reader; } /** * Gets the names of the configured reader objects. * * @param string|null $name Name to check. If null returns all configured reader names. * @return array Array of the configured reader objects. */ public static function configured($name = null) { if ($name) { return isset(static::$_readers[$name]); } return array_keys(static::$_readers); } /** * Remove a configured reader. This will unset the reader * and make any future attempts to use it cause an Exception. * * @param string $name Name of the reader to drop. * @return bool Success */ public static function drop($name) { if (!isset(static::$_readers[$name])) { return false; } unset(static::$_readers[$name]); return true; } /** * Loads stored configuration information from a resource. You can add * config file resource readers with `Configure::config()`. * * Loaded configuration information will be merged with the current * runtime configuration. You can load configuration files from plugins * by preceding the filename with the plugin name. * * `Configure::load('Users.user', 'default')` * * Would load the 'user' config file using the default config reader. You can load * app config files by giving the name of the resource you want loaded. * * `Configure::load('setup', 'default');` * * If using `default` config and no reader has been configured for it yet, * one will be automatically created using PhpReader * * @param string $key name of configuration resource to load. * @param string $config Name of the configured reader to use to read the resource identified by $key. * @param bool $merge if config files should be merged instead of simply overridden * @return bool False if file not found, true if load successful. * @throws ConfigureException Will throw any exceptions the reader raises. * @link http://book.cakephp.org/2.0/en/development/configuration.html#Configure::load */ public static function load($key, $config = 'default', $merge = true) { $reader = static::_getReader($config); if (!$reader) { return false; } $values = $reader->read($key); if ($merge) { $keys = array_keys($values); foreach ($keys as $key) { if (($c = static::read($key)) && is_array($values[$key]) && is_array($c)) { $values[$key] = Hash::merge($c, $values[$key]); } } } return static::write($values); } /** * Dump data currently in Configure into $key. The serialization format * is decided by the config reader attached as $config. For example, if the * 'default' adapter is a PhpReader, the generated file will be a PHP * configuration file loadable by the PhpReader. * * ## Usage * * Given that the 'default' reader is an instance of PhpReader. * Save all data in Configure to the file `my_config.php`: * * `Configure::dump('my_config.php', 'default');` * * Save only the error handling configuration: * * `Configure::dump('error.php', 'default', array('Error', 'Exception');` * * @param string $key The identifier to create in the config adapter. * This could be a filename or a cache key depending on the adapter being used. * @param string $config The name of the configured adapter to dump data with. * @param array $keys The name of the top-level keys you want to dump. * This allows you save only some data stored in Configure. * @return bool success * @throws ConfigureException if the adapter does not implement a `dump` method. */ public static function dump($key, $config = 'default', $keys = array()) { $reader = static::_getReader($config); if (!$reader) { throw new ConfigureException(__d('cake_dev', 'There is no "%s" adapter.', $config)); } if (!method_exists($reader, 'dump')) { throw new ConfigureException(__d('cake_dev', 'The "%s" adapter, does not have a %s method.', $config, 'dump()')); } $values = static::$_values; if (!empty($keys) && is_array($keys)) { $values = array_intersect_key($values, array_flip($keys)); } return (bool)$reader->dump($key, $values); } /** * Get the configured reader. Internally used by `Configure::load()` and `Configure::dump()` * Will create new PhpReader for default if not configured yet. * * @param string $config The name of the configured adapter * @return mixed Reader instance or false */ protected static function _getReader($config) { if (!isset(static::$_readers[$config])) { if ($config !== 'default') { return false; } App::uses('PhpReader', 'Configure'); static::config($config, new PhpReader()); } return static::$_readers[$config]; } /** * Used to determine the current version of CakePHP. * * Usage `Configure::version();` * * @return string Current version of CakePHP */ public static function version() { if (!isset(static::$_values['Cake']['version'])) { require CAKE . 'Config' . DS . 'config.php'; static::write($config); } return static::$_values['Cake']['version']; } /** * Used to write runtime configuration into Cache. Stored runtime configuration can be * restored using `Configure::restore()`. These methods can be used to enable configuration managers * frontends, or other GUI type interfaces for configuration. * * @param string $name The storage name for the saved configuration. * @param string $cacheConfig The cache configuration to save into. Defaults to 'default' * @param array $data Either an array of data to store, or leave empty to store all values. * @return bool Success */ public static function store($name, $cacheConfig = 'default', $data = null) { if ($data === null) { $data = static::$_values; } return Cache::write($name, $data, $cacheConfig); } /** * Restores configuration data stored in the Cache into configure. Restored * values will overwrite existing ones. * * @param string $name Name of the stored config file to load. * @param string $cacheConfig Name of the Cache configuration to read from. * @return bool Success. */ public static function restore($name, $cacheConfig = 'default') { $values = Cache::read($name, $cacheConfig); if ($values) { return static::write($values); } return false; } /** * Clear all values stored in Configure. * * @return bool Success. */ public static function clear() { static::$_values = array(); return true; } /** * Set the error and exception handlers. * * @param array $error The Error handling configuration. * @param array $exception The exception handling configuration. * @return void */ protected static function _setErrorHandlers($error, $exception) { $level = -1; if (isset($error['level'])) { error_reporting($error['level']); $level = $error['level']; } if (!empty($error['handler'])) { set_error_handler($error['handler'], $level); } if (!empty($exception['handler'])) { set_exception_handler($exception['handler']); } } } cakephp-2.8.0/lib/Cake/Core/Object.php000066400000000000000000000155031265552240500173660ustar00rootroot00000000000000 0, 'return' => 1, 'bare' => 1, 'requested' => 1); $data = isset($extra['data']) ? $extra['data'] : null; unset($extra['data']); if (is_string($url) && strpos($url, Router::fullBaseUrl()) === 0) { $url = Router::normalize(str_replace(Router::fullBaseUrl(), '', $url)); } if (is_string($url)) { $request = new CakeRequest($url); } elseif (is_array($url)) { $params = $url + array('pass' => array(), 'named' => array(), 'base' => false); $params = $extra + $params; $request = new CakeRequest(Router::reverse($params)); } if (isset($data)) { $request->data = $data; } $dispatcher = new Dispatcher(); $result = $dispatcher->dispatch($request, new CakeResponse(), $extra); Router::popRequest(); return $result; } /** * Calls a method on this object with the given parameters. Provides an OO wrapper * for `call_user_func_array` * * @param string $method Name of the method to call * @param array $params Parameter list to use when calling $method * @return mixed Returns the result of the method call */ public function dispatchMethod($method, $params = array()) { switch (count($params)) { case 0: return $this->{$method}(); case 1: return $this->{$method}($params[0]); case 2: return $this->{$method}($params[0], $params[1]); case 3: return $this->{$method}($params[0], $params[1], $params[2]); case 4: return $this->{$method}($params[0], $params[1], $params[2], $params[3]); case 5: return $this->{$method}($params[0], $params[1], $params[2], $params[3], $params[4]); default: return call_user_func_array(array(&$this, $method), $params); } } /** * Stop execution of the current script. Wraps exit() making * testing easier. * * @param int|string $status see http://php.net/exit for values * @return void */ protected function _stop($status = 0) { exit($status); } /** * Convenience method to write a message to CakeLog. See CakeLog::write() * for more information on writing to logs. * * @param string $msg Log message * @param int $type Error type constant. Defined in app/Config/core.php. * @param null|string|array $scope The scope(s) a log message is being created in. * See CakeLog::config() for more information on logging scopes. * @return bool Success of log write */ public function log($msg, $type = LOG_ERR, $scope = null) { if (!is_string($msg)) { $msg = print_r($msg, true); } return CakeLog::write($type, $msg, $scope); } /** * Allows setting of multiple properties of the object in a single line of code. Will only set * properties that are part of a class declaration. * * @param array $properties An associative array containing properties and corresponding values. * @return void */ protected function _set($properties = array()) { if (is_array($properties) && !empty($properties)) { $vars = get_object_vars($this); foreach ($properties as $key => $val) { if (array_key_exists($key, $vars)) { $this->{$key} = $val; } } } } /** * Merges this objects $property with the property in $class' definition. * This classes value for the property will be merged on top of $class' * * This provides some of the DRY magic CakePHP provides. If you want to shut it off, redefine * this method as an empty function. * * @param array $properties The name of the properties to merge. * @param string $class The class to merge the property with. * @param bool $normalize Set to true to run the properties through Hash::normalize() before merging. * @return void */ protected function _mergeVars($properties, $class, $normalize = true) { $classProperties = get_class_vars($class); foreach ($properties as $var) { if (isset($classProperties[$var]) && !empty($classProperties[$var]) && is_array($this->{$var}) && $this->{$var} != $classProperties[$var] ) { if ($normalize) { $classProperties[$var] = Hash::normalize($classProperties[$var]); $this->{$var} = Hash::normalize($this->{$var}); } $this->{$var} = Hash::merge($classProperties[$var], $this->{$var}); } } } } cakephp-2.8.0/lib/Cake/Error/000077500000000000000000000000001265552240500156445ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Error/ErrorHandler.php000066400000000000000000000256271265552240500207600ustar00rootroot00000000000000 1. * * ### Uncaught exceptions * * When debug < 1 a CakeException will render 404 or 500 errors. If an uncaught exception is thrown * and it is a type that ErrorHandler does not know about it will be treated as a 500 error. * * ### Implementing application specific exception handling * * You can implement application specific exception handling in one of a few ways. Each approach * gives you different amounts of control over the exception handling process. * * - Set Configure::write('Exception.handler', 'YourClass::yourMethod'); * - Create AppController::appError(); * - Set Configure::write('Exception.renderer', 'YourClass'); * * #### Create your own Exception handler with `Exception.handler` * * This gives you full control over the exception handling process. The class you choose should be * loaded in your app/Config/bootstrap.php, so its available to handle any exceptions. You can * define the handler as any callback type. Using Exception.handler overrides all other exception * handling settings and logic. * * #### Using `AppController::appError();` * * This controller method is called instead of the default exception rendering. It receives the * thrown exception as its only argument. You should implement your error handling in that method. * Using AppController::appError(), will supersede any configuration for Exception.renderer. * * #### Using a custom renderer with `Exception.renderer` * * If you don't want to take control of the exception handling, but want to change how exceptions are * rendered you can use `Exception.renderer` to choose a class to render exception pages. By default * `ExceptionRenderer` is used. Your custom exception renderer class should be placed in app/Lib/Error. * * Your custom renderer should expect an exception in its constructor, and implement a render method. * Failing to do so will cause additional errors. * * #### Logging exceptions * * Using the built-in exception handling, you can log all the exceptions * that are dealt with by ErrorHandler by setting `Exception.log` to true in your core.php. * Enabling this will log every exception to CakeLog and the configured loggers. * * ### PHP errors * * Error handler also provides the built in features for handling php errors (trigger_error). * While in debug mode, errors will be output to the screen using debugger. While in production mode, * errors will be logged to CakeLog. You can control which errors are logged by setting * `Error.level` in your core.php. * * #### Logging errors * * When ErrorHandler is used for handling errors, you can enable error logging by setting `Error.log` to true. * This will log all errors to the configured log handlers. * * #### Controlling what errors are logged/displayed * * You can control which errors are logged / displayed by ErrorHandler by setting `Error.level`. Setting this * to one or a combination of a few of the E_* constants will only enable the specified errors. * * e.g. `Configure::write('Error.level', E_ALL & ~E_NOTICE);` * * Would enable handling for all non Notice errors. * * @package Cake.Error * @see ExceptionRenderer for more information on how to customize exception rendering. */ class ErrorHandler { /** * Whether to give up rendering an exception, if the renderer itself is * throwing exceptions. * * @var bool */ protected static $_bailExceptionRendering = false; /** * Set as the default exception handler by the CakePHP bootstrap process. * * This will either use custom exception renderer class if configured, * or use the default ExceptionRenderer. * * @param Exception|ParseError $exception The exception to render. * @return void * @see http://php.net/manual/en/function.set-exception-handler.php */ public static function handleException($exception) { $config = Configure::read('Exception'); static::_log($exception, $config); $renderer = isset($config['renderer']) ? $config['renderer'] : 'ExceptionRenderer'; if ($renderer !== 'ExceptionRenderer') { list($plugin, $renderer) = pluginSplit($renderer, true); App::uses($renderer, $plugin . 'Error'); } try { $error = new $renderer($exception); $error->render(); } catch (Exception $e) { set_error_handler(Configure::read('Error.handler')); // Should be using configured ErrorHandler Configure::write('Error.trace', false); // trace is useless here since it's internal $message = sprintf("[%s] %s\n%s", // Keeping same message format get_class($e), $e->getMessage(), $e->getTraceAsString() ); static::$_bailExceptionRendering = true; trigger_error($message, E_USER_ERROR); } } /** * Generates a formatted error message * * @param Exception $exception Exception instance * @return string Formatted message */ protected static function _getMessage($exception) { $message = sprintf("[%s] %s", get_class($exception), $exception->getMessage() ); if (method_exists($exception, 'getAttributes')) { $attributes = $exception->getAttributes(); if ($attributes) { $message .= "\nException Attributes: " . var_export($exception->getAttributes(), true); } } if (PHP_SAPI !== 'cli') { $request = Router::getRequest(); if ($request) { $message .= "\nRequest URL: " . $request->here(); } } $message .= "\nStack Trace:\n" . $exception->getTraceAsString(); return $message; } /** * Handles exception logging * * @param Exception|ParseError $exception The exception to render. * @param array $config An array of configuration for logging. * @return bool */ protected static function _log($exception, $config) { if (empty($config['log'])) { return false; } if (!empty($config['skipLog'])) { foreach ((array)$config['skipLog'] as $class) { if ($exception instanceof $class) { return false; } } } return CakeLog::write(LOG_ERR, static::_getMessage($exception)); } /** * Set as the default error handler by CakePHP. Use Configure::write('Error.handler', $callback), to use your own * error handling methods. This function will use Debugger to display errors when debug > 0. And * will log errors to CakeLog, when debug == 0. * * You can use Configure::write('Error.level', $value); to set what type of errors will be handled here. * Stack traces for errors can be enabled with Configure::write('Error.trace', true); * * @param int $code Code of error * @param string $description Error description * @param string $file File on which error occurred * @param int $line Line that triggered the error * @param array $context Context * @return bool true if error was handled */ public static function handleError($code, $description, $file = null, $line = null, $context = null) { if (error_reporting() === 0) { return false; } $errorConfig = Configure::read('Error'); list($error, $log) = static::mapErrorCode($code); if ($log === LOG_ERR) { return static::handleFatalError($code, $description, $file, $line); } $debug = Configure::read('debug'); if ($debug) { $data = array( 'level' => $log, 'code' => $code, 'error' => $error, 'description' => $description, 'file' => $file, 'line' => $line, 'context' => $context, 'start' => 2, 'path' => Debugger::trimPath($file) ); return Debugger::getInstance()->outputError($data); } $message = $error . ' (' . $code . '): ' . $description . ' in [' . $file . ', line ' . $line . ']'; if (!empty($errorConfig['trace'])) { // https://bugs.php.net/bug.php?id=65322 if (version_compare(PHP_VERSION, '5.4.21', '<')) { if (!class_exists('Debugger')) { App::load('Debugger'); } if (!class_exists('CakeText')) { App::uses('CakeText', 'Utility'); App::load('CakeText'); } } $trace = Debugger::trace(array('start' => 1, 'format' => 'log')); $message .= "\nTrace:\n" . $trace . "\n"; } return CakeLog::write($log, $message); } /** * Generate an error page when some fatal error happens. * * @param int $code Code of error * @param string $description Error description * @param string $file File on which error occurred * @param int $line Line that triggered the error * @return bool * @throws FatalErrorException If the Exception renderer threw an exception during rendering, and debug > 0. * @throws InternalErrorException If the Exception renderer threw an exception during rendering, and debug is 0. */ public static function handleFatalError($code, $description, $file, $line) { $logMessage = 'Fatal Error (' . $code . '): ' . $description . ' in [' . $file . ', line ' . $line . ']'; CakeLog::write(LOG_ERR, $logMessage); $exceptionHandler = Configure::read('Exception.handler'); if (!is_callable($exceptionHandler)) { return false; } if (ob_get_level()) { ob_end_clean(); } if (Configure::read('debug')) { $exception = new FatalErrorException($description, 500, $file, $line); } else { $exception = new InternalErrorException(); } if (static::$_bailExceptionRendering) { static::$_bailExceptionRendering = false; throw $exception; } call_user_func($exceptionHandler, $exception); return false; } /** * Map an error code into an Error word, and log location. * * @param int $code Error code to map * @return array Array of error word, and log location. */ public static function mapErrorCode($code) { $error = $log = null; switch ($code) { case E_PARSE: case E_ERROR: case E_CORE_ERROR: case E_COMPILE_ERROR: case E_USER_ERROR: $error = 'Fatal Error'; $log = LOG_ERR; break; case E_WARNING: case E_USER_WARNING: case E_COMPILE_WARNING: case E_RECOVERABLE_ERROR: $error = 'Warning'; $log = LOG_WARNING; break; case E_NOTICE: case E_USER_NOTICE: $error = 'Notice'; $log = LOG_NOTICE; break; case E_STRICT: $error = 'Strict'; $log = LOG_NOTICE; break; case E_DEPRECATED: case E_USER_DEPRECATED: $error = 'Deprecated'; $log = LOG_NOTICE; break; } return array($error, $log); } } cakephp-2.8.0/lib/Cake/Error/ExceptionRenderer.php000066400000000000000000000232241265552240500220050ustar00rootroot00000000000000 1. * When debug < 1 a CakeException will render 404 or 500 errors. If an uncaught exception is thrown * and it is a type that ExceptionHandler does not know about it will be treated as a 500 error. * * ### Implementing application specific exception rendering * * You can implement application specific exception handling in one of a few ways: * * - Create an AppController::appError(); * - Create a subclass of ExceptionRenderer and configure it to be the `Exception.renderer` * * #### Using AppController::appError(); * * This controller method is called instead of the default exception handling. It receives the * thrown exception as its only argument. You should implement your error handling in that method. * * #### Using a subclass of ExceptionRenderer * * Using a subclass of ExceptionRenderer gives you full control over how Exceptions are rendered, you * can configure your class in your core.php, with `Configure::write('Exception.renderer', 'MyClass');` * You should place any custom exception renderers in `app/Lib/Error`. * * @package Cake.Error */ class ExceptionRenderer { /** * Controller instance. * * @var Controller */ public $controller = null; /** * template to render for CakeException * * @var string */ public $template = ''; /** * The method corresponding to the Exception this object is for. * * @var string */ public $method = ''; /** * The exception being handled. * * @var Exception */ public $error = null; /** * Creates the controller to perform rendering on the error response. * If the error is a CakeException it will be converted to either a 400 or a 500 * code error depending on the code used to construct the error. * * @param Exception|ParseError $exception Exception */ public function __construct($exception) { $this->controller = $this->_getController($exception); if (method_exists($this->controller, 'appError')) { $this->controller->appError($exception); return; } $method = $template = Inflector::variable(str_replace('Exception', '', get_class($exception))); $code = $exception->getCode(); $methodExists = method_exists($this, $method); if ($exception instanceof CakeException && !$methodExists) { $method = '_cakeError'; if (empty($template) || $template === 'internalError') { $template = 'error500'; } } elseif ($exception instanceof PDOException) { $method = 'pdoError'; $template = 'pdo_error'; $code = 500; } elseif (!$methodExists) { $method = 'error500'; if ($code >= 400 && $code < 500) { $method = 'error400'; } } $isNotDebug = !Configure::read('debug'); if ($isNotDebug && $method === '_cakeError') { $method = 'error400'; } if ($isNotDebug && $code == 500) { $method = 'error500'; } $this->template = $template; $this->method = $method; $this->error = $exception; } /** * Get the controller instance to handle the exception. * Override this method in subclasses to customize the controller used. * This method returns the built in `CakeErrorController` normally, or if an error is repeated * a bare controller will be used. * * @param Exception $exception The exception to get a controller for. * @return Controller */ protected function _getController($exception) { App::uses('AppController', 'Controller'); App::uses('CakeErrorController', 'Controller'); if (!$request = Router::getRequest(true)) { $request = new CakeRequest(); } $response = new CakeResponse(); if (method_exists($exception, 'responseHeader')) { $response->header($exception->responseHeader()); } if (class_exists('AppController')) { try { $controller = new CakeErrorController($request, $response); $controller->startupProcess(); $startup = true; } catch (Exception $e) { $startup = false; } // Retry RequestHandler, as another aspect of startupProcess() // could have failed. Ignore any exceptions out of startup, as // there could be userland input data parsers. if ($startup === false && !empty($controller) && $controller->Components->enabled('RequestHandler') ) { try { $controller->RequestHandler->startup($controller); } catch (Exception $e) { } } } if (empty($controller)) { $controller = new Controller($request, $response); $controller->viewPath = 'Errors'; } return $controller; } /** * Renders the response for the exception. * * @return void */ public function render() { if ($this->method) { call_user_func_array(array($this, $this->method), array($this->error)); } } /** * Generic handler for the internal framework errors CakePHP can generate. * * @param CakeException $error The exception to render. * @return void */ protected function _cakeError(CakeException $error) { $url = $this->controller->request->here(); $code = ($error->getCode() >= 400 && $error->getCode() < 506) ? $error->getCode() : 500; $this->controller->response->statusCode($code); $this->controller->set(array( 'code' => $code, 'name' => h($error->getMessage()), 'message' => h($error->getMessage()), 'url' => h($url), 'error' => $error, '_serialize' => array('code', 'name', 'message', 'url') )); $this->controller->set($error->getAttributes()); $this->_outputMessage($this->template); } /** * Convenience method to display a 400 series page. * * @param Exception $error The exception to render. * @return void */ public function error400($error) { $message = $error->getMessage(); if (!Configure::read('debug') && $error instanceof CakeException) { $message = __d('cake', 'Not Found'); } $url = $this->controller->request->here(); $this->controller->response->statusCode($error->getCode()); $this->controller->set(array( 'name' => h($message), 'message' => h($message), 'url' => h($url), 'error' => $error, '_serialize' => array('name', 'message', 'url') )); $this->_outputMessage('error400'); } /** * Convenience method to display a 500 page. * * @param Exception $error The exception to render. * @return void */ public function error500($error) { $message = $error->getMessage(); if (!Configure::read('debug')) { $message = __d('cake', 'An Internal Error Has Occurred.'); } $url = $this->controller->request->here(); $code = ($error->getCode() > 500 && $error->getCode() < 506) ? $error->getCode() : 500; $this->controller->response->statusCode($code); $this->controller->set(array( 'name' => h($message), 'message' => h($message), 'url' => h($url), 'error' => $error, '_serialize' => array('name', 'message', 'url') )); $this->_outputMessage('error500'); } /** * Convenience method to display a PDOException. * * @param PDOException $error The exception to render. * @return void */ public function pdoError(PDOException $error) { $url = $this->controller->request->here(); $code = 500; $this->controller->response->statusCode($code); $this->controller->set(array( 'code' => $code, 'name' => h($error->getMessage()), 'message' => h($error->getMessage()), 'url' => h($url), 'error' => $error, '_serialize' => array('code', 'name', 'message', 'url', 'error') )); $this->_outputMessage($this->template); } /** * Generate the response using the controller object. * * @param string $template The template to render. * @return void */ protected function _outputMessage($template) { try { $this->controller->render($template); $this->controller->afterFilter(); $this->controller->response->send(); } catch (MissingViewException $e) { $attributes = $e->getAttributes(); if (isset($attributes['file']) && strpos($attributes['file'], 'error500') !== false) { $this->_outputMessageSafe('error500'); } else { $this->_outputMessage('error500'); } } catch (MissingPluginException $e) { $attributes = $e->getAttributes(); if (isset($attributes['plugin']) && $attributes['plugin'] === $this->controller->plugin) { $this->controller->plugin = null; } $this->_outputMessageSafe('error500'); } catch (Exception $e) { $this->_outputMessageSafe('error500'); } } /** * A safer way to render error messages, replaces all helpers, with basics * and doesn't call component methods. * * @param string $template The template to render * @return void */ protected function _outputMessageSafe($template) { $this->controller->layoutPath = null; $this->controller->subDir = null; $this->controller->viewPath = 'Errors'; $this->controller->layout = 'error'; $this->controller->helpers = array('Form', 'Html', 'Session'); $view = new View($this->controller); $this->controller->response->body($view->render($template, 'error')); $this->controller->response->type('html'); $this->controller->response->send(); } } cakephp-2.8.0/lib/Cake/Error/exceptions.php000066400000000000000000000335131265552240500205430ustar00rootroot00000000000000 "header value" * - an array of string headers is also accepted * @param string $value The header value. * @return array * @see CakeResponse::header() */ public function responseHeader($header = null, $value = null) { if ($header) { if (is_array($header)) { return $this->_responseHeaders = $header; } $this->_responseHeaders = array($header => $value); } return $this->_responseHeaders; } } /** * Parent class for all of the HTTP related exceptions in CakePHP. * All HTTP status/error related exceptions should extend this class so * catch blocks can be specifically typed. * * @package Cake.Error */ if (!class_exists('HttpException', false)) { class HttpException extends CakeBaseException { } } /** * Represents an HTTP 400 error. * * @package Cake.Error */ class BadRequestException extends HttpException { /** * Constructor * * @param string $message If no message is given 'Bad Request' will be the message * @param int $code Status code, defaults to 400 */ public function __construct($message = null, $code = 400) { if (empty($message)) { $message = 'Bad Request'; } parent::__construct($message, $code); } } /** * Represents an HTTP 401 error. * * @package Cake.Error */ class UnauthorizedException extends HttpException { /** * Constructor * * @param string $message If no message is given 'Unauthorized' will be the message * @param int $code Status code, defaults to 401 */ public function __construct($message = null, $code = 401) { if (empty($message)) { $message = 'Unauthorized'; } parent::__construct($message, $code); } } /** * Represents an HTTP 403 error. * * @package Cake.Error */ class ForbiddenException extends HttpException { /** * Constructor * * @param string $message If no message is given 'Forbidden' will be the message * @param int $code Status code, defaults to 403 */ public function __construct($message = null, $code = 403) { if (empty($message)) { $message = 'Forbidden'; } parent::__construct($message, $code); } } /** * Represents an HTTP 404 error. * * @package Cake.Error */ class NotFoundException extends HttpException { /** * Constructor * * @param string $message If no message is given 'Not Found' will be the message * @param int $code Status code, defaults to 404 */ public function __construct($message = null, $code = 404) { if (empty($message)) { $message = 'Not Found'; } parent::__construct($message, $code); } } /** * Represents an HTTP 405 error. * * @package Cake.Error */ class MethodNotAllowedException extends HttpException { /** * Constructor * * @param string $message If no message is given 'Method Not Allowed' will be the message * @param int $code Status code, defaults to 405 */ public function __construct($message = null, $code = 405) { if (empty($message)) { $message = 'Method Not Allowed'; } parent::__construct($message, $code); } } /** * Represents an HTTP 500 error. * * @package Cake.Error */ class InternalErrorException extends HttpException { /** * Constructor * * @param string $message If no message is given 'Internal Server Error' will be the message * @param int $code Status code, defaults to 500 */ public function __construct($message = null, $code = 500) { if (empty($message)) { $message = 'Internal Server Error'; } parent::__construct($message, $code); } } /** * CakeException is used a base class for CakePHP's internal exceptions. * In general framework errors are interpreted as 500 code errors. * * @package Cake.Error */ class CakeException extends CakeBaseException { /** * Array of attributes that are passed in from the constructor, and * made available in the view when a development error is displayed. * * @var array */ protected $_attributes = array(); /** * Template string that has attributes sprintf()'ed into it. * * @var string */ protected $_messageTemplate = ''; /** * Constructor. * * Allows you to create exceptions that are treated as framework errors and disabled * when debug = 0. * * @param string|array $message Either the string of the error message, or an array of attributes * that are made available in the view, and sprintf()'d into CakeException::$_messageTemplate * @param int $code The code of the error, is also the HTTP status code for the error. */ public function __construct($message, $code = 500) { if (is_array($message)) { $this->_attributes = $message; $message = __d('cake_dev', $this->_messageTemplate, $message); } parent::__construct($message, $code); } /** * Get the passed in attributes * * @return array */ public function getAttributes() { return $this->_attributes; } } /** * Missing Controller exception - used when a controller * cannot be found. * * @package Cake.Error */ class MissingControllerException extends CakeException { protected $_messageTemplate = 'Controller class %s could not be found.'; //@codingStandardsIgnoreStart public function __construct($message, $code = 404) { parent::__construct($message, $code); } //@codingStandardsIgnoreEnd } /** * Missing Action exception - used when a controller action * cannot be found. * * @package Cake.Error */ class MissingActionException extends CakeException { protected $_messageTemplate = 'Action %s::%s() could not be found.'; //@codingStandardsIgnoreStart public function __construct($message, $code = 404) { parent::__construct($message, $code); } //@codingStandardsIgnoreEnd } /** * Private Action exception - used when a controller action * starts with a `_`. * * @package Cake.Error */ class PrivateActionException extends CakeException { protected $_messageTemplate = 'Private Action %s::%s() is not directly accessible.'; //@codingStandardsIgnoreStart public function __construct($message, $code = 404, Exception $previous = null) { parent::__construct($message, $code, $previous); } //@codingStandardsIgnoreEnd } /** * Used when a component cannot be found. * * @package Cake.Error */ class MissingComponentException extends CakeException { protected $_messageTemplate = 'Component class %s could not be found.'; } /** * Used when a behavior cannot be found. * * @package Cake.Error */ class MissingBehaviorException extends CakeException { protected $_messageTemplate = 'Behavior class %s could not be found.'; } /** * Used when a view file cannot be found. * * @package Cake.Error */ class MissingViewException extends CakeException { protected $_messageTemplate = 'View file "%s" is missing.'; } /** * Used when a layout file cannot be found. * * @package Cake.Error */ class MissingLayoutException extends CakeException { protected $_messageTemplate = 'Layout file "%s" is missing.'; } /** * Used when a helper cannot be found. * * @package Cake.Error */ class MissingHelperException extends CakeException { protected $_messageTemplate = 'Helper class %s could not be found.'; } /** * Runtime Exceptions for ConnectionManager * * @package Cake.Error */ class MissingDatabaseException extends CakeException { protected $_messageTemplate = 'Database connection "%s" could not be found.'; } /** * Used when no connections can be found. * * @package Cake.Error */ class MissingConnectionException extends CakeException { protected $_messageTemplate = 'Database connection "%s" is missing, or could not be created.'; /** * Constructor * * @param string|array $message The error message. * @param int $code The error code. */ public function __construct($message, $code = 500) { if (is_array($message)) { $message += array('enabled' => true); } parent::__construct($message, $code); } } /** * Used when a Task cannot be found. * * @package Cake.Error */ class MissingTaskException extends CakeException { protected $_messageTemplate = 'Task class %s could not be found.'; } /** * Used when a shell method cannot be found. * * @package Cake.Error */ class MissingShellMethodException extends CakeException { protected $_messageTemplate = "Unknown command %1\$s %2\$s.\nFor usage try `cake %1\$s --help`"; } /** * Used when a shell cannot be found. * * @package Cake.Error */ class MissingShellException extends CakeException { protected $_messageTemplate = 'Shell class %s could not be found.'; } /** * Exception class to be thrown when a datasource configuration is not found * * @package Cake.Error */ class MissingDatasourceConfigException extends CakeException { protected $_messageTemplate = 'The datasource configuration "%s" was not found in database.php'; } /** * Used when a datasource cannot be found. * * @package Cake.Error */ class MissingDatasourceException extends CakeException { protected $_messageTemplate = 'Datasource class %s could not be found. %s'; } /** * Exception class to be thrown when a database table is not found in the datasource * * @package Cake.Error */ class MissingTableException extends CakeException { protected $_messageTemplate = 'Table %s for model %s was not found in datasource %s.'; } /** * Exception raised when a Model could not be found. * * @package Cake.Error */ class MissingModelException extends CakeException { protected $_messageTemplate = 'Model %s could not be found.'; } /** * Exception raised when a test loader could not be found * * @package Cake.Error */ class MissingTestLoaderException extends CakeException { protected $_messageTemplate = 'Test loader %s could not be found.'; } /** * Exception raised when a plugin could not be found * * @package Cake.Error */ class MissingPluginException extends CakeException { protected $_messageTemplate = 'Plugin %s could not be found.'; } /** * Exception raised when a Dispatcher filter could not be found * * @package Cake.Error */ class MissingDispatcherFilterException extends CakeException { protected $_messageTemplate = 'Dispatcher filter %s could not be found.'; } /** * Exception class for AclComponent and Interface implementations. * * @package Cake.Error */ class AclException extends CakeException { } /** * Exception class for Cache. This exception will be thrown from Cache when it * encounters an error. * * @package Cake.Error */ class CacheException extends CakeException { } /** * Exception class for Router. This exception will be thrown from Router when it * encounters an error. * * @package Cake.Error */ class RouterException extends CakeException { } /** * Exception class for CakeLog. This exception will be thrown from CakeLog when it * encounters an error. * * @package Cake.Error */ class CakeLogException extends CakeException { } /** * Exception class for CakeSession. This exception will be thrown from CakeSession when it * encounters an error. * * @package Cake.Error */ class CakeSessionException extends CakeException { } /** * Exception class for Configure. This exception will be thrown from Configure when it * encounters an error. * * @package Cake.Error */ class ConfigureException extends CakeException { } /** * Exception class for Socket. This exception will be thrown from CakeSocket, CakeEmail, HttpSocket * SmtpTransport, MailTransport and HttpResponse when it encounters an error. * * @package Cake.Error */ class SocketException extends CakeException { } /** * Exception class for Xml. This exception will be thrown from Xml when it * encounters an error. * * @package Cake.Error */ class XmlException extends CakeException { } /** * Exception class for Console libraries. This exception will be thrown from Console library * classes when they encounter an error. * * @package Cake.Error */ class ConsoleException extends CakeException { } /** * Represents a fatal error * * @package Cake.Error */ class FatalErrorException extends CakeException { /** * Constructor * * @param string $message The error message. * @param int $code The error code. * @param string $file The file the error occurred in. * @param int $line The line the error occurred on. */ public function __construct($message, $code = 500, $file = null, $line = null) { parent::__construct($message, $code); if ($file) { $this->file = $file; } if ($line) { $this->line = $line; } } } /** * Not Implemented Exception - used when an API method is not implemented * * @package Cake.Error */ class NotImplementedException extends CakeException { protected $_messageTemplate = '%s is not implemented.'; //@codingStandardsIgnoreStart public function __construct($message, $code = 501) { parent::__construct($message, $code); } //@codingStandardsIgnoreEnd } cakephp-2.8.0/lib/Cake/Event/000077500000000000000000000000001265552240500156345ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Event/CakeEvent.php000066400000000000000000000056271265552240500202240ustar00rootroot00000000000000 $userData)); * $event = new CakeEvent('User.afterRegister', $UserModel); * ``` */ public function __construct($name, $subject = null, $data = null) { $this->_name = $name; $this->data = $data; $this->_subject = $subject; } /** * Dynamically returns the name and subject if accessed directly * * @param string $attribute Attribute name. * @return mixed */ public function __get($attribute) { if ($attribute === 'name' || $attribute === 'subject') { return $this->{$attribute}(); } } /** * Returns the name of this event. This is usually used as the event identifier * * @return string */ public function name() { return $this->_name; } /** * Returns the subject of this event * * @return object */ public function subject() { return $this->_subject; } /** * Stops the event from being used anymore * * @return void */ public function stopPropagation() { return $this->_stopped = true; } /** * Check if the event is stopped * * @return bool True if the event is stopped */ public function isStopped() { return $this->_stopped; } } cakephp-2.8.0/lib/Cake/Event/CakeEventListener.php000066400000000000000000000030071265552240500217200ustar00rootroot00000000000000 'sendEmail', * 'Article.afterBuy' => 'decrementInventory', * 'User.onRegister' => array('callable' => 'logRegistration', 'priority' => 20, 'passParams' => true) * ); * } * ``` * * @return array associative array or event key names pointing to the function * that should be called in the object when the respective event is fired */ public function implementedEvents(); } cakephp-2.8.0/lib/Cake/Event/CakeEventManager.php000066400000000000000000000231231265552240500215060ustar00rootroot00000000000000_isGlobal = true; return static::$_generalManager; } /** * Adds a new listener to an event. Listeners * * @param callback|CakeEventListener $callable PHP valid callback type or instance of CakeEventListener to be called * when the event named with $eventKey is triggered. If a CakeEventListener instance is passed, then the `implementedEvents` * method will be called on the object to register the declared events individually as methods to be managed by this class. * It is possible to define multiple event handlers per event name. * * @param string $eventKey The event unique identifier name with which the callback will be associated. If $callable * is an instance of CakeEventListener this argument will be ignored * * @param array $options used to set the `priority` and `passParams` flags to the listener. * Priorities are handled like queues, and multiple attachments added to the same priority queue will be treated in * the order of insertion. `passParams` means that the event data property will be converted to function arguments * when the listener is called. If $called is an instance of CakeEventListener, this parameter will be ignored * * @return void * @throws InvalidArgumentException When event key is missing or callable is not an * instance of CakeEventListener. */ public function attach($callable, $eventKey = null, $options = array()) { if (!$eventKey && !($callable instanceof CakeEventListener)) { throw new InvalidArgumentException(__d('cake_dev', 'The eventKey variable is required')); } if ($callable instanceof CakeEventListener) { $this->_attachSubscriber($callable); return; } $options = $options + array('priority' => static::$defaultPriority, 'passParams' => false); $this->_listeners[$eventKey][$options['priority']][] = array( 'callable' => $callable, 'passParams' => $options['passParams'], ); } /** * Auxiliary function to attach all implemented callbacks of a CakeEventListener class instance * as individual methods on this manager * * @param CakeEventListener $subscriber Event listener. * @return void */ protected function _attachSubscriber(CakeEventListener $subscriber) { foreach ((array)$subscriber->implementedEvents() as $eventKey => $function) { $options = array(); $method = $function; if (is_array($function) && isset($function['callable'])) { list($method, $options) = $this->_extractCallable($function, $subscriber); } elseif (is_array($function) && is_numeric(key($function))) { foreach ($function as $f) { list($method, $options) = $this->_extractCallable($f, $subscriber); $this->attach($method, $eventKey, $options); } continue; } if (is_string($method)) { $method = array($subscriber, $function); } $this->attach($method, $eventKey, $options); } } /** * Auxiliary function to extract and return a PHP callback type out of the callable definition * from the return value of the `implementedEvents` method on a CakeEventListener * * @param array $function the array taken from a handler definition for an event * @param CakeEventListener $object The handler object * @return callback */ protected function _extractCallable($function, $object) { $method = $function['callable']; $options = $function; unset($options['callable']); if (is_string($method)) { $method = array($object, $method); } return array($method, $options); } /** * Removes a listener from the active listeners. * * @param callback|CakeEventListener $callable any valid PHP callback type or an instance of CakeEventListener * @param string $eventKey The event unique identifier name with which the callback has been associated * @return void */ public function detach($callable, $eventKey = null) { if ($callable instanceof CakeEventListener) { return $this->_detachSubscriber($callable, $eventKey); } if (empty($eventKey)) { foreach (array_keys($this->_listeners) as $eventKey) { $this->detach($callable, $eventKey); } return; } if (empty($this->_listeners[$eventKey])) { return; } foreach ($this->_listeners[$eventKey] as $priority => $callables) { foreach ($callables as $k => $callback) { if ($callback['callable'] === $callable) { unset($this->_listeners[$eventKey][$priority][$k]); break; } } } } /** * Auxiliary function to help detach all listeners provided by an object implementing CakeEventListener * * @param CakeEventListener $subscriber the subscriber to be detached * @param string $eventKey optional event key name to unsubscribe the listener from * @return void */ protected function _detachSubscriber(CakeEventListener $subscriber, $eventKey = null) { $events = (array)$subscriber->implementedEvents(); if (!empty($eventKey) && empty($events[$eventKey])) { return; } elseif (!empty($eventKey)) { $events = array($eventKey => $events[$eventKey]); } foreach ($events as $key => $function) { if (is_array($function)) { if (is_numeric(key($function))) { foreach ($function as $handler) { $handler = isset($handler['callable']) ? $handler['callable'] : $handler; $this->detach(array($subscriber, $handler), $key); } continue; } $function = $function['callable']; } $this->detach(array($subscriber, $function), $key); } } /** * Dispatches a new event to all configured listeners * * @param string|CakeEvent $event the event key name or instance of CakeEvent * @return CakeEvent * @triggers $event */ public function dispatch($event) { if (is_string($event)) { $event = new CakeEvent($event); } $listeners = $this->listeners($event->name()); if (empty($listeners)) { return $event; } foreach ($listeners as $listener) { if ($event->isStopped()) { break; } if ($listener['passParams'] === true) { $result = call_user_func_array($listener['callable'], $event->data); } else { $result = call_user_func($listener['callable'], $event); } if ($result === false) { $event->stopPropagation(); } if ($result !== null) { $event->result = $result; } } return $event; } /** * Returns a list of all listeners for an eventKey in the order they should be called * * @param string $eventKey Event key. * @return array */ public function listeners($eventKey) { $localListeners = array(); $priorities = array(); if (!$this->_isGlobal) { $localListeners = $this->prioritisedListeners($eventKey); $localListeners = empty($localListeners) ? array() : $localListeners; } $globalListeners = static::instance()->prioritisedListeners($eventKey); $globalListeners = empty($globalListeners) ? array() : $globalListeners; $priorities = array_merge(array_keys($globalListeners), array_keys($localListeners)); $priorities = array_unique($priorities); asort($priorities); $result = array(); foreach ($priorities as $priority) { if (isset($globalListeners[$priority])) { $result = array_merge($result, $globalListeners[$priority]); } if (isset($localListeners[$priority])) { $result = array_merge($result, $localListeners[$priority]); } } return $result; } /** * Returns the listeners for the specified event key indexed by priority * * @param string $eventKey Event key. * @return array */ public function prioritisedListeners($eventKey) { if (empty($this->_listeners[$eventKey])) { return array(); } return $this->_listeners[$eventKey]; } } cakephp-2.8.0/lib/Cake/I18n/000077500000000000000000000000001265552240500152725ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/I18n/I18n.php000066400000000000000000000533301265552240500165260ustar00rootroot00000000000000l10n = new L10n(); } /** * Return a static instance of the I18n class * * @return I18n */ public static function getInstance() { static $instance = array(); if (!$instance) { $instance[0] = new I18n(); } return $instance[0]; } /** * Used by the translation functions in basics.php * Returns a translated string based on current language and translation files stored in locale folder * * @param string $singular String to translate * @param string $plural Plural string (if any) * @param string $domain Domain The domain of the translation. Domains are often used by plugin translations. * If null, the default domain will be used. * @param string $category Category The integer value of the category to use. * @param int $count Count Count is used with $plural to choose the correct plural form. * @param string $language Language to translate string to. * If null it checks for language in session followed by Config.language configuration variable. * @param string $context Context The context of the translation, e.g a verb or a noun. * @return string translated string. * @throws CakeException When '' is provided as a domain. */ public static function translate($singular, $plural = null, $domain = null, $category = self::LC_MESSAGES, $count = null, $language = null, $context = null ) { $_this = I18n::getInstance(); if (strpos($singular, "\r\n") !== false) { $singular = str_replace("\r\n", "\n", $singular); } if ($plural !== null && strpos($plural, "\r\n") !== false) { $plural = str_replace("\r\n", "\n", $plural); } if (is_numeric($category)) { $_this->category = $_this->_categories[$category]; } if (empty($language)) { if (CakeSession::started()) { $language = CakeSession::read('Config.language'); } if (empty($language)) { $language = Configure::read('Config.language'); } } if (($_this->_lang && $_this->_lang !== $language) || !$_this->_lang) { $lang = $_this->l10n->get($language); $_this->_lang = $lang; } if ($domain === null) { $domain = static::$defaultDomain; } if ($domain === '') { throw new CakeException(__d('cake_dev', 'You cannot use "" as a domain.')); } $_this->domain = $domain . '_' . $_this->l10n->lang; if (!isset($_this->_domains[$domain][$_this->_lang])) { $_this->_domains[$domain][$_this->_lang] = Cache::read($_this->domain, '_cake_core_'); } if (!isset($_this->_domains[$domain][$_this->_lang][$_this->category])) { $_this->_bindTextDomain($domain); Cache::write($_this->domain, $_this->_domains[$domain][$_this->_lang], '_cake_core_'); } if ($_this->category === 'LC_TIME') { return $_this->_translateTime($singular, $domain); } if (!isset($count)) { $plurals = 0; } elseif (!empty($_this->_domains[$domain][$_this->_lang][$_this->category]["%plural-c"]) && $_this->_noLocale === false) { $header = $_this->_domains[$domain][$_this->_lang][$_this->category]["%plural-c"]; $plurals = $_this->_pluralGuess($header, $count); } else { if ($count != 1) { $plurals = 1; } else { $plurals = 0; } } if (!empty($_this->_domains[$domain][$_this->_lang][$_this->category][$singular][$context])) { if (($trans = $_this->_domains[$domain][$_this->_lang][$_this->category][$singular][$context]) || ($plurals) && ($trans = $_this->_domains[$domain][$_this->_lang][$_this->category][$plural][$context]) ) { if (is_array($trans)) { if (isset($trans[$plurals])) { $trans = $trans[$plurals]; } else { trigger_error( __d('cake_dev', 'Missing plural form translation for "%s" in "%s" domain, "%s" locale. ' . ' Check your po file for correct plurals and valid Plural-Forms header.', $singular, $domain, $_this->_lang ), E_USER_WARNING ); $trans = $trans[0]; } } if (strlen($trans)) { return $trans; } } } if (!empty($plurals)) { return $plural; } return $singular; } /** * Clears the domains internal data array. Useful for testing i18n. * * @return void */ public static function clear() { $self = I18n::getInstance(); $self->_domains = array(); } /** * Get the loaded domains cache. * * @return array */ public static function domains() { $self = I18n::getInstance(); return $self->_domains; } /** * Attempts to find the plural form of a string. * * @param string $header Type * @param int $n Number * @return int plural match * @link http://localization-guide.readthedocs.org/en/latest/l10n/pluralforms.html * @link https://developer.mozilla.org/en-US/docs/Mozilla/Localization/Localization_and_Plurals#List_of_Plural_Rules */ protected function _pluralGuess($header, $n) { if (!is_string($header) || $header === "nplurals=1;plural=0;" || !isset($header[0])) { return 0; } if ($header === "nplurals=2;plural=n!=1;") { return $n != 1 ? 1 : 0; } elseif ($header === "nplurals=2;plural=n>1;") { return $n > 1 ? 1 : 0; } if (strpos($header, "plurals=3")) { if (strpos($header, "100!=11")) { if (strpos($header, "10<=4")) { return $n % 10 == 1 && $n % 100 != 11 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); } elseif (strpos($header, "100<10")) { return $n % 10 == 1 && $n % 100 != 11 ? 0 : ($n % 10 >= 2 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); } return $n % 10 == 1 && $n % 100 != 11 ? 0 : ($n != 0 ? 1 : 2); } elseif (strpos($header, "n==2")) { return $n == 1 ? 0 : ($n == 2 ? 1 : 2); } elseif (strpos($header, "n==0")) { return $n == 1 ? 0 : ($n == 0 || ($n % 100 > 0 && $n % 100 < 20) ? 1 : 2); } elseif (strpos($header, "n>=2")) { return $n == 1 ? 0 : ($n >= 2 && $n <= 4 ? 1 : 2); } elseif (strpos($header, "10>=2")) { return $n == 1 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2); } return $n % 10 == 1 ? 0 : ($n % 10 == 2 ? 1 : 2); } elseif (strpos($header, "plurals=4")) { if (strpos($header, "100==2")) { return $n % 100 == 1 ? 0 : ($n % 100 == 2 ? 1 : ($n % 100 == 3 || $n % 100 == 4 ? 2 : 3)); } elseif (strpos($header, "n>=3")) { return $n == 1 ? 0 : ($n == 2 ? 1 : ($n == 0 || ($n >= 3 && $n <= 10) ? 2 : 3)); } elseif (strpos($header, "100>=1")) { return $n == 1 ? 0 : ($n == 0 || ($n % 100 >= 1 && $n % 100 <= 10) ? 1 : ($n % 100 >= 11 && $n % 100 <= 20 ? 2 : 3)); } } elseif (strpos($header, "plurals=5")) { return $n == 1 ? 0 : ($n == 2 ? 1 : ($n >= 3 && $n <= 6 ? 2 : ($n >= 7 && $n <= 10 ? 3 : 4))); } elseif (strpos($header, "plurals=6")) { return $n == 0 ? 0 : ($n == 1 ? 1 : ($n == 2 ? 2 : ($n % 100 >= 3 && $n % 100 <= 10 ? 3 : ($n % 100 >= 11 ? 4 : 5)))); } return 0; } /** * Binds the given domain to a file in the specified directory. * * @param string $domain Domain to bind * @return string Domain binded */ protected function _bindTextDomain($domain) { $this->_noLocale = true; $core = true; $merge = array(); $searchPaths = App::path('locales'); $plugins = CakePlugin::loaded(); if (!empty($plugins)) { foreach ($plugins as $plugin) { $pluginDomain = Inflector::underscore($plugin); if ($pluginDomain === $domain) { $searchPaths[] = CakePlugin::path($plugin) . 'Locale' . DS; if (!Configure::read('I18n.preferApp')) { $searchPaths = array_reverse($searchPaths); } break; } } } foreach ($searchPaths as $directory) { foreach ($this->l10n->languagePath as $lang) { $localeDef = $directory . $lang . DS . $this->category; if (is_file($localeDef)) { $definitions = static::loadLocaleDefinition($localeDef); if ($definitions !== false) { $this->_domains[$domain][$this->_lang][$this->category] = $definitions; $this->_noLocale = false; return $domain; } } if ($core) { $app = $directory . $lang . DS . $this->category . DS . 'core'; $translations = false; if (is_file($app . '.mo')) { $translations = static::loadMo($app . '.mo'); } if ($translations === false && is_file($app . '.po')) { $translations = static::loadPo($app . '.po'); } if ($translations !== false) { $this->_domains[$domain][$this->_lang][$this->category] = $translations; $merge[$domain][$this->_lang][$this->category] = $this->_domains[$domain][$this->_lang][$this->category]; $this->_noLocale = false; $core = null; } } $file = $directory . $lang . DS . $this->category . DS . $domain; $translations = false; if (is_file($file . '.mo')) { $translations = static::loadMo($file . '.mo'); } if ($translations === false && is_file($file . '.po')) { $translations = static::loadPo($file . '.po'); } if ($translations !== false) { $this->_domains[$domain][$this->_lang][$this->category] = $translations; $this->_noLocale = false; break 2; } } } if (empty($this->_domains[$domain][$this->_lang][$this->category])) { $this->_domains[$domain][$this->_lang][$this->category] = array(); return $domain; } if (isset($this->_domains[$domain][$this->_lang][$this->category][""])) { $head = $this->_domains[$domain][$this->_lang][$this->category][""]; foreach (explode("\n", $head) as $line) { $header = strtok($line, ':'); $line = trim(strtok("\n")); $this->_domains[$domain][$this->_lang][$this->category]["%po-header"][strtolower($header)] = $line; } if (isset($this->_domains[$domain][$this->_lang][$this->category]["%po-header"]["plural-forms"])) { $switch = preg_replace("/(?:[() {}\\[\\]^\\s*\\]]+)/", "", $this->_domains[$domain][$this->_lang][$this->category]["%po-header"]["plural-forms"]); $this->_domains[$domain][$this->_lang][$this->category]["%plural-c"] = $switch; unset($this->_domains[$domain][$this->_lang][$this->category]["%po-header"]); } $this->_domains = Hash::mergeDiff($this->_domains, $merge); if (isset($this->_domains[$domain][$this->_lang][$this->category][null])) { unset($this->_domains[$domain][$this->_lang][$this->category][null]); } } return $domain; } /** * Loads the binary .mo file and returns array of translations * * @param string $filename Binary .mo file to load * @return mixed Array of translations on success or false on failure * @link https://www.gnu.org/software/gettext/manual/html_node/MO-Files.html */ public static function loadMo($filename) { $translations = false; // @codingStandardsIgnoreStart // Binary files extracted makes non-standard local variables if ($data = file_get_contents($filename)) { $translations = array(); $header = substr($data, 0, 20); $header = unpack('L1magic/L1version/L1count/L1o_msg/L1o_trn', $header); extract($header); if ((dechex($magic) === '950412de' || dechex($magic) === 'ffffffff950412de') && !$version) { for ($n = 0; $n < $count; $n++) { $r = unpack("L1len/L1offs", substr($data, $o_msg + $n * 8, 8)); $msgid = substr($data, $r["offs"], $r["len"]); unset($msgid_plural); $context = null; if (strpos($msgid, "\x04") !== false) { list($context, $msgid) = explode("\x04", $msgid); } if (strpos($msgid, "\000")) { list($msgid, $msgid_plural) = explode("\000", $msgid); } $r = unpack("L1len/L1offs", substr($data, $o_trn + $n * 8, 8)); $msgstr = substr($data, $r["offs"], $r["len"]); if (strpos($msgstr, "\000")) { $msgstr = explode("\000", $msgstr); } if ($msgid != '') { $translations[$msgid][$context] = $msgstr; } else { $translations[$msgid] = $msgstr; } if (isset($msgid_plural)) { $translations[$msgid_plural] =& $translations[$msgid]; } } } } // @codingStandardsIgnoreEnd return $translations; } /** * Loads the text .po file and returns array of translations * * @param string $filename Text .po file to load * @return mixed Array of translations on success or false on failure */ public static function loadPo($filename) { if (!$file = fopen($filename, 'r')) { return false; } $type = 0; $translations = array(); $translationKey = ''; $translationContext = null; $plural = 0; $header = ''; do { $line = trim(fgets($file)); if ($line === '' || $line[0] === '#') { $translationContext = null; continue; } if (preg_match("/msgid[[:space:]]+\"(.+)\"$/i", $line, $regs)) { $type = 1; $translationKey = stripcslashes($regs[1]); } elseif (preg_match("/msgid[[:space:]]+\"\"$/i", $line, $regs)) { $type = 2; $translationKey = ''; } elseif (preg_match("/msgctxt[[:space:]]+\"(.+)\"$/i", $line, $regs)) { $translationContext = $regs[1]; } elseif (preg_match("/^\"(.*)\"$/i", $line, $regs) && ($type == 1 || $type == 2 || $type == 3)) { $type = 3; $translationKey .= stripcslashes($regs[1]); } elseif (preg_match("/msgstr[[:space:]]+\"(.+)\"$/i", $line, $regs) && ($type == 1 || $type == 3) && $translationKey) { $translations[$translationKey][$translationContext] = stripcslashes($regs[1]); $type = 4; } elseif (preg_match("/msgstr[[:space:]]+\"\"$/i", $line, $regs) && ($type == 1 || $type == 3) && $translationKey) { $type = 4; $translations[$translationKey][$translationContext] = ''; } elseif (preg_match("/^\"(.*)\"$/i", $line, $regs) && $type == 4 && $translationKey) { $translations[$translationKey][$translationContext] .= stripcslashes($regs[1]); } elseif (preg_match("/msgid_plural[[:space:]]+\".*\"$/i", $line, $regs)) { $type = 6; } elseif (preg_match("/^\"(.*)\"$/i", $line, $regs) && $type == 6 && $translationKey) { $type = 6; } elseif (preg_match("/msgstr\[(\d+)\][[:space:]]+\"(.+)\"$/i", $line, $regs) && ($type == 6 || $type == 7) && $translationKey) { $plural = $regs[1]; $translations[$translationKey][$translationContext][$plural] = stripcslashes($regs[2]); $type = 7; } elseif (preg_match("/msgstr\[(\d+)\][[:space:]]+\"\"$/i", $line, $regs) && ($type == 6 || $type == 7) && $translationKey) { $plural = $regs[1]; $translations[$translationKey][$translationContext][$plural] = ''; $type = 7; } elseif (preg_match("/^\"(.*)\"$/i", $line, $regs) && $type == 7 && $translationKey) { $translations[$translationKey][$translationContext][$plural] .= stripcslashes($regs[1]); } elseif (preg_match("/msgstr[[:space:]]+\"(.+)\"$/i", $line, $regs) && $type == 2 && !$translationKey) { $header .= stripcslashes($regs[1]); $type = 5; } elseif (preg_match("/msgstr[[:space:]]+\"\"$/i", $line, $regs) && !$translationKey) { $header = ''; $type = 5; } elseif (preg_match("/^\"(.*)\"$/i", $line, $regs) && $type == 5) { $header .= stripcslashes($regs[1]); } else { unset($translations[$translationKey][$translationContext]); $type = 0; $translationKey = ''; $translationContext = null; $plural = 0; } } while (!feof($file)); fclose($file); $merge[''] = $header; return array_merge($merge, $translations); } /** * Parses a locale definition file following the POSIX standard * * @param string $filename Locale definition filename * @return mixed Array of definitions on success or false on failure */ public static function loadLocaleDefinition($filename) { if (!$file = fopen($filename, 'r')) { return false; } $definitions = array(); $comment = '#'; $escape = '\\'; $currentToken = false; $value = ''; $_this = I18n::getInstance(); while ($line = fgets($file)) { $line = trim($line); if (empty($line) || $line[0] === $comment) { continue; } $parts = preg_split("/[[:space:]]+/", $line); if ($parts[0] === 'comment_char') { $comment = $parts[1]; continue; } if ($parts[0] === 'escape_char') { $escape = $parts[1]; continue; } $count = count($parts); if ($count === 2) { $currentToken = $parts[0]; $value = $parts[1]; } elseif ($count === 1) { $value = is_array($value) ? $parts[0] : $value . $parts[0]; } else { continue; } $len = strlen($value) - 1; if ($value[$len] === $escape) { $value = substr($value, 0, $len); continue; } $mustEscape = array($escape . ',', $escape . ';', $escape . '<', $escape . '>', $escape . $escape); $replacements = array_map('crc32', $mustEscape); $value = str_replace($mustEscape, $replacements, $value); $value = explode(';', $value); $_this->_escape = $escape; foreach ($value as $i => $val) { $val = trim($val, '"'); $val = preg_replace_callback('/(?:<)?(.[^>]*)(?:>)?/', array(&$_this, '_parseLiteralValue'), $val); $val = str_replace($replacements, $mustEscape, $val); $value[$i] = $val; } if (count($value) === 1) { $definitions[$currentToken] = array_pop($value); } else { $definitions[$currentToken] = $value; } } return $definitions; } /** * Puts the parameters in raw translated strings * * @param string $translated The raw translated string * @param array $args The arguments to put in the translation * @return string Translated string with arguments */ public static function insertArgs($translated, array $args) { $len = count($args); if ($len === 0 || ($len === 1 && $args[0] === null)) { return $translated; } if (is_array($args[0])) { $args = $args[0]; } $translated = preg_replace('/(?_escape . 'x') { $delimiter = $this->_escape . 'x'; return implode('', array_map('chr', array_map('hexdec', array_filter(explode($delimiter, $string))))); } if (substr($string, 0, 2) === $this->_escape . 'd') { $delimiter = $this->_escape . 'd'; return implode('', array_map('chr', array_filter(explode($delimiter, $string)))); } if ($string[0] === $this->_escape && isset($string[1]) && is_numeric($string[1])) { $delimiter = $this->_escape; return implode('', array_map('chr', array_filter(explode($delimiter, $string)))); } if (substr($string, 0, 3) === 'U00') { $delimiter = 'U00'; return implode('', array_map('chr', array_map('hexdec', array_filter(explode($delimiter, $string))))); } if (preg_match('/U([0-9a-fA-F]{4})/', $string, $match)) { return Multibyte::ascii(array(hexdec($match[1]))); } return $string; } /** * Returns a Time format definition from corresponding domain * * @param string $format Format to be translated * @param string $domain Domain where format is stored * @return mixed translated format string if only value or array of translated strings for corresponding format. */ protected function _translateTime($format, $domain) { if (!empty($this->_domains[$domain][$this->_lang]['LC_TIME'][$format])) { if (($trans = $this->_domains[$domain][$this->_lang][$this->category][$format])) { return $trans; } } return $format; } } cakephp-2.8.0/lib/Cake/I18n/L10n.php000066400000000000000000000711341265552240500165230ustar00rootroot00000000000000 'af', /* Albanian */ 'sqi' => 'sq', /* Albanian - bibliographic */ 'alb' => 'sq', /* Arabic */ 'ara' => 'ar', /* Armenian/Armenia */ 'hye' => 'hy', /* Basque */ 'eus' => 'eu', /* Basque */ 'baq' => 'eu', /* Tibetan */ 'bod' => 'bo', /* Tibetan - bibliographic */ 'tib' => 'bo', /* Bosnian */ 'bos' => 'bs', /* Bulgarian */ 'bul' => 'bg', /* Byelorussian */ 'bel' => 'be', /* Catalan */ 'cat' => 'ca', /* Chinese */ 'zho' => 'zh', /* Chinese - bibliographic */ 'chi' => 'zh', /* Croatian */ 'hrv' => 'hr', /* Czech */ 'ces' => 'cs', /* Czech - bibliographic */ 'cze' => 'cs', /* Danish */ 'dan' => 'da', /* Dutch (Standard) */ 'nld' => 'nl', /* Dutch (Standard) - bibliographic */ 'dut' => 'nl', /* English */ 'eng' => 'en', /* Estonian */ 'est' => 'et', /* Faeroese */ 'fao' => 'fo', /* Farsi/Persian */ 'fas' => 'fa', /* Farsi/Persian - bibliographic */ 'per' => 'fa', /* Finnish */ 'fin' => 'fi', /* French (Standard) */ 'fra' => 'fr', /* French (Standard) - bibliographic */ 'fre' => 'fr', /* Gaelic (Scots) */ 'gla' => 'gd', /* Galician */ 'glg' => 'gl', /* German (Standard) */ 'deu' => 'de', /* German (Standard) - bibliographic */ 'ger' => 'de', /* Greek */ 'gre' => 'el', /* Greek */ 'ell' => 'el', /* Hebrew */ 'heb' => 'he', /* Hindi */ 'hin' => 'hi', /* Hungarian */ 'hun' => 'hu', /* Icelandic */ 'isl' => 'is', /* Icelandic - bibliographic */ 'ice' => 'is', /* Indonesian */ 'ind' => 'id', /* Irish */ 'gle' => 'ga', /* Italian */ 'ita' => 'it', /* Japanese */ 'jpn' => 'ja', /* Kazakh */ 'kaz' => 'kk', /* Kalaallisut (Greenlandic) */ 'kal' => 'kl', /* Korean */ 'kor' => 'ko', /* Latvian */ 'lav' => 'lv', /* Limburgish */ 'lim' => 'li', /* Lithuanian */ 'lit' => 'lt', /* Macedonian */ 'mkd' => 'mk', /* Macedonian - bibliographic */ 'mac' => 'mk', /* Malaysian */ 'msa' => 'ms', /* Malaysian - bibliographic */ 'may' => 'ms', /* Maltese */ 'mlt' => 'mt', /* Norwegian */ 'nor' => 'no', /* Norwegian Bokmal */ 'nob' => 'nb', /* Norwegian Nynorsk */ 'nno' => 'nn', /* Polish */ 'pol' => 'pl', /* Portuguese (Portugal) */ 'por' => 'pt', /* Rhaeto-Romanic */ 'roh' => 'rm', /* Romanian */ 'ron' => 'ro', /* Romanian - bibliographic */ 'rum' => 'ro', /* Russian */ 'rus' => 'ru', /* Sami */ 'sme' => 'se', /* Serbian */ 'srp' => 'sr', /* Slovak */ 'slk' => 'sk', /* Slovak - bibliographic */ 'slo' => 'sk', /* Slovenian */ 'slv' => 'sl', /* Sorbian */ 'wen' => 'sb', /* Spanish (Spain - Traditional) */ 'spa' => 'es', /* Swedish */ 'swe' => 'sv', /* Thai */ 'tha' => 'th', /* Tsonga */ 'tso' => 'ts', /* Tswana */ 'tsn' => 'tn', /* Turkish */ 'tur' => 'tr', /* Ukrainian */ 'ukr' => 'uk', /* Urdu */ 'urd' => 'ur', /* Venda */ 'ven' => 've', /* Vietnamese */ 'vie' => 'vi', /* Welsh */ 'cym' => 'cy', /* Welsh - bibliographic */ 'wel' => 'cy', /* Xhosa */ 'xho' => 'xh', /* Yiddish */ 'yid' => 'yi', /* Zulu */ 'zul' => 'zu' ); /** * HTTP_ACCEPT_LANGUAGE catalog * * holds all information related to a language * * @var array */ protected $_l10nCatalog = array( 'af' => array('language' => 'Afrikaans', 'locale' => 'afr', 'localeFallback' => 'afr', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ar' => array('language' => 'Arabic', 'locale' => 'ara', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-ae' => array('language' => 'Arabic (U.A.E.)', 'locale' => 'ar_ae', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-bh' => array('language' => 'Arabic (Bahrain)', 'locale' => 'ar_bh', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-dz' => array('language' => 'Arabic (Algeria)', 'locale' => 'ar_dz', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-eg' => array('language' => 'Arabic (Egypt)', 'locale' => 'ar_eg', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-iq' => array('language' => 'Arabic (Iraq)', 'locale' => 'ar_iq', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-jo' => array('language' => 'Arabic (Jordan)', 'locale' => 'ar_jo', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-kw' => array('language' => 'Arabic (Kuwait)', 'locale' => 'ar_kw', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-lb' => array('language' => 'Arabic (Lebanon)', 'locale' => 'ar_lb', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-ly' => array('language' => 'Arabic (Libya)', 'locale' => 'ar_ly', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-ma' => array('language' => 'Arabic (Morocco)', 'locale' => 'ar_ma', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-om' => array('language' => 'Arabic (Oman)', 'locale' => 'ar_om', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-qa' => array('language' => 'Arabic (Qatar)', 'locale' => 'ar_qa', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-sa' => array('language' => 'Arabic (Saudi Arabia)', 'locale' => 'ar_sa', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-sy' => array('language' => 'Arabic (Syria)', 'locale' => 'ar_sy', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-tn' => array('language' => 'Arabic (Tunisia)', 'locale' => 'ar_tn', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-ye' => array('language' => 'Arabic (Yemen)', 'locale' => 'ar_ye', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'be' => array('language' => 'Byelorussian', 'locale' => 'bel', 'localeFallback' => 'bel', 'charset' => 'utf-8', 'direction' => 'ltr'), 'bg' => array('language' => 'Bulgarian', 'locale' => 'bul', 'localeFallback' => 'bul', 'charset' => 'utf-8', 'direction' => 'ltr'), 'bo' => array('language' => 'Tibetan', 'locale' => 'bod', 'localeFallback' => 'bod', 'charset' => 'utf-8', 'direction' => 'ltr'), 'bo-cn' => array('language' => 'Tibetan (China)', 'locale' => 'bo_cn', 'localeFallback' => 'bod', 'charset' => 'utf-8', 'direction' => 'ltr'), 'bo-in' => array('language' => 'Tibetan (India)', 'locale' => 'bo_in', 'localeFallback' => 'bod', 'charset' => 'utf-8', 'direction' => 'ltr'), 'bs' => array('language' => 'Bosnian', 'locale' => 'bos', 'localeFallback' => 'bos', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ca' => array('language' => 'Catalan', 'locale' => 'cat', 'localeFallback' => 'cat', 'charset' => 'utf-8', 'direction' => 'ltr'), 'cs' => array('language' => 'Czech', 'locale' => 'ces', 'localeFallback' => 'ces', 'charset' => 'utf-8', 'direction' => 'ltr'), 'da' => array('language' => 'Danish', 'locale' => 'dan', 'localeFallback' => 'dan', 'charset' => 'utf-8', 'direction' => 'ltr'), 'de' => array('language' => 'German (Standard)', 'locale' => 'deu', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'), 'de-at' => array('language' => 'German (Austria)', 'locale' => 'de_at', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'), 'de-ch' => array('language' => 'German (Swiss)', 'locale' => 'de_ch', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'), 'de-de' => array('language' => 'German (Germany)', 'locale' => 'de_de', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'), 'de-li' => array('language' => 'German (Liechtenstein)', 'locale' => 'de_li', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'), 'de-lu' => array('language' => 'German (Luxembourg)', 'locale' => 'de_lu', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'), 'el' => array('language' => 'Greek', 'locale' => 'ell', 'localeFallback' => 'ell', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en' => array('language' => 'English', 'locale' => 'eng', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-au' => array('language' => 'English (Australian)', 'locale' => 'en_au', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-bz' => array('language' => 'English (Belize)', 'locale' => 'en_bz', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-ca' => array('language' => 'English (Canadian)', 'locale' => 'en_ca', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-gb' => array('language' => 'English (British)', 'locale' => 'en_gb', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-ie' => array('language' => 'English (Ireland)', 'locale' => 'en_ie', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-jm' => array('language' => 'English (Jamaica)', 'locale' => 'en_jm', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-nz' => array('language' => 'English (New Zealand)', 'locale' => 'en_nz', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-tt' => array('language' => 'English (Trinidad)', 'locale' => 'en_tt', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-us' => array('language' => 'English (United States)', 'locale' => 'en_us', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-za' => array('language' => 'English (South Africa)', 'locale' => 'en_za', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es' => array('language' => 'Spanish (Spain - Traditional)', 'locale' => 'spa', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-ar' => array('language' => 'Spanish (Argentina)', 'locale' => 'es_ar', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-bo' => array('language' => 'Spanish (Bolivia)', 'locale' => 'es_bo', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-cl' => array('language' => 'Spanish (Chile)', 'locale' => 'es_cl', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-co' => array('language' => 'Spanish (Colombia)', 'locale' => 'es_co', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-cr' => array('language' => 'Spanish (Costa Rica)', 'locale' => 'es_cr', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-do' => array('language' => 'Spanish (Dominican Republic)', 'locale' => 'es_do', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-ec' => array('language' => 'Spanish (Ecuador)', 'locale' => 'es_ec', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-es' => array('language' => 'Spanish (Spain)', 'locale' => 'es_es', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-gt' => array('language' => 'Spanish (Guatemala)', 'locale' => 'es_gt', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-hn' => array('language' => 'Spanish (Honduras)', 'locale' => 'es_hn', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-mx' => array('language' => 'Spanish (Mexican)', 'locale' => 'es_mx', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-ni' => array('language' => 'Spanish (Nicaragua)', 'locale' => 'es_ni', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-pa' => array('language' => 'Spanish (Panama)', 'locale' => 'es_pa', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-pe' => array('language' => 'Spanish (Peru)', 'locale' => 'es_pe', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-pr' => array('language' => 'Spanish (Puerto Rico)', 'locale' => 'es_pr', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-py' => array('language' => 'Spanish (Paraguay)', 'locale' => 'es_py', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-sv' => array('language' => 'Spanish (El Salvador)', 'locale' => 'es_sv', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-uy' => array('language' => 'Spanish (Uruguay)', 'locale' => 'es_uy', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-ve' => array('language' => 'Spanish (Venezuela)', 'locale' => 'es_ve', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'et' => array('language' => 'Estonian', 'locale' => 'est', 'localeFallback' => 'est', 'charset' => 'utf-8', 'direction' => 'ltr'), 'eu' => array('language' => 'Basque', 'locale' => 'eus', 'localeFallback' => 'eus', 'charset' => 'utf-8', 'direction' => 'ltr'), 'fa' => array('language' => 'Farsi', 'locale' => 'fas', 'localeFallback' => 'fas', 'charset' => 'utf-8', 'direction' => 'rtl'), 'fi' => array('language' => 'Finnish', 'locale' => 'fin', 'localeFallback' => 'fin', 'charset' => 'utf-8', 'direction' => 'ltr'), 'fo' => array('language' => 'Faeroese', 'locale' => 'fao', 'localeFallback' => 'fao', 'charset' => 'utf-8', 'direction' => 'ltr'), 'fr' => array('language' => 'French (Standard)', 'locale' => 'fra', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'), 'fr-be' => array('language' => 'French (Belgium)', 'locale' => 'fr_be', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'), 'fr-ca' => array('language' => 'French (Canadian)', 'locale' => 'fr_ca', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'), 'fr-ch' => array('language' => 'French (Swiss)', 'locale' => 'fr_ch', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'), 'fr-fr' => array('language' => 'French (France)', 'locale' => 'fr_fr', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'), 'fr-lu' => array('language' => 'French (Luxembourg)', 'locale' => 'fr_lu', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ga' => array('language' => 'Irish', 'locale' => 'gle', 'localeFallback' => 'gle', 'charset' => 'utf-8', 'direction' => 'ltr'), 'gd' => array('language' => 'Gaelic (Scots)', 'locale' => 'gla', 'localeFallback' => 'gla', 'charset' => 'utf-8', 'direction' => 'ltr'), 'gd-ie' => array('language' => 'Gaelic (Irish)', 'locale' => 'gd_ie', 'localeFallback' => 'gla', 'charset' => 'utf-8', 'direction' => 'ltr'), 'gl' => array('language' => 'Galician', 'locale' => 'glg', 'localeFallback' => 'glg', 'charset' => 'utf-8', 'direction' => 'ltr'), 'he' => array('language' => 'Hebrew', 'locale' => 'heb', 'localeFallback' => 'heb', 'charset' => 'utf-8', 'direction' => 'rtl'), 'hi' => array('language' => 'Hindi', 'locale' => 'hin', 'localeFallback' => 'hin', 'charset' => 'utf-8', 'direction' => 'ltr'), 'hr' => array('language' => 'Croatian', 'locale' => 'hrv', 'localeFallback' => 'hrv', 'charset' => 'utf-8', 'direction' => 'ltr'), 'hu' => array('language' => 'Hungarian', 'locale' => 'hun', 'localeFallback' => 'hun', 'charset' => 'utf-8', 'direction' => 'ltr'), 'hy' => array('language' => 'Armenian - Armenia', 'locale' => 'hye', 'localeFallback' => 'hye', 'charset' => 'utf-8', 'direction' => 'ltr'), 'id' => array('language' => 'Indonesian', 'locale' => 'ind', 'localeFallback' => 'ind', 'charset' => 'utf-8', 'direction' => 'ltr'), 'is' => array('language' => 'Icelandic', 'locale' => 'isl', 'localeFallback' => 'isl', 'charset' => 'utf-8', 'direction' => 'ltr'), 'it' => array('language' => 'Italian', 'locale' => 'ita', 'localeFallback' => 'ita', 'charset' => 'utf-8', 'direction' => 'ltr'), 'it-ch' => array('language' => 'Italian (Swiss) ', 'locale' => 'it_ch', 'localeFallback' => 'ita', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ja' => array('language' => 'Japanese', 'locale' => 'jpn', 'localeFallback' => 'jpn', 'charset' => 'utf-8', 'direction' => 'ltr'), 'kk' => array('language' => 'Kazakh', 'locale' => 'kaz', 'localeFallback' => 'kaz', 'charset' => 'utf-8', 'direction' => 'ltr'), 'kl' => array('language' => 'Kalaallisut (Greenlandic)', 'locale' => 'kal', 'localeFallback' => 'kal', 'charset' => 'kl', 'direction' => 'ltr'), 'ko' => array('language' => 'Korean', 'locale' => 'kor', 'localeFallback' => 'kor', 'charset' => 'kr', 'direction' => 'ltr'), 'ko-kp' => array('language' => 'Korea (North)', 'locale' => 'ko_kp', 'localeFallback' => 'kor', 'charset' => 'kr', 'direction' => 'ltr'), 'ko-kr' => array('language' => 'Korea (South)', 'locale' => 'ko_kr', 'localeFallback' => 'kor', 'charset' => 'kr', 'direction' => 'ltr'), 'koi8-r' => array('language' => 'Russian', 'locale' => 'koi8_r', 'localeFallback' => 'rus', 'charset' => 'koi8-r', 'direction' => 'ltr'), 'li' => array('language' => 'Limburgish', 'locale' => 'lim', 'localeFallback' => 'nld', 'charset' => 'utf-8', 'direction' => 'ltr'), 'lt' => array('language' => 'Lithuanian', 'locale' => 'lit', 'localeFallback' => 'lit', 'charset' => 'utf-8', 'direction' => 'ltr'), 'lv' => array('language' => 'Latvian', 'locale' => 'lav', 'localeFallback' => 'lav', 'charset' => 'utf-8', 'direction' => 'ltr'), 'mk' => array('language' => 'FYRO Macedonian', 'locale' => 'mkd', 'localeFallback' => 'mkd', 'charset' => 'utf-8', 'direction' => 'ltr'), 'mk-mk' => array('language' => 'Macedonian', 'locale' => 'mk_mk', 'localeFallback' => 'mkd', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ms' => array('language' => 'Malaysian', 'locale' => 'msa', 'localeFallback' => 'msa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'mt' => array('language' => 'Maltese', 'locale' => 'mlt', 'localeFallback' => 'mlt', 'charset' => 'utf-8', 'direction' => 'ltr'), 'nb' => array('language' => 'Norwegian Bokmal', 'locale' => 'nob', 'localeFallback' => 'nor', 'charset' => 'utf-8', 'direction' => 'ltr'), 'nl' => array('language' => 'Dutch (Standard)', 'locale' => 'nld', 'localeFallback' => 'nld', 'charset' => 'utf-8', 'direction' => 'ltr'), 'nl-be' => array('language' => 'Dutch (Belgium)', 'locale' => 'nl_be', 'localeFallback' => 'nld', 'charset' => 'utf-8', 'direction' => 'ltr'), 'nn' => array('language' => 'Norwegian Nynorsk', 'locale' => 'nno', 'localeFallback' => 'nor', 'charset' => 'utf-8', 'direction' => 'ltr'), 'no' => array('language' => 'Norwegian', 'locale' => 'nor', 'localeFallback' => 'nor', 'charset' => 'utf-8', 'direction' => 'ltr'), 'pl' => array('language' => 'Polish', 'locale' => 'pol', 'localeFallback' => 'pol', 'charset' => 'utf-8', 'direction' => 'ltr'), 'pt' => array('language' => 'Portuguese (Portugal)', 'locale' => 'por', 'localeFallback' => 'por', 'charset' => 'utf-8', 'direction' => 'ltr'), 'pt-br' => array('language' => 'Portuguese (Brazil)', 'locale' => 'pt_br', 'localeFallback' => 'por', 'charset' => 'utf-8', 'direction' => 'ltr'), 'rm' => array('language' => 'Rhaeto-Romanic', 'locale' => 'roh', 'localeFallback' => 'roh', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ro' => array('language' => 'Romanian', 'locale' => 'ron', 'localeFallback' => 'ron', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ro-mo' => array('language' => 'Romanian (Moldavia)', 'locale' => 'ro_mo', 'localeFallback' => 'ron', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ru' => array('language' => 'Russian', 'locale' => 'rus', 'localeFallback' => 'rus', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ru-mo' => array('language' => 'Russian (Moldavia)', 'locale' => 'ru_mo', 'localeFallback' => 'rus', 'charset' => 'utf-8', 'direction' => 'ltr'), 'sb' => array('language' => 'Sorbian', 'locale' => 'wen', 'localeFallback' => 'wen', 'charset' => 'utf-8', 'direction' => 'ltr'), 'sk' => array('language' => 'Slovak', 'locale' => 'slk', 'localeFallback' => 'slk', 'charset' => 'utf-8', 'direction' => 'ltr'), 'sl' => array('language' => 'Slovenian', 'locale' => 'slv', 'localeFallback' => 'slv', 'charset' => 'utf-8', 'direction' => 'ltr'), 'sq' => array('language' => 'Albanian', 'locale' => 'sqi', 'localeFallback' => 'sqi', 'charset' => 'utf-8', 'direction' => 'ltr'), 'sr' => array('language' => 'Serbian', 'locale' => 'srp', 'localeFallback' => 'srp', 'charset' => 'utf-8', 'direction' => 'ltr'), 'sv' => array('language' => 'Swedish', 'locale' => 'swe', 'localeFallback' => 'swe', 'charset' => 'utf-8', 'direction' => 'ltr'), 'sv-fi' => array('language' => 'Swedish (Finland)', 'locale' => 'sv_fi', 'localeFallback' => 'swe', 'charset' => 'utf-8', 'direction' => 'ltr'), 'se' => array('language' => 'Sami', 'locale' => 'sme', 'localeFallback' => 'sme', 'charset' => 'utf-8', 'direction' => 'ltr'), 'th' => array('language' => 'Thai', 'locale' => 'tha', 'localeFallback' => 'tha', 'charset' => 'utf-8', 'direction' => 'ltr'), 'tn' => array('language' => 'Tswana', 'locale' => 'tsn', 'localeFallback' => 'tsn', 'charset' => 'utf-8', 'direction' => 'ltr'), 'tr' => array('language' => 'Turkish', 'locale' => 'tur', 'localeFallback' => 'tur', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ts' => array('language' => 'Tsonga', 'locale' => 'tso', 'localeFallback' => 'tso', 'charset' => 'utf-8', 'direction' => 'ltr'), 'uk' => array('language' => 'Ukrainian', 'locale' => 'ukr', 'localeFallback' => 'ukr', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ur' => array('language' => 'Urdu', 'locale' => 'urd', 'localeFallback' => 'urd', 'charset' => 'utf-8', 'direction' => 'rtl'), 've' => array('language' => 'Venda', 'locale' => 'ven', 'localeFallback' => 'ven', 'charset' => 'utf-8', 'direction' => 'ltr'), 'vi' => array('language' => 'Vietnamese', 'locale' => 'vie', 'localeFallback' => 'vie', 'charset' => 'utf-8', 'direction' => 'ltr'), 'cy' => array('language' => 'Welsh', 'locale' => 'cym', 'localeFallback' => 'cym', 'charset' => 'utf-8', 'direction' => 'ltr'), 'xh' => array('language' => 'Xhosa', 'locale' => 'xho', 'localeFallback' => 'xho', 'charset' => 'utf-8', 'direction' => 'ltr'), 'yi' => array('language' => 'Yiddish', 'locale' => 'yid', 'localeFallback' => 'yid', 'charset' => 'utf-8', 'direction' => 'ltr'), 'zh' => array('language' => 'Chinese', 'locale' => 'zho', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr'), 'zh-cn' => array('language' => 'Chinese (PRC)', 'locale' => 'zh_cn', 'localeFallback' => 'zho', 'charset' => 'GB2312', 'direction' => 'ltr'), 'zh-hk' => array('language' => 'Chinese (Hong Kong)', 'locale' => 'zh_hk', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr'), 'zh-sg' => array('language' => 'Chinese (Singapore)', 'locale' => 'zh_sg', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr'), 'zh-tw' => array('language' => 'Chinese (Taiwan)', 'locale' => 'zh_tw', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr'), 'zu' => array('language' => 'Zulu', 'locale' => 'zul', 'localeFallback' => 'zul', 'charset' => 'utf-8', 'direction' => 'ltr') ); /** * Class constructor */ public function __construct() { if (defined('DEFAULT_LANGUAGE')) { $this->default = DEFAULT_LANGUAGE; } $default = Configure::read('Config.language'); if ($default) { $this->default = $default; } } /** * Gets the settings for $language. * If $language is null it attempt to get settings from L10n::_autoLanguage(); if this fails * the method will get the settings from L10n::_setLanguage(); * * @param string $language Language (if null will use DEFAULT_LANGUAGE if defined) * @return mixed */ public function get($language = null) { if ($language !== null) { return $this->_setLanguage($language); } if (!$this->_autoLanguage()) { $this->_setLanguage(); } return $this->lang; } /** * Sets the class vars to correct values for $language. * If $language is null it will use the L10n::$default if defined * * @param string $language Language (if null will use L10n::$default if defined) * @return mixed */ protected function _setLanguage($language = null) { $catalog = false; if ($language !== null) { $catalog = $this->catalog($language); } if (!$catalog && $this->default) { $language = $this->default; $catalog = $this->catalog($language); } if ($catalog) { $this->language = $catalog['language']; $this->languagePath = array_unique(array( $catalog['locale'], $catalog['localeFallback'] )); $this->lang = $language; $this->locale = $catalog['locale']; $this->charset = $catalog['charset']; $this->direction = $catalog['direction']; } elseif ($language) { $this->lang = $language; $this->languagePath = array($language); } if ($this->default && $language !== $this->default) { $catalog = $this->catalog($this->default); $fallback = $catalog['localeFallback']; if (!in_array($fallback, $this->languagePath)) { $this->languagePath[] = $fallback; } } if (Configure::read('Config.language') === null) { Configure::write('Config.language', $this->lang); } if ($language) { return $language; } } /** * Attempts to find the locale settings based on the HTTP_ACCEPT_LANGUAGE variable * * @return bool Success */ protected function _autoLanguage() { $_detectableLanguages = CakeRequest::acceptLanguage(); foreach ($_detectableLanguages as $langKey) { if (isset($this->_l10nCatalog[$langKey])) { $this->_setLanguage($langKey); return true; } if (strpos($langKey, '-') !== false) { $langKey = substr($langKey, 0, 2); if (isset($this->_l10nCatalog[$langKey])) { $this->_setLanguage($langKey); return true; } } } return false; } /** * Attempts to find locale for language, or language for locale * * @param string|array $mixed 2/3 char string (language/locale), array of those strings, or null * @return string|array|bool string language/locale, array of those values, whole map as an array, * or false when language/locale doesn't exist */ public function map($mixed = null) { if (is_array($mixed)) { $result = array(); foreach ($mixed as $_mixed) { if ($_result = $this->map($_mixed)) { $result[$_mixed] = $_result; } } return $result; } if (is_string($mixed)) { if (strlen($mixed) === 2 && in_array($mixed, $this->_l10nMap)) { return array_search($mixed, $this->_l10nMap); } if (isset($this->_l10nMap[$mixed])) { return $this->_l10nMap[$mixed]; } return false; } return $this->_l10nMap; } /** * Attempts to find catalog record for requested language * * @param string|array $language string requested language, array of requested languages, or null for whole catalog * @return array|bool array catalog record for requested language, array of catalog records, whole catalog, * or false when language doesn't exist */ public function catalog($language = null) { if (is_array($language)) { $result = array(); foreach ($language as $_language) { if ($_result = $this->catalog($_language)) { $result[$_language] = $_result; } } return $result; } if (is_string($language)) { if (isset($this->_l10nCatalog[$language])) { return $this->_l10nCatalog[$language]; } if (isset($this->_l10nMap[$language]) && isset($this->_l10nCatalog[$this->_l10nMap[$language]])) { return $this->_l10nCatalog[$this->_l10nMap[$language]]; } return false; } return $this->_l10nCatalog; } } cakephp-2.8.0/lib/Cake/I18n/Multibyte.php000066400000000000000000000621561265552240500177730ustar00rootroot00000000000000 1) { $matches[$needle[0]] = $matches[$needle[0]] - 1; } elseif ($i === $needleCount) { $found = true; } } if (!$found && isset($haystack[$position])) { $parts[] = $haystack[$position]; unset($haystack[$position]); } $position++; } if ($found && $part && !empty($parts)) { return Multibyte::ascii($parts); } elseif ($found && !empty($haystack)) { return Multibyte::ascii($haystack); } return false; } /** * Finds the last occurrence of a character in a string within another, case insensitive. * * @param string $haystack The string from which to get the last occurrence of $needle. * @param string $needle The string to find in $haystack. * @param bool $part Determines which portion of $haystack this function returns. * If set to true, it returns all of $haystack from the beginning to the last occurrence of $needle. * If set to false, it returns all of $haystack from the last occurrence of $needle to the end, * Default value is false. * @return string|bool The portion of $haystack. or false if $needle is not found. */ public static function strrichr($haystack, $needle, $part = false) { $check = Multibyte::strtoupper($haystack); $check = Multibyte::utf8($check); $found = false; $haystack = Multibyte::utf8($haystack); $haystackCount = count($haystack); $matches = array_count_values($check); $needle = Multibyte::strtoupper($needle); $needle = Multibyte::utf8($needle); $needleCount = count($needle); $parts = array(); $position = 0; while (($found === false) && ($position < $haystackCount)) { if (isset($needle[0]) && $needle[0] === $check[$position]) { for ($i = 1; $i < $needleCount; $i++) { if ($needle[$i] !== $check[$position + $i]) { if ($needle[$i] === $check[($position + $i) - 1]) { $found = true; } unset($parts[$position - 1]); $haystack = array_merge(array($haystack[$position]), $haystack); break; } } if (isset($matches[$needle[0]]) && $matches[$needle[0]] > 1) { $matches[$needle[0]] = $matches[$needle[0]] - 1; } elseif ($i === $needleCount) { $found = true; } } if (!$found && isset($haystack[$position])) { $parts[] = $haystack[$position]; unset($haystack[$position]); } $position++; } if ($found && $part && !empty($parts)) { return Multibyte::ascii($parts); } elseif ($found && !empty($haystack)) { return Multibyte::ascii($haystack); } return false; } /** * Finds position of last occurrence of a string within another, case insensitive * * @param string $haystack The string from which to get the position of the last occurrence of $needle. * @param string $needle The string to find in $haystack. * @param int $offset The position in $haystack to start searching. * @return int|bool The numeric position of the last occurrence of $needle in the $haystack string, * or false if $needle is not found. */ public static function strripos($haystack, $needle, $offset = 0) { if (Multibyte::checkMultibyte($haystack)) { $found = false; $haystack = Multibyte::strtoupper($haystack); $haystack = Multibyte::utf8($haystack); $haystackCount = count($haystack); $matches = array_count_values($haystack); $needle = Multibyte::strtoupper($needle); $needle = Multibyte::utf8($needle); $needleCount = count($needle); $position = $offset; while (($found === false) && ($position < $haystackCount)) { if (isset($needle[0]) && $needle[0] === $haystack[$position]) { for ($i = 1; $i < $needleCount; $i++) { if ($needle[$i] !== $haystack[$position + $i]) { if ($needle[$i] === $haystack[($position + $i) - 1]) { $position--; $found = true; continue; } } } if (!$offset && isset($matches[$needle[0]]) && $matches[$needle[0]] > 1) { $matches[$needle[0]] = $matches[$needle[0]] - 1; } elseif ($i === $needleCount) { $found = true; $position--; } } $position++; } return ($found) ? $position : false; } return strripos($haystack, $needle, $offset); } /** * Find position of last occurrence of a string in a string. * * @param string $haystack The string being checked, for the last occurrence of $needle. * @param string $needle The string to find in $haystack. * @param int $offset May be specified to begin searching an arbitrary number of characters into the string. * Negative values will stop searching at an arbitrary point prior to the end of the string. * @return int|bool The numeric position of the last occurrence of $needle in the $haystack string. * If $needle is not found, it returns false. */ public static function strrpos($haystack, $needle, $offset = 0) { if (Multibyte::checkMultibyte($haystack)) { $found = false; $haystack = Multibyte::utf8($haystack); $haystackCount = count($haystack); $matches = array_count_values($haystack); $needle = Multibyte::utf8($needle); $needleCount = count($needle); $position = $offset; while (($found === false) && ($position < $haystackCount)) { if (isset($needle[0]) && $needle[0] === $haystack[$position]) { for ($i = 1; $i < $needleCount; $i++) { if ($needle[$i] !== $haystack[$position + $i]) { if ($needle[$i] === $haystack[($position + $i) - 1]) { $position--; $found = true; continue; } } } if (!$offset && isset($matches[$needle[0]]) && $matches[$needle[0]] > 1) { $matches[$needle[0]] = $matches[$needle[0]] - 1; } elseif ($i === $needleCount) { $found = true; $position--; } } $position++; } return ($found) ? $position : false; } return strrpos($haystack, $needle, $offset); } /** * Finds first occurrence of a string within another * * @param string $haystack The string from which to get the first occurrence of $needle. * @param string $needle The string to find in $haystack * @param bool $part Determines which portion of $haystack this function returns. * If set to true, it returns all of $haystack from the beginning to the first occurrence of $needle. * If set to false, it returns all of $haystack from the first occurrence of $needle to the end, * Default value is FALSE. * @return string|bool The portion of $haystack, or true if $needle is not found. */ public static function strstr($haystack, $needle, $part = false) { $php = (PHP_VERSION < 5.3); if (($php && $part) || Multibyte::checkMultibyte($haystack)) { $check = Multibyte::utf8($haystack); $found = false; $haystack = Multibyte::utf8($haystack); $haystackCount = count($haystack); $needle = Multibyte::utf8($needle); $needleCount = count($needle); $parts = array(); $position = 0; while (($found === false) && ($position < $haystackCount)) { if (isset($needle[0]) && $needle[0] === $check[$position]) { for ($i = 1; $i < $needleCount; $i++) { if ($needle[$i] !== $check[$position + $i]) { break; } } if ($i === $needleCount) { $found = true; } } if (!$found) { $parts[] = $haystack[$position]; unset($haystack[$position]); } $position++; } if ($found && $part && !empty($parts)) { return Multibyte::ascii($parts); } elseif ($found && !empty($haystack)) { return Multibyte::ascii($haystack); } return false; } if (!$php) { return strstr($haystack, $needle, $part); } return strstr($haystack, $needle); } /** * Make a string lowercase * * @param string $string The string being lowercased. * @return string with all alphabetic characters converted to lowercase. */ public static function strtolower($string) { $utf8Map = Multibyte::utf8($string); $length = count($utf8Map); $lowerCase = array(); for ($i = 0; $i < $length; $i++) { $char = $utf8Map[$i]; if ($char < 128) { $str = strtolower(chr($char)); $strlen = strlen($str); for ($ii = 0; $ii < $strlen; $ii++) { $lower = ord(substr($str, $ii, 1)); } $lowerCase[] = $lower; $matched = true; } else { $matched = false; $keys = static::_find($char, 'upper'); if (!empty($keys)) { foreach ($keys as $key => $value) { if ($keys[$key]['upper'] == $char && count($keys[$key]['lower'][0]) === 1) { $lowerCase[] = $keys[$key]['lower'][0]; $matched = true; break 1; } } } } if ($matched === false) { $lowerCase[] = $char; } } return Multibyte::ascii($lowerCase); } /** * Make a string uppercase * * @param string $string The string being uppercased. * @return string with all alphabetic characters converted to uppercase. */ public static function strtoupper($string) { $utf8Map = Multibyte::utf8($string); $length = count($utf8Map); $replaced = array(); $upperCase = array(); for ($i = 0; $i < $length; $i++) { $char = $utf8Map[$i]; if ($char < 128) { $str = strtoupper(chr($char)); $strlen = strlen($str); for ($ii = 0; $ii < $strlen; $ii++) { $upper = ord(substr($str, $ii, 1)); } $upperCase[] = $upper; $matched = true; } else { $matched = false; $keys = static::_find($char); $keyCount = count($keys); if (!empty($keys)) { foreach ($keys as $key => $value) { $matched = false; $replace = 0; if ($length > 1 && count($keys[$key]['lower']) > 1) { $j = 0; for ($ii = 0, $count = count($keys[$key]['lower']); $ii < $count; $ii++) { $nextChar = $utf8Map[$i + $ii]; if (isset($nextChar) && ($nextChar == $keys[$key]['lower'][$j + $ii])) { $replace++; } } if ($replace == $count) { $upperCase[] = $keys[$key]['upper']; $replaced = array_merge($replaced, array_values($keys[$key]['lower'])); $matched = true; break 1; } } elseif ($length > 1 && $keyCount > 1) { $j = 0; for ($ii = 1; $ii < $keyCount; $ii++) { $nextChar = $utf8Map[$i + $ii - 1]; if (in_array($nextChar, $keys[$ii]['lower'])) { for ($jj = 0, $count = count($keys[$ii]['lower']); $jj < $count; $jj++) { $nextChar = $utf8Map[$i + $jj]; if (isset($nextChar) && ($nextChar == $keys[$ii]['lower'][$j + $jj])) { $replace++; } } if ($replace == $count) { $upperCase[] = $keys[$ii]['upper']; $replaced = array_merge($replaced, array_values($keys[$ii]['lower'])); $matched = true; break 2; } } } } if ($keys[$key]['lower'][0] == $char) { $upperCase[] = $keys[$key]['upper']; $matched = true; break 1; } } } } if ($matched === false && !in_array($char, $replaced, true)) { $upperCase[] = $char; } } return Multibyte::ascii($upperCase); } /** * Count the number of substring occurrences * * @param string $haystack The string being checked. * @param string $needle The string being found. * @return int The number of times the $needle substring occurs in the $haystack string. */ public static function substrCount($haystack, $needle) { $count = 0; $haystack = Multibyte::utf8($haystack); $haystackCount = count($haystack); $matches = array_count_values($haystack); $needle = Multibyte::utf8($needle); $needleCount = count($needle); if ($needleCount === 1 && isset($matches[$needle[0]])) { return $matches[$needle[0]]; } for ($i = 0; $i < $haystackCount; $i++) { if (isset($needle[0]) && $needle[0] === $haystack[$i]) { for ($ii = 1; $ii < $needleCount; $ii++) { if ($needle[$ii] === $haystack[$i + 1]) { if ((isset($needle[$ii + 1]) && $haystack[$i + 2]) && $needle[$ii + 1] !== $haystack[$i + 2]) { $count--; } else { $count++; } } } } } return $count; } /** * Get part of string * * @param string $string The string being checked. * @param int $start The first position used in $string. * @param int $length The maximum length of the returned string. * @return string The portion of $string specified by the $string and $length parameters. */ public static function substr($string, $start, $length = null) { if ($start === 0 && $length === null) { return $string; } $string = Multibyte::utf8($string); for ($i = 1; $i <= $start; $i++) { unset($string[$i - 1]); } if ($length === null || count($string) < $length) { return Multibyte::ascii($string); } $string = array_values($string); $value = array(); for ($i = 0; $i < $length; $i++) { $value[] = $string[$i]; } return Multibyte::ascii($value); } /** * Prepare a string for mail transport, using the provided encoding * * @param string $string value to encode * @param string $charset charset to use for encoding. defaults to UTF-8 * @param string $newline Newline string. * @return string */ public static function mimeEncode($string, $charset = null, $newline = "\r\n") { if (!Multibyte::checkMultibyte($string) && strlen($string) < 75) { return $string; } if (empty($charset)) { $charset = Configure::read('App.encoding'); } $charset = strtoupper($charset); $start = '=?' . $charset . '?B?'; $end = '?='; $spacer = $end . $newline . ' ' . $start; $length = 75 - strlen($start) - strlen($end); $length = $length - ($length % 4); if ($charset === 'UTF-8') { $parts = array(); $maxchars = floor(($length * 3) / 4); $stringLength = strlen($string); while ($stringLength > $maxchars) { $i = (int)$maxchars; $test = ord($string[$i]); while ($test >= 128 && $test <= 191) { $i--; $test = ord($string[$i]); } $parts[] = base64_encode(substr($string, 0, $i)); $string = substr($string, $i); $stringLength = strlen($string); } $parts[] = base64_encode($string); $string = implode($spacer, $parts); } else { $string = chunk_split(base64_encode($string), $length, $spacer); $string = preg_replace('/' . preg_quote($spacer) . '$/', '', $string); } return $start . $string . $end; } /** * Return the Code points range for Unicode characters * * @param int $decimal Decimal value. * @return string */ protected static function _codepoint($decimal) { if ($decimal > 128 && $decimal < 256) { $return = '0080_00ff'; // Latin-1 Supplement } elseif ($decimal < 384) { $return = '0100_017f'; // Latin Extended-A } elseif ($decimal < 592) { $return = '0180_024F'; // Latin Extended-B } elseif ($decimal < 688) { $return = '0250_02af'; // IPA Extensions } elseif ($decimal >= 880 && $decimal < 1024) { $return = '0370_03ff'; // Greek and Coptic } elseif ($decimal < 1280) { $return = '0400_04ff'; // Cyrillic } elseif ($decimal < 1328) { $return = '0500_052f'; // Cyrillic Supplement } elseif ($decimal < 1424) { $return = '0530_058f'; // Armenian } elseif ($decimal >= 7680 && $decimal < 7936) { $return = '1e00_1eff'; // Latin Extended Additional } elseif ($decimal < 8192) { $return = '1f00_1fff'; // Greek Extended } elseif ($decimal >= 8448 && $decimal < 8528) { $return = '2100_214f'; // Letterlike Symbols } elseif ($decimal < 8592) { $return = '2150_218f'; // Number Forms } elseif ($decimal >= 9312 && $decimal < 9472) { $return = '2460_24ff'; // Enclosed Alphanumerics } elseif ($decimal >= 11264 && $decimal < 11360) { $return = '2c00_2c5f'; // Glagolitic } elseif ($decimal < 11392) { $return = '2c60_2c7f'; // Latin Extended-C } elseif ($decimal < 11520) { $return = '2c80_2cff'; // Coptic } elseif ($decimal >= 65280 && $decimal < 65520) { $return = 'ff00_ffef'; // Halfwidth and Fullwidth Forms } else { $return = false; } static::$_codeRange[$decimal] = $return; return $return; } /** * Find the related code folding values for $char * * @param int $char decimal value of character * @param string $type Type 'lower' or 'upper'. Defaults to 'lower'. * @return array */ protected static function _find($char, $type = 'lower') { $found = array(); if (!isset(static::$_codeRange[$char])) { $range = static::_codepoint($char); if ($range === false) { return array(); } if (!Configure::configured('_cake_core_')) { App::uses('PhpReader', 'Configure'); Configure::config('_cake_core_', new PhpReader(CAKE . 'Config' . DS)); } Configure::load('unicode' . DS . 'casefolding' . DS . $range, '_cake_core_'); static::$_caseFold[$range] = Configure::read($range); Configure::delete($range); } if (!static::$_codeRange[$char]) { return array(); } static::$_table = static::$_codeRange[$char]; $count = count(static::$_caseFold[static::$_table]); for ($i = 0; $i < $count; $i++) { if ($type === 'lower' && static::$_caseFold[static::$_table][$i][$type][0] === $char) { $found[] = static::$_caseFold[static::$_table][$i]; } elseif ($type === 'upper' && static::$_caseFold[static::$_table][$i][$type] === $char) { $found[] = static::$_caseFold[static::$_table][$i]; } } return $found; } /** * Check the $string for multibyte characters * * @param string $string Value to test. * @return bool */ public static function checkMultibyte($string) { $length = strlen($string); for ($i = 0; $i < $length; $i++) { $value = ord(($string[$i])); if ($value > 128) { return true; } } return false; } } cakephp-2.8.0/lib/Cake/LICENSE.txt000066400000000000000000000024071265552240500164010ustar00rootroot00000000000000The MIT License CakePHP(tm) : The Rapid Development PHP Framework (http://cakephp.org) Copyright (c) 2005-2015, Cake Software Foundation, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Cake Software Foundation, Inc. 1785 E. Sahara Avenue, Suite 490-204 Las Vegas, Nevada 89104, United States of America.cakephp-2.8.0/lib/Cake/Log/000077500000000000000000000000001265552240500152745ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Log/CakeLog.php000066400000000000000000000365641265552240500173300ustar00rootroot00000000000000 'File')); * ``` * * See the documentation on CakeLog::config() for more detail. * * ### Writing to the log * * You write to the logs using CakeLog::write(). See its documentation for more * information. * * ### Logging Levels * * By default CakeLog supports all the log levels defined in * RFC 5424. When logging messages you can either use the named methods, * or the correct constants with `write()`: * * ``` * CakeLog::error('Something horrible happened'); * CakeLog::write(LOG_ERR, 'Something horrible happened'); * ``` * * If you require custom logging levels, you can use CakeLog::levels() to * append additional logging levels. * * ### Logging scopes * * When logging messages and configuring log adapters, you can specify * 'scopes' that the logger will handle. You can think of scopes as subsystems * in your application that may require different logging setups. For * example in an e-commerce application you may want to handle logged errors * in the cart and ordering subsystems differently than the rest of the * application. By using scopes you can control logging for each part * of your application and still keep standard log levels. * * See CakeLog::config() and CakeLog::write() for more information * on scopes * * @package Cake.Log * @link http://book.cakephp.org/2.0/en/core-libraries/logging.html#logging */ class CakeLog { /** * LogEngineCollection class * * @var LogEngineCollection */ protected static $_Collection; /** * Default log levels as detailed in RFC 5424 * http://tools.ietf.org/html/rfc5424 * * @var array */ protected static $_defaultLevels = array( 'emergency' => LOG_EMERG, 'alert' => LOG_ALERT, 'critical' => LOG_CRIT, 'error' => LOG_ERR, 'warning' => LOG_WARNING, 'notice' => LOG_NOTICE, 'info' => LOG_INFO, 'debug' => LOG_DEBUG, ); /** * Active log levels for this instance. * * @var array */ protected static $_levels; /** * Mapped log levels * * @var array */ protected static $_levelMap; /** * initialize ObjectCollection * * @return void */ protected static function _init() { static::$_levels = static::defaultLevels(); static::$_Collection = new LogEngineCollection(); } /** * Configure and add a new logging stream to CakeLog * You can use add loggers from app/Log/Engine use app.loggername, or any * plugin/Log/Engine using plugin.loggername. * * ### Usage: * * ``` * CakeLog::config('second_file', array( * 'engine' => 'File', * 'path' => '/var/logs/my_app/' * )); * ``` * * Will configure a FileLog instance to use the specified path. * All options that are not `engine` are passed onto the logging adapter, * and handled there. Any class can be configured as a logging * adapter as long as it implements the methods in CakeLogInterface. * * ### Logging levels * * When configuring loggers, you can set which levels a logger will handle. * This allows you to disable debug messages in production for example: * * ``` * CakeLog::config('default', array( * 'engine' => 'File', * 'path' => LOGS, * 'levels' => array('error', 'critical', 'alert', 'emergency') * )); * ``` * * The above logger would only log error messages or higher. Any * other log messages would be discarded. * * ### Logging scopes * * When configuring loggers you can define the active scopes the logger * is for. If defined only the listed scopes will be handled by the * logger. If you don't define any scopes an adapter will catch * all scopes that match the handled levels. * * ``` * CakeLog::config('payments', array( * 'engine' => 'File', * 'types' => array('info', 'error', 'warning'), * 'scopes' => array('payment', 'order') * )); * ``` * * The above logger will only capture log entries made in the * `payment` and `order` scopes. All other scopes including the * undefined scope will be ignored. Its important to remember that * when using scopes you must also define the `types` of log messages * that a logger will handle. Failing to do so will result in the logger * catching all log messages even if the scope is incorrect. * * @param string $key The keyname for this logger, used to remove the * logger later. * @param array $config Array of configuration information for the logger * @return bool success of configuration. * @throws CakeLogException * @link http://book.cakephp.org/2.0/en/core-libraries/logging.html#creating-and-configuring-log-streams */ public static function config($key, $config) { if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/', $key)) { throw new CakeLogException(__d('cake_dev', 'Invalid key name')); } if (empty($config['engine'])) { throw new CakeLogException(__d('cake_dev', 'Missing logger class name')); } if (empty(static::$_Collection)) { static::_init(); } static::$_Collection->load($key, $config); return true; } /** * Returns the keynames of the currently active streams * * @return array Array of configured log streams. */ public static function configured() { if (empty(static::$_Collection)) { static::_init(); } return static::$_Collection->loaded(); } /** * Gets/sets log levels * * Call this method without arguments, eg: `CakeLog::levels()` to obtain current * level configuration. * * To append additional level 'user0' and 'user1' to to default log levels: * * ``` * CakeLog::levels(array('user0, 'user1')); * // or * CakeLog::levels(array('user0, 'user1'), true); * ``` * * will result in: * * ``` * array( * 0 => 'emergency', * 1 => 'alert', * ... * 8 => 'user0', * 9 => 'user1', * ); * ``` * * To set/replace existing configuration, pass an array with the second argument * set to false. * * ``` * CakeLog::levels(array('user0, 'user1'), false); * ``` * * will result in: * * ``` * array( * 0 => 'user0', * 1 => 'user1', * ); * ``` * * @param array $levels array * @param bool $append true to append, false to replace * @return array Active log levels */ public static function levels($levels = array(), $append = true) { if (empty(static::$_Collection)) { static::_init(); } if (empty($levels)) { return static::$_levels; } $levels = array_values($levels); if ($append) { static::$_levels = array_merge(static::$_levels, $levels); } else { static::$_levels = $levels; } static::$_levelMap = array_flip(static::$_levels); return static::$_levels; } /** * Reset log levels to the original value * * @return array Default log levels */ public static function defaultLevels() { static::$_levelMap = static::$_defaultLevels; static::$_levels = array_flip(static::$_levelMap); return static::$_levels; } /** * Removes a stream from the active streams. Once a stream has been removed * it will no longer have messages sent to it. * * @param string $streamName Key name of a configured stream to remove. * @return void */ public static function drop($streamName) { if (empty(static::$_Collection)) { static::_init(); } static::$_Collection->unload($streamName); } /** * Checks whether $streamName is enabled * * @param string $streamName to check * @return bool * @throws CakeLogException */ public static function enabled($streamName) { if (empty(static::$_Collection)) { static::_init(); } if (!isset(static::$_Collection->{$streamName})) { throw new CakeLogException(__d('cake_dev', 'Stream %s not found', $streamName)); } return static::$_Collection->enabled($streamName); } /** * Enable stream. Streams that were previously disabled * can be re-enabled with this method. * * @param string $streamName to enable * @return void * @throws CakeLogException */ public static function enable($streamName) { if (empty(static::$_Collection)) { static::_init(); } if (!isset(static::$_Collection->{$streamName})) { throw new CakeLogException(__d('cake_dev', 'Stream %s not found', $streamName)); } static::$_Collection->enable($streamName); } /** * Disable stream. Disabling a stream will * prevent that log stream from receiving any messages until * its re-enabled. * * @param string $streamName to disable * @return void * @throws CakeLogException */ public static function disable($streamName) { if (empty(static::$_Collection)) { static::_init(); } if (!isset(static::$_Collection->{$streamName})) { throw new CakeLogException(__d('cake_dev', 'Stream %s not found', $streamName)); } static::$_Collection->disable($streamName); } /** * Gets the logging engine from the active streams. * * @param string $streamName Key name of a configured stream to get. * @return mixed instance of BaseLog or false if not found * @see BaseLog */ public static function stream($streamName) { if (empty(static::$_Collection)) { static::_init(); } if (!empty(static::$_Collection->{$streamName})) { return static::$_Collection->{$streamName}; } return false; } /** * Writes the given message and type to all of the configured log adapters. * Configured adapters are passed both the $type and $message variables. $type * is one of the following strings/values. * * ### Types: * * - LOG_EMERG => 'emergency', * - LOG_ALERT => 'alert', * - LOG_CRIT => 'critical', * - `LOG_ERR` => 'error', * - `LOG_WARNING` => 'warning', * - `LOG_NOTICE` => 'notice', * - `LOG_INFO` => 'info', * - `LOG_DEBUG` => 'debug', * * ### Usage: * * Write a message to the 'warning' log: * * `CakeLog::write('warning', 'Stuff is broken here');` * * @param int|string $type Type of message being written. When value is an integer * or a string matching the recognized levels, then it will * be treated log levels. Otherwise it's treated as scope. * @param string $message Message content to log * @param string|array $scope The scope(s) a log message is being created in. * See CakeLog::config() for more information on logging scopes. * @return bool Success * @link http://book.cakephp.org/2.0/en/core-libraries/logging.html#writing-to-logs */ public static function write($type, $message, $scope = array()) { if (empty(static::$_Collection)) { static::_init(); } if (is_int($type) && isset(static::$_levels[$type])) { $type = static::$_levels[$type]; } if (is_string($type) && empty($scope) && !in_array($type, static::$_levels)) { $scope = $type; } $logged = false; foreach (static::$_Collection->enabled() as $streamName) { $logger = static::$_Collection->{$streamName}; $types = $scopes = $config = array(); if (method_exists($logger, 'config')) { $config = $logger->config(); } if (isset($config['types'])) { $types = $config['types']; } if (isset($config['scopes'])) { $scopes = $config['scopes']; } $inScope = (count(array_intersect((array)$scope, $scopes)) > 0); $correctLevel = in_array($type, $types); if ( // No config is a catch all (bc mode) (empty($types) && empty($scopes)) || // BC layer for mixing scope & level (in_array($type, $scopes)) || // no scopes, but has level (empty($scopes) && $correctLevel) || // exact scope + level ($correctLevel && $inScope) ) { $logger->write($type, $message); $logged = true; } } return $logged; } /** * Convenience method to log emergency messages * * @param string $message log message * @param string|array $scope The scope(s) a log message is being created in. * See CakeLog::config() for more information on logging scopes. * @return bool Success */ public static function emergency($message, $scope = array()) { return static::write(static::$_levelMap['emergency'], $message, $scope); } /** * Convenience method to log alert messages * * @param string $message log message * @param string|array $scope The scope(s) a log message is being created in. * See CakeLog::config() for more information on logging scopes. * @return bool Success */ public static function alert($message, $scope = array()) { return static::write(static::$_levelMap['alert'], $message, $scope); } /** * Convenience method to log critical messages * * @param string $message log message * @param string|array $scope The scope(s) a log message is being created in. * See CakeLog::config() for more information on logging scopes. * @return bool Success */ public static function critical($message, $scope = array()) { return static::write(static::$_levelMap['critical'], $message, $scope); } /** * Convenience method to log error messages * * @param string $message log message * @param string|array $scope The scope(s) a log message is being created in. * See CakeLog::config() for more information on logging scopes. * @return bool Success */ public static function error($message, $scope = array()) { return static::write(static::$_levelMap['error'], $message, $scope); } /** * Convenience method to log warning messages * * @param string $message log message * @param string|array $scope The scope(s) a log message is being created in. * See CakeLog::config() for more information on logging scopes. * @return bool Success */ public static function warning($message, $scope = array()) { return static::write(static::$_levelMap['warning'], $message, $scope); } /** * Convenience method to log notice messages * * @param string $message log message * @param string|array $scope The scope(s) a log message is being created in. * See CakeLog::config() for more information on logging scopes. * @return bool Success */ public static function notice($message, $scope = array()) { return static::write(static::$_levelMap['notice'], $message, $scope); } /** * Convenience method to log debug messages * * @param string $message log message * @param string|array $scope The scope(s) a log message is being created in. * See CakeLog::config() for more information on logging scopes. * @return bool Success */ public static function debug($message, $scope = array()) { return static::write(static::$_levelMap['debug'], $message, $scope); } /** * Convenience method to log info messages * * @param string $message log message * @param string|array $scope The scope(s) a log message is being created in. * See CakeLog::config() for more information on logging scopes. * @return bool Success */ public static function info($message, $scope = array()) { return static::write(static::$_levelMap['info'], $message, $scope); } } cakephp-2.8.0/lib/Cake/Log/CakeLogInterface.php000066400000000000000000000020461265552240500211350ustar00rootroot00000000000000config($config); } /** * Sets instance config. When $config is null, returns config array * * Config * * - `types` string or array, levels the engine is interested in * - `scopes` string or array, scopes the engine is interested in * * @param array $config engine configuration * @return array */ public function config($config = array()) { if (!empty($config)) { foreach (array('types', 'scopes') as $option) { if (isset($config[$option]) && is_string($config[$option])) { $config[$option] = array($config[$option]); } } $this->_config = $config; } return $this->_config; } } cakephp-2.8.0/lib/Cake/Log/Engine/ConsoleLog.php000066400000000000000000000050741265552240500212640ustar00rootroot00000000000000_output)) ) { $outputAs = ConsoleOutput::PLAIN; } else { $outputAs = ConsoleOutput::COLOR; } $config = Hash::merge(array( 'stream' => 'php://stderr', 'types' => null, 'scopes' => array(), 'outputAs' => $outputAs, ), $this->_config); $config = $this->config($config); if ($config['stream'] instanceof ConsoleOutput) { $this->_output = $config['stream']; } elseif (is_string($config['stream'])) { $this->_output = new ConsoleOutput($config['stream']); } else { throw new CakeLogException('`stream` not a ConsoleOutput nor string'); } $this->_output->outputAs($config['outputAs']); } /** * Implements writing to console. * * @param string $type The type of log you are making. * @param string $message The message you want to log. * @return bool success of write. */ public function write($type, $message) { $output = date('Y-m-d H:i:s') . ' ' . ucfirst($type) . ': ' . $message . "\n"; return $this->_output->write(sprintf('<%s>%s', $type, $output, $type), false); } } cakephp-2.8.0/lib/Cake/Log/Engine/FileLog.php000066400000000000000000000131251265552240500205350ustar00rootroot00000000000000 LOGS, 'file' => null, 'types' => null, 'scopes' => array(), 'rotate' => 10, 'size' => 10485760, // 10MB 'mask' => null, ); /** * Path to save log files on. * * @var string */ protected $_path = null; /** * Log file name * * @var string */ protected $_file = null; /** * Max file size, used for log file rotation. * * @var int */ protected $_size = null; /** * Constructs a new File Logger. * * Config * * - `types` string or array, levels the engine is interested in * - `scopes` string or array, scopes the engine is interested in * - `file` Log file name * - `path` The path to save logs on. * - `size` Used to implement basic log file rotation. If log file size * reaches specified size the existing file is renamed by appending timestamp * to filename and new log file is created. Can be integer bytes value or * human reabable string values like '10MB', '100KB' etc. * - `rotate` Log files are rotated specified times before being removed. * If value is 0, old versions are removed rather then rotated. * - `mask` A mask is applied when log files are created. Left empty no chmod * is made. * * @param array $config Options for the FileLog, see above. */ public function __construct($config = array()) { $config = Hash::merge($this->_defaults, $config); parent::__construct($config); } /** * Sets protected properties based on config provided * * @param array $config Engine configuration * @return array */ public function config($config = array()) { parent::config($config); if (!empty($config['path'])) { $this->_path = $config['path']; } if (Configure::read('debug') && !is_dir($this->_path)) { mkdir($this->_path, 0775, true); } if (!empty($config['file'])) { $this->_file = $config['file']; if (substr($this->_file, -4) !== '.log') { $this->_file .= '.log'; } } if (!empty($config['size'])) { if (is_numeric($config['size'])) { $this->_size = (int)$config['size']; } else { $this->_size = CakeNumber::fromReadableSize($config['size']); } } return $this->_config; } /** * Implements writing to log files. * * @param string $type The type of log you are making. * @param string $message The message you want to log. * @return bool success of write. */ public function write($type, $message) { $output = date('Y-m-d H:i:s') . ' ' . ucfirst($type) . ': ' . $message . "\n"; $filename = $this->_getFilename($type); if (!empty($this->_size)) { $this->_rotateFile($filename); } $pathname = $this->_path . $filename; if (empty($this->_config['mask'])) { return file_put_contents($pathname, $output, FILE_APPEND); } $exists = file_exists($pathname); $result = file_put_contents($pathname, $output, FILE_APPEND); static $selfError = false; if (!$selfError && !$exists && !chmod($pathname, (int)$this->_config['mask'])) { $selfError = true; trigger_error(__d( 'cake_dev', 'Could not apply permission mask "%s" on log file "%s"', array($this->_config['mask'], $pathname)), E_USER_WARNING); $selfError = false; } return $result; } /** * Get filename * * @param string $type The type of log. * @return string File name */ protected function _getFilename($type) { $debugTypes = array('notice', 'info', 'debug'); if (!empty($this->_file)) { $filename = $this->_file; } elseif ($type === 'error' || $type === 'warning') { $filename = 'error.log'; } elseif (in_array($type, $debugTypes)) { $filename = 'debug.log'; } else { $filename = $type . '.log'; } return $filename; } /** * Rotate log file if size specified in config is reached. * Also if `rotate` count is reached oldest file is removed. * * @param string $filename Log file name * @return mixed True if rotated successfully or false in case of error, otherwise null. * Void if file doesn't need to be rotated. */ protected function _rotateFile($filename) { $filepath = $this->_path . $filename; if (version_compare(PHP_VERSION, '5.3.0') >= 0) { clearstatcache(true, $filepath); } else { clearstatcache(); } if (!file_exists($filepath) || filesize($filepath) < $this->_size ) { return null; } if ($this->_config['rotate'] === 0) { $result = unlink($filepath); } else { $result = rename($filepath, $filepath . '.' . time()); } $files = glob($filepath . '.*'); if ($files) { $filesToDelete = count($files) - $this->_config['rotate']; while ($filesToDelete > 0) { unlink(array_shift($files)); $filesToDelete--; } } return $result; } } cakephp-2.8.0/lib/Cake/Log/Engine/SyslogLog.php000066400000000000000000000103101265552240500211270ustar00rootroot00000000000000 'Syslog', * 'types' => array('emergency', 'alert', 'critical', 'error'), * 'format' => "%s: My-App - %s", * 'prefix' => 'Web Server 01' * )); * ``` * * @var array */ protected $_defaults = array( 'format' => '%s: %s', 'flag' => LOG_ODELAY, 'prefix' => '', 'facility' => LOG_USER ); /** * Used to map the string names back to their LOG_* constants * * @var array */ protected $_priorityMap = array( 'emergency' => LOG_EMERG, 'alert' => LOG_ALERT, 'critical' => LOG_CRIT, 'error' => LOG_ERR, 'warning' => LOG_WARNING, 'notice' => LOG_NOTICE, 'info' => LOG_INFO, 'debug' => LOG_DEBUG ); /** * Whether the logger connection is open or not * * @var bool */ protected $_open = false; /** * Make sure the configuration contains the format parameter, by default it uses * the error number and the type as a prefix to the message * * @param array $config Options list. */ public function __construct($config = array()) { $config += $this->_defaults; parent::__construct($config); } /** * Writes a message to syslog * * Map the $type back to a LOG_ constant value, split multi-line messages into multiple * log messages, pass all messages through the format defined in the configuration * * @param string $type The type of log you are making. * @param string $message The message you want to log. * @return bool success of write. */ public function write($type, $message) { if (!$this->_open) { $config = $this->_config; $this->_open($config['prefix'], $config['flag'], $config['facility']); $this->_open = true; } $priority = LOG_DEBUG; if (isset($this->_priorityMap[$type])) { $priority = $this->_priorityMap[$type]; } $messages = explode("\n", $message); foreach ($messages as $message) { $message = sprintf($this->_config['format'], $type, $message); $this->_write($priority, $message); } return true; } /** * Extracts the call to openlog() in order to run unit tests on it. This function * will initialize the connection to the system logger * * @param string $ident the prefix to add to all messages logged * @param int $options the options flags to be used for logged messages * @param int $facility the stream or facility to log to * @return void */ protected function _open($ident, $options, $facility) { openlog($ident, $options, $facility); } /** * Extracts the call to syslog() in order to run unit tests on it. This function * will perform the actual write in the system logger * * @param int $priority Message priority. * @param string $message Message to log. * @return bool */ protected function _write($priority, $message) { return syslog($priority, $message); } /** * Closes the logger connection */ public function __destruct() { closelog(); } } cakephp-2.8.0/lib/Cake/Log/LogEngineCollection.php000066400000000000000000000045651265552240500217020ustar00rootroot00000000000000_getLogger($loggerName); $logger = new $className($options); if (!$logger instanceof CakeLogInterface) { throw new CakeLogException( __d('cake_dev', 'logger class %s does not implement a %s method.', $loggerName, 'write()') ); } $this->_loaded[$name] = $logger; if ($enable) { $this->enable($name); } return $logger; } /** * Attempts to import a logger class from the various paths it could be on. * Checks that the logger class implements a write method as well. * * @param string $loggerName the plugin.className of the logger class you want to build. * @return mixed boolean false on any failures, string of classname to use if search was successful. * @throws CakeLogException */ protected static function _getLogger($loggerName) { list($plugin, $loggerName) = pluginSplit($loggerName, true); if (substr($loggerName, -3) !== 'Log') { $loggerName .= 'Log'; } App::uses($loggerName, $plugin . 'Log/Engine'); if (!class_exists($loggerName)) { throw new CakeLogException(__d('cake_dev', 'Could not load class %s', $loggerName)); } return $loggerName; } } cakephp-2.8.0/lib/Cake/Model/000077500000000000000000000000001265552240500156135ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Model/AclNode.php000066400000000000000000000130051265552240500176300ustar00rootroot00000000000000 array('type' => 'nested')); /** * Constructor */ public function __construct() { $config = Configure::read('Acl.database'); if (isset($config)) { $this->useDbConfig = $config; } parent::__construct(); } /** * Retrieves the Aro/Aco node for this model * * @param string|array|Model $ref Array with 'model' and 'foreign_key', model object, or string value * @return array Node found in database * @throws CakeException when binding to a model that doesn't exist. */ public function node($ref = null) { $db = $this->getDataSource(); $type = $this->alias; $result = null; if (!empty($this->useTable)) { $table = $this->useTable; } else { $table = Inflector::pluralize(Inflector::underscore($type)); } if (empty($ref)) { return null; } elseif (is_string($ref)) { $path = explode('/', $ref); $start = $path[0]; unset($path[0]); $queryData = array( 'conditions' => array( $db->name("{$type}.lft") . ' <= ' . $db->name("{$type}0.lft"), $db->name("{$type}.rght") . ' >= ' . $db->name("{$type}0.rght")), 'fields' => array('id', 'parent_id', 'model', 'foreign_key', 'alias'), 'joins' => array(array( 'table' => $table, 'alias' => "{$type}0", 'type' => 'INNER', 'conditions' => array("{$type}0.alias" => $start) )), 'order' => $db->name("{$type}.lft") . ' DESC' ); $conditionsAfterJoin = array(); foreach ($path as $i => $alias) { $j = $i - 1; $queryData['joins'][] = array( 'table' => $table, 'alias' => "{$type}{$i}", 'type' => 'INNER', 'conditions' => array( $db->name("{$type}{$i}.alias") . ' = ' . $db->value($alias, 'string') ) ); // it will be better if this conditions will performs after join operation $conditionsAfterJoin[] = $db->name("{$type}{$j}.id") . ' = ' . $db->name("{$type}{$i}.parent_id"); $conditionsAfterJoin[] = $db->name("{$type}{$i}.rght") . ' < ' . $db->name("{$type}{$j}.rght"); $conditionsAfterJoin[] = $db->name("{$type}{$i}.lft") . ' > ' . $db->name("{$type}{$j}.lft"); $queryData['conditions'] = array('or' => array( $db->name("{$type}.lft") . ' <= ' . $db->name("{$type}0.lft") . ' AND ' . $db->name("{$type}.rght") . ' >= ' . $db->name("{$type}0.rght"), $db->name("{$type}.lft") . ' <= ' . $db->name("{$type}{$i}.lft") . ' AND ' . $db->name("{$type}.rght") . ' >= ' . $db->name("{$type}{$i}.rght")) ); } $queryData['conditions'] = array_merge($queryData['conditions'], $conditionsAfterJoin); $result = $db->read($this, $queryData, -1); $path = array_values($path); if (!isset($result[0][$type]) || (!empty($path) && $result[0][$type]['alias'] != $path[count($path) - 1]) || (empty($path) && $result[0][$type]['alias'] != $start) ) { return false; } } elseif (is_object($ref) && $ref instanceof Model) { $ref = array('model' => $ref->name, 'foreign_key' => $ref->id); } elseif (is_array($ref) && !(isset($ref['model']) && isset($ref['foreign_key']))) { $name = key($ref); list(, $alias) = pluginSplit($name); $model = ClassRegistry::init(array('class' => $name, 'alias' => $alias)); if (empty($model)) { throw new CakeException('cake_dev', "Model class '%s' not found in AclNode::node() when trying to bind %s object", $type, $this->alias); } $tmpRef = null; if (method_exists($model, 'bindNode')) { $tmpRef = $model->bindNode($ref); } if (empty($tmpRef)) { $ref = array('model' => $alias, 'foreign_key' => $ref[$name][$model->primaryKey]); } else { if (is_string($tmpRef)) { return $this->node($tmpRef); } $ref = $tmpRef; } } if (is_array($ref)) { if (is_array(current($ref)) && is_string(key($ref))) { $name = key($ref); $ref = current($ref); } foreach ($ref as $key => $val) { if (strpos($key, $type) !== 0 && strpos($key, '.') === false) { unset($ref[$key]); $ref["{$type}0.{$key}"] = $val; } } $queryData = array( 'conditions' => $ref, 'fields' => array('id', 'parent_id', 'model', 'foreign_key', 'alias'), 'joins' => array(array( 'table' => $table, 'alias' => "{$type}0", 'type' => 'INNER', 'conditions' => array( $db->name("{$type}.lft") . ' <= ' . $db->name("{$type}0.lft"), $db->name("{$type}.rght") . ' >= ' . $db->name("{$type}0.rght") ) )), 'order' => $db->name("{$type}.lft") . ' DESC' ); $result = $db->read($this, $queryData, -1); if (!$result) { throw new CakeException(__d('cake_dev', "AclNode::node() - Couldn't find %s node identified by \"%s\"", $type, print_r($ref, true))); } } return $result; } } cakephp-2.8.0/lib/Cake/Model/Aco.php000066400000000000000000000017251265552240500170330ustar00rootroot00000000000000 array('with' => 'Permission')); } cakephp-2.8.0/lib/Cake/Model/AcoAction.php000066400000000000000000000016561265552240500201740ustar00rootroot00000000000000 array('with' => 'Permission')); } cakephp-2.8.0/lib/Cake/Model/Behavior/000077500000000000000000000000001265552240500173525ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Model/Behavior/AclBehavior.php000066400000000000000000000106531265552240500222470ustar00rootroot00000000000000 'Aro', 'controlled' => 'Aco', 'both' => array('Aro', 'Aco')); /** * Sets up the configuration for the model, and loads ACL models if they haven't been already * * @param Model $model Model using this behavior. * @param array $config Configuration options. * @return void */ public function setup(Model $model, $config = array()) { if (isset($config[0])) { $config['type'] = $config[0]; unset($config[0]); } $this->settings[$model->name] = array_merge(array('type' => 'controlled'), $config); $this->settings[$model->name]['type'] = strtolower($this->settings[$model->name]['type']); $types = $this->_typeMaps[$this->settings[$model->name]['type']]; if (!is_array($types)) { $types = array($types); } foreach ($types as $type) { $model->{$type} = ClassRegistry::init($type); } if (!method_exists($model, 'parentNode')) { trigger_error(__d('cake_dev', 'Callback %s not defined in %s', 'parentNode()', $model->alias), E_USER_WARNING); } } /** * Retrieves the Aro/Aco node for this model * * @param Model $model Model using this behavior. * @param string|array|Model $ref Array with 'model' and 'foreign_key', model object, or string value * @param string $type Only needed when Acl is set up as 'both', specify 'Aro' or 'Aco' to get the correct node * @return array * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/acl.html#node */ public function node(Model $model, $ref = null, $type = null) { if (empty($type)) { $type = $this->_typeMaps[$this->settings[$model->name]['type']]; if (is_array($type)) { trigger_error(__d('cake_dev', 'AclBehavior is setup with more then one type, please specify type parameter for node()'), E_USER_WARNING); return array(); } } if (empty($ref)) { $ref = array('model' => $model->name, 'foreign_key' => $model->id); } return $model->{$type}->node($ref); } /** * Creates a new ARO/ACO node bound to this record * * @param Model $model Model using this behavior. * @param bool $created True if this is a new record * @param array $options Options passed from Model::save(). * @return void */ public function afterSave(Model $model, $created, $options = array()) { $types = $this->_typeMaps[$this->settings[$model->name]['type']]; if (!is_array($types)) { $types = array($types); } foreach ($types as $type) { $parent = $model->parentNode($type); if (!empty($parent)) { $parent = $this->node($model, $parent, $type); } $data = array( 'parent_id' => isset($parent[0][$type]['id']) ? $parent[0][$type]['id'] : null, 'model' => $model->name, 'foreign_key' => $model->id ); if (!$created) { $node = $this->node($model, null, $type); $data['id'] = isset($node[0][$type]['id']) ? $node[0][$type]['id'] : null; } $model->{$type}->create(); $model->{$type}->save($data); } } /** * Destroys the ARO/ACO node bound to the deleted record * * @param Model $model Model using this behavior. * @return void */ public function afterDelete(Model $model) { $types = $this->_typeMaps[$this->settings[$model->name]['type']]; if (!is_array($types)) { $types = array($types); } foreach ($types as $type) { $node = Hash::extract($this->node($model, null, $type), "0.{$type}.id"); if (!empty($node)) { $model->{$type}->delete($node); } } } } cakephp-2.8.0/lib/Cake/Model/Behavior/ContainableBehavior.php000066400000000000000000000342071265552240500237700ustar00rootroot00000000000000settings[$Model->alias])) { $this->settings[$Model->alias] = array('recursive' => true, 'notices' => true, 'autoFields' => true); } $this->settings[$Model->alias] = array_merge($this->settings[$Model->alias], $settings); } /** * Runs before a find() operation. Used to allow 'contain' setting * as part of the find call, like this: * * `Model->find('all', array('contain' => array('Model1', 'Model2')));` * * ``` * Model->find('all', array('contain' => array( * 'Model1' => array('Model11', 'Model12'), * 'Model2', * 'Model3' => array( * 'Model31' => 'Model311', * 'Model32', * 'Model33' => array('Model331', 'Model332') * ))); * ``` * * @param Model $Model Model using the behavior * @param array $query Query parameters as set by cake * @return array */ public function beforeFind(Model $Model, $query) { $reset = (isset($query['reset']) ? $query['reset'] : true); $noContain = false; $contain = array(); if (isset($this->runtime[$Model->alias]['contain'])) { $noContain = empty($this->runtime[$Model->alias]['contain']); $contain = $this->runtime[$Model->alias]['contain']; unset($this->runtime[$Model->alias]['contain']); } if (isset($query['contain'])) { $noContain = $noContain || empty($query['contain']); if ($query['contain'] !== false) { $contain = array_merge($contain, (array)$query['contain']); } } $noContain = $noContain && empty($contain); if ($noContain || empty($contain)) { if ($noContain) { $query['recursive'] = -1; } return $query; } if ((isset($contain[0]) && is_bool($contain[0])) || is_bool(end($contain))) { $reset = is_bool(end($contain)) ? array_pop($contain) : array_shift($contain); } $containments = $this->containments($Model, $contain); $map = $this->containmentsMap($containments); $mandatory = array(); foreach ($containments['models'] as $model) { $instance = $model['instance']; $needed = $this->fieldDependencies($instance, $map, false); if (!empty($needed)) { $mandatory = array_merge($mandatory, $needed); } if ($contain) { $backupBindings = array(); foreach ($this->types as $relation) { if (!empty($instance->__backAssociation[$relation])) { $backupBindings[$relation] = $instance->__backAssociation[$relation]; } else { $backupBindings[$relation] = $instance->{$relation}; } } foreach ($this->types as $type) { $unbind = array(); foreach ($instance->{$type} as $assoc => $options) { if (!isset($model['keep'][$assoc])) { $unbind[] = $assoc; } } if (!empty($unbind)) { if (!$reset && empty($instance->__backOriginalAssociation)) { $instance->__backOriginalAssociation = $backupBindings; } $instance->unbindModel(array($type => $unbind), $reset); } foreach ($instance->{$type} as $assoc => $options) { if (isset($model['keep'][$assoc]) && !empty($model['keep'][$assoc])) { if (isset($model['keep'][$assoc]['fields'])) { $model['keep'][$assoc]['fields'] = $this->fieldDependencies($containments['models'][$assoc]['instance'], $map, $model['keep'][$assoc]['fields']); } if (!$reset && empty($instance->__backOriginalAssociation)) { $instance->__backOriginalAssociation = $backupBindings; } elseif ($reset) { $instance->__backAssociation[$type] = $backupBindings[$type]; } $instance->{$type}[$assoc] = array_merge($instance->{$type}[$assoc], $model['keep'][$assoc]); } if (!$reset) { $instance->__backInnerAssociation[] = $assoc; } } } } } if ($this->settings[$Model->alias]['recursive']) { $query['recursive'] = (isset($query['recursive'])) ? max($query['recursive'], $containments['depth']) : $containments['depth']; } $autoFields = ($this->settings[$Model->alias]['autoFields'] && !in_array($Model->findQueryType, array('list', 'count')) && !empty($query['fields'])); if (!$autoFields) { return $query; } $query['fields'] = (array)$query['fields']; foreach (array('hasOne', 'belongsTo') as $type) { if (!empty($Model->{$type})) { foreach ($Model->{$type} as $assoc => $data) { if ($Model->useDbConfig === $Model->{$assoc}->useDbConfig && !empty($data['fields'])) { foreach ((array)$data['fields'] as $field) { $query['fields'][] = (strpos($field, '.') === false ? $assoc . '.' : '') . $field; } } } } } if (!empty($mandatory[$Model->alias])) { foreach ($mandatory[$Model->alias] as $field) { if ($field === '--primaryKey--') { $field = $Model->primaryKey; } elseif (preg_match('/^.+\.\-\-[^-]+\-\-$/', $field)) { list($modelName, $field) = explode('.', $field); if ($Model->useDbConfig === $Model->{$modelName}->useDbConfig) { $field = $modelName . '.' . ( ($field === '--primaryKey--') ? $Model->$modelName->primaryKey : $field ); } else { $field = null; } } if ($field !== null) { $query['fields'][] = $field; } } } $query['fields'] = array_unique($query['fields']); return $query; } /** * Unbinds all relations from a model except the specified ones. Calling this function without * parameters unbinds all related models. * * @param Model $Model Model on which binding restriction is being applied * @return void * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/containable.html#using-containable */ public function contain(Model $Model) { $args = func_get_args(); $contain = call_user_func_array('am', array_slice($args, 1)); $this->runtime[$Model->alias]['contain'] = $contain; } /** * Permanently restore the original binding settings of given model, useful * for restoring the bindings after using 'reset' => false as part of the * contain call. * * @param Model $Model Model on which to reset bindings * @return void */ public function resetBindings(Model $Model) { if (!empty($Model->__backOriginalAssociation)) { $Model->__backAssociation = $Model->__backOriginalAssociation; unset($Model->__backOriginalAssociation); } $Model->resetAssociations(); if (!empty($Model->__backInnerAssociation)) { $assocs = $Model->__backInnerAssociation; $Model->__backInnerAssociation = array(); foreach ($assocs as $currentModel) { $this->resetBindings($Model->$currentModel); } } } /** * Process containments for model. * * @param Model $Model Model on which binding restriction is being applied * @param array $contain Parameters to use for restricting this model * @param array $containments Current set of containments * @param bool $throwErrors Whether non-existent bindings show throw errors * @return array Containments */ public function containments(Model $Model, $contain, $containments = array(), $throwErrors = null) { $options = array('className', 'joinTable', 'with', 'foreignKey', 'associationForeignKey', 'conditions', 'fields', 'order', 'limit', 'offset', 'unique', 'finderQuery'); $keep = array(); if ($throwErrors === null) { $throwErrors = (empty($this->settings[$Model->alias]) ? true : $this->settings[$Model->alias]['notices']); } foreach ((array)$contain as $name => $children) { if (is_numeric($name)) { $name = $children; $children = array(); } if (preg_match('/(? $children); } $children = (array)$children; foreach ($children as $key => $val) { if (is_string($key) && is_string($val) && !in_array($key, $options, true)) { $children[$key] = (array)$val; } } $keys = array_keys($children); if ($keys && isset($children[0])) { $keys = array_merge(array_values($children), $keys); } foreach ($keys as $i => $key) { if (is_array($key)) { continue; } $optionKey = in_array($key, $options, true); if (!$optionKey && is_string($key) && preg_match('/^[a-z(]/', $key) && (!isset($Model->{$key}) || !is_object($Model->{$key}))) { $option = 'fields'; $val = array($key); if ($key{0} === '(') { $val = preg_split('/\s*,\s*/', substr($key, 1, -1)); } elseif (preg_match('/ASC|DESC$/', $key)) { $option = 'order'; $val = $Model->{$name}->alias . '.' . $key; } elseif (preg_match('/[ =!]/', $key)) { $option = 'conditions'; $val = $Model->{$name}->alias . '.' . $key; } $children[$option] = is_array($val) ? $val : array($val); $newChildren = null; if (!empty($name) && !empty($children[$key])) { $newChildren = $children[$key]; } unset($children[$key], $children[$i]); $key = $option; $optionKey = true; if (!empty($newChildren)) { $children = Hash::merge($children, $newChildren); } } if ($optionKey && isset($children[$key])) { if (!empty($keep[$name][$key]) && is_array($keep[$name][$key])) { $keep[$name][$key] = array_merge((isset($keep[$name][$key]) ? $keep[$name][$key] : array()), (array)$children[$key]); } else { $keep[$name][$key] = $children[$key]; } unset($children[$key]); } } if (!isset($Model->{$name}) || !is_object($Model->{$name})) { if ($throwErrors) { trigger_error(__d('cake_dev', 'Model "%s" is not associated with model "%s"', $Model->alias, $name), E_USER_WARNING); } continue; } $containments = $this->containments($Model->{$name}, $children, $containments); $depths[] = $containments['depth'] + 1; if (!isset($keep[$name])) { $keep[$name] = array(); } } if (!isset($containments['models'][$Model->alias])) { $containments['models'][$Model->alias] = array('keep' => array(), 'instance' => &$Model); } $containments['models'][$Model->alias]['keep'] = array_merge($containments['models'][$Model->alias]['keep'], $keep); $containments['depth'] = empty($depths) ? 0 : max($depths); return $containments; } /** * Calculate needed fields to fetch the required bindings for the given model. * * @param Model $Model Model * @param array $map Map of relations for given model * @param array|bool $fields If array, fields to initially load, if false use $Model as primary model * @return array Fields */ public function fieldDependencies(Model $Model, $map, $fields = array()) { if ($fields === false) { foreach ($map as $parent => $children) { foreach ($children as $type => $bindings) { foreach ($bindings as $dependency) { if ($type === 'hasAndBelongsToMany') { $fields[$parent][] = '--primaryKey--'; } elseif ($type === 'belongsTo') { $fields[$parent][] = $dependency . '.--primaryKey--'; } } } } return $fields; } if (empty($map[$Model->alias])) { return $fields; } foreach ($map[$Model->alias] as $type => $bindings) { foreach ($bindings as $dependency) { $innerFields = array(); switch ($type) { case 'belongsTo': $fields[] = $Model->{$type}[$dependency]['foreignKey']; break; case 'hasOne': case 'hasMany': $innerFields[] = $Model->$dependency->primaryKey; $fields[] = $Model->primaryKey; break; } if (!empty($innerFields) && !empty($Model->{$type}[$dependency]['fields'])) { $Model->{$type}[$dependency]['fields'] = array_unique(array_merge($Model->{$type}[$dependency]['fields'], $innerFields)); } } } return array_unique($fields); } /** * Build the map of containments * * @param array $containments Containments * @return array Built containments */ public function containmentsMap($containments) { $map = array(); foreach ($containments['models'] as $name => $model) { $instance = $model['instance']; foreach ($this->types as $type) { foreach ($instance->{$type} as $assoc => $options) { if (isset($model['keep'][$assoc])) { $map[$name][$type] = isset($map[$name][$type]) ? array_merge($map[$name][$type], (array)$assoc) : (array)$assoc; } } } } return $map; } } cakephp-2.8.0/lib/Cake/Model/Behavior/TranslateBehavior.php000066400000000000000000000536151265552240500235120ustar00rootroot00000000000000 array('field_one', * 'field_two' => 'FieldAssoc', 'field_three')) * * With above example only one permanent hasMany will be joined (for field_two * as FieldAssoc) * * $config could be empty - and translations configured dynamically by * bindTranslation() method * * @param Model $Model Model the behavior is being attached to. * @param array $config Array of configuration information. * @return mixed */ public function setup(Model $Model, $config = array()) { $db = ConnectionManager::getDataSource($Model->useDbConfig); if (!$db->connected) { trigger_error( __d('cake_dev', 'Datasource %s for TranslateBehavior of model %s is not connected', $Model->useDbConfig, $Model->alias), E_USER_ERROR ); return false; } $this->settings[$Model->alias] = array(); $this->runtime[$Model->alias] = array('fields' => array()); $this->translateModel($Model); return $this->bindTranslation($Model, $config, false); } /** * Cleanup Callback unbinds bound translations and deletes setting information. * * @param Model $Model Model being detached. * @return void */ public function cleanup(Model $Model) { $this->unbindTranslation($Model); unset($this->settings[$Model->alias]); unset($this->runtime[$Model->alias]); } /** * beforeFind Callback * * @param Model $Model Model find is being run on. * @param array $query Array of Query parameters. * @return array Modified query */ public function beforeFind(Model $Model, $query) { $this->runtime[$Model->alias]['virtualFields'] = $Model->virtualFields; $locale = $this->_getLocale($Model); if (empty($locale)) { return $query; } $db = $Model->getDataSource(); $RuntimeModel = $this->translateModel($Model); if (!empty($RuntimeModel->tablePrefix)) { $tablePrefix = $RuntimeModel->tablePrefix; } else { $tablePrefix = $db->config['prefix']; } $joinTable = new StdClass(); $joinTable->tablePrefix = $tablePrefix; $joinTable->table = $RuntimeModel->table; $joinTable->schemaName = $RuntimeModel->getDataSource()->getSchemaName(); $this->_joinTable = $joinTable; $this->_runtimeModel = $RuntimeModel; if (is_string($query['fields']) && $query['fields'] === "COUNT(*) AS {$db->name('count')}") { $query['fields'] = "COUNT(DISTINCT({$db->name($Model->escapeField())})) {$db->alias}count"; $query['joins'][] = array( 'type' => 'INNER', 'alias' => $RuntimeModel->alias, 'table' => $joinTable, 'conditions' => array( $Model->escapeField() => $db->identifier($RuntimeModel->escapeField('foreign_key')), $RuntimeModel->escapeField('model') => $Model->name, $RuntimeModel->escapeField('locale') => $locale ) ); $conditionFields = $this->_checkConditions($Model, $query); foreach ($conditionFields as $field) { $query = $this->_addJoin($Model, $query, $field, $field, $locale); } unset($this->_joinTable, $this->_runtimeModel); return $query; } elseif (is_string($query['fields'])) { $query['fields'] = CakeText::tokenize($query['fields']); } $fields = array_merge( $this->settings[$Model->alias], $this->runtime[$Model->alias]['fields'] ); $addFields = array(); if (empty($query['fields'])) { $addFields = $fields; } elseif (is_array($query['fields'])) { $isAllFields = ( in_array($Model->alias . '.' . '*', $query['fields']) || in_array($Model->escapeField('*'), $query['fields']) ); foreach ($fields as $key => $value) { $field = (is_numeric($key)) ? $value : $key; if ($isAllFields || in_array($Model->alias . '.' . $field, $query['fields']) || in_array($field, $query['fields']) ) { $addFields[] = $field; } } } $this->runtime[$Model->alias]['virtualFields'] = $Model->virtualFields; if ($addFields) { foreach ($addFields as $_f => $field) { $aliasField = is_numeric($_f) ? $field : $_f; foreach (array($aliasField, $Model->alias . '.' . $aliasField) as $_field) { $key = array_search($_field, (array)$query['fields']); if ($key !== false) { unset($query['fields'][$key]); } } $query = $this->_addJoin($Model, $query, $field, $aliasField, $locale); } } $this->runtime[$Model->alias]['beforeFind'] = $addFields; unset($this->_joinTable, $this->_runtimeModel); return $query; } /** * Check a query's conditions for translated fields. * Return an array of translated fields found in the conditions. * * @param Model $Model The model being read. * @param array $query The query array. * @return array The list of translated fields that are in the conditions. */ protected function _checkConditions(Model $Model, $query) { $conditionFields = array(); if (empty($query['conditions']) || (!empty($query['conditions']) && !is_array($query['conditions']))) { return $conditionFields; } foreach ($query['conditions'] as $col => $val) { foreach ($this->settings[$Model->alias] as $field => $assoc) { if (is_numeric($field)) { $field = $assoc; } if (strpos($col, $field) !== false) { $conditionFields[] = $field; } } } return $conditionFields; } /** * Appends a join for translated fields. * * @param Model $Model The model being worked on. * @param array $query The query array to append a join to. * @param string $field The field name being joined. * @param string $aliasField The aliased field name being joined. * @param string|array $locale The locale(s) having joins added. * @return array The modified query */ protected function _addJoin(Model $Model, $query, $field, $aliasField, $locale) { $db = ConnectionManager::getDataSource($Model->useDbConfig); $RuntimeModel = $this->_runtimeModel; $joinTable = $this->_joinTable; $aliasVirtual = "i18n_{$field}"; $alias = "I18n__{$field}"; if (is_array($locale)) { foreach ($locale as $_locale) { $aliasVirtualLocale = "{$aliasVirtual}_{$_locale}"; $aliasLocale = "{$alias}__{$_locale}"; $Model->virtualFields[$aliasVirtualLocale] = "{$aliasLocale}.content"; if (!empty($query['fields']) && is_array($query['fields'])) { $query['fields'][] = $aliasVirtualLocale; } $query['joins'][] = array( 'type' => 'LEFT', 'alias' => $aliasLocale, 'table' => $joinTable, 'conditions' => array( $Model->escapeField() => $db->identifier("{$aliasLocale}.foreign_key"), "{$aliasLocale}.model" => $Model->name, "{$aliasLocale}.{$RuntimeModel->displayField}" => $aliasField, "{$aliasLocale}.locale" => $_locale ) ); } } else { $Model->virtualFields[$aliasVirtual] = "{$alias}.content"; if (!empty($query['fields']) && is_array($query['fields'])) { $query['fields'][] = $aliasVirtual; } $query['joins'][] = array( 'type' => 'INNER', 'alias' => $alias, 'table' => $joinTable, 'conditions' => array( "{$Model->alias}.{$Model->primaryKey}" => $db->identifier("{$alias}.foreign_key"), "{$alias}.model" => $Model->name, "{$alias}.{$RuntimeModel->displayField}" => $aliasField, "{$alias}.locale" => $locale ) ); } return $query; } /** * afterFind Callback * * @param Model $Model Model find was run on * @param array $results Array of model results. * @param bool $primary Did the find originate on $model. * @return array Modified results */ public function afterFind(Model $Model, $results, $primary = false) { $Model->virtualFields = $this->runtime[$Model->alias]['virtualFields']; $this->runtime[$Model->alias]['virtualFields'] = $this->runtime[$Model->alias]['fields'] = array(); if (!empty($this->runtime[$Model->alias]['restoreFields'])) { $this->runtime[$Model->alias]['fields'] = $this->runtime[$Model->alias]['restoreFields']; unset($this->runtime[$Model->alias]['restoreFields']); } $locale = $this->_getLocale($Model); if (empty($locale) || empty($results) || empty($this->runtime[$Model->alias]['beforeFind'])) { return $results; } $beforeFind = $this->runtime[$Model->alias]['beforeFind']; foreach ($results as $key => &$row) { $results[$key][$Model->alias]['locale'] = (is_array($locale)) ? current($locale) : $locale; foreach ($beforeFind as $_f => $field) { $aliasField = is_numeric($_f) ? $field : $_f; $aliasVirtual = "i18n_{$field}"; if (is_array($locale)) { foreach ($locale as $_locale) { $aliasVirtualLocale = "{$aliasVirtual}_{$_locale}"; if (!isset($row[$Model->alias][$aliasField]) && !empty($row[$Model->alias][$aliasVirtualLocale])) { $row[$Model->alias][$aliasField] = $row[$Model->alias][$aliasVirtualLocale]; $row[$Model->alias]['locale'] = $_locale; } unset($row[$Model->alias][$aliasVirtualLocale]); } if (!isset($row[$Model->alias][$aliasField])) { $row[$Model->alias][$aliasField] = ''; } } else { $value = ''; if (isset($row[$Model->alias][$aliasVirtual])) { $value = $row[$Model->alias][$aliasVirtual]; } $row[$Model->alias][$aliasField] = $value; unset($row[$Model->alias][$aliasVirtual]); } } } return $results; } /** * beforeValidate Callback * * @param Model $Model Model invalidFields was called on. * @param array $options Options passed from Model::save(). * @return bool * @see Model::save() */ public function beforeValidate(Model $Model, $options = array()) { unset($this->runtime[$Model->alias]['beforeSave']); $this->_setRuntimeData($Model); return true; } /** * beforeSave callback. * * Copies data into the runtime property when `$options['validate']` is * disabled. Or the runtime data hasn't been set yet. * * @param Model $Model Model save was called on. * @param array $options Options passed from Model::save(). * @return bool true. * @see Model::save() */ public function beforeSave(Model $Model, $options = array()) { if (isset($options['validate']) && !$options['validate']) { unset($this->runtime[$Model->alias]['beforeSave']); } if (isset($this->runtime[$Model->alias]['beforeSave'])) { return true; } $this->_setRuntimeData($Model); return true; } /** * Sets the runtime data. * * Used from beforeValidate() and beforeSave() for compatibility issues, * and to allow translations to be persisted even when validation * is disabled. * * @param Model $Model Model using this behavior. * @return void */ protected function _setRuntimeData(Model $Model) { $locale = $this->_getLocale($Model); if (empty($locale)) { return true; } $fields = array_merge($this->settings[$Model->alias], $this->runtime[$Model->alias]['fields']); $tempData = array(); foreach ($fields as $key => $value) { $field = (is_numeric($key)) ? $value : $key; if (isset($Model->data[$Model->alias][$field])) { $tempData[$field] = $Model->data[$Model->alias][$field]; if (is_array($Model->data[$Model->alias][$field])) { if (is_string($locale) && !empty($Model->data[$Model->alias][$field][$locale])) { $Model->data[$Model->alias][$field] = $Model->data[$Model->alias][$field][$locale]; } else { $values = array_values($Model->data[$Model->alias][$field]); $Model->data[$Model->alias][$field] = $values[0]; } } } } $this->runtime[$Model->alias]['beforeSave'] = $tempData; } /** * Restores model data to the original data. * This solves issues with saveAssociated and validate = first. * * @param Model $Model Model using this behavior. * @return void */ public function afterValidate(Model $Model) { $Model->data[$Model->alias] = array_merge( $Model->data[$Model->alias], $this->runtime[$Model->alias]['beforeSave'] ); return true; } /** * afterSave Callback * * @param Model $Model Model the callback is called on * @param bool $created Whether or not the save created a record. * @param array $options Options passed from Model::save(). * @return void */ public function afterSave(Model $Model, $created, $options = array()) { if (!isset($this->runtime[$Model->alias]['beforeValidate']) && !isset($this->runtime[$Model->alias]['beforeSave'])) { return true; } if (isset($this->runtime[$Model->alias]['beforeValidate'])) { $tempData = $this->runtime[$Model->alias]['beforeValidate']; } else { $tempData = $this->runtime[$Model->alias]['beforeSave']; } unset($this->runtime[$Model->alias]['beforeValidate'], $this->runtime[$Model->alias]['beforeSave']); $conditions = array('model' => $Model->name, 'foreign_key' => $Model->id); $RuntimeModel = $this->translateModel($Model); if ($created) { $tempData = $this->_prepareTranslations($Model, $tempData); } $locale = $this->_getLocale($Model); $atomic = array(); if (isset($options['atomic'])) { $atomic = array('atomic' => $options['atomic']); } foreach ($tempData as $field => $value) { unset($conditions['content']); $conditions['field'] = $field; if (is_array($value)) { $conditions['locale'] = array_keys($value); } else { $conditions['locale'] = $locale; if (is_array($locale)) { $value = array($locale[0] => $value); } else { $value = array($locale => $value); } } $translations = $RuntimeModel->find('list', array( 'conditions' => $conditions, 'fields' => array( $RuntimeModel->alias . '.locale', $RuntimeModel->alias . '.id' ) )); foreach ($value as $_locale => $_value) { $RuntimeModel->create(); $conditions['locale'] = $_locale; $conditions['content'] = $_value; if (array_key_exists($_locale, $translations)) { $RuntimeModel->save(array( $RuntimeModel->alias => array_merge( $conditions, array('id' => $translations[$_locale]) ), $atomic )); } else { $RuntimeModel->save(array($RuntimeModel->alias => $conditions), $atomic); } } } } /** * Prepares the data to be saved for translated records. * Add blank fields, and populates data for multi-locale saves. * * @param Model $Model Model using this behavior * @param array $data The sparse data that was provided. * @return array The fully populated data to save. */ protected function _prepareTranslations(Model $Model, $data) { $fields = array_merge($this->settings[$Model->alias], $this->runtime[$Model->alias]['fields']); $locales = array(); foreach ($data as $key => $value) { if (is_array($value)) { $locales = array_merge($locales, array_keys($value)); } } $locales = array_unique($locales); $hasLocales = count($locales) > 0; foreach ($fields as $key => $field) { if (!is_numeric($key)) { $field = $key; } if ($hasLocales && !isset($data[$field])) { $data[$field] = array_fill_keys($locales, ''); } elseif (!isset($data[$field])) { $data[$field] = ''; } } return $data; } /** * afterDelete Callback * * @param Model $Model Model the callback was run on. * @return void */ public function afterDelete(Model $Model) { $RuntimeModel = $this->translateModel($Model); $conditions = array('model' => $Model->name, 'foreign_key' => $Model->id); $RuntimeModel->deleteAll($conditions); } /** * Get selected locale for model * * @param Model $Model Model the locale needs to be set/get on. * @return mixed string or false */ protected function _getLocale(Model $Model) { if (!isset($Model->locale) || $Model->locale === null) { $I18n = I18n::getInstance(); $I18n->l10n->get(Configure::read('Config.language')); $Model->locale = $I18n->l10n->locale; } return $Model->locale; } /** * Get instance of model for translations. * * If the model has a translateModel property set, this will be used as the class * name to find/use. If no translateModel property is found 'I18nModel' will be used. * * @param Model $Model Model to get a translatemodel for. * @return Model */ public function translateModel(Model $Model) { if (!isset($this->runtime[$Model->alias]['model'])) { if (!isset($Model->translateModel) || empty($Model->translateModel)) { $className = 'I18nModel'; } else { $className = $Model->translateModel; } $this->runtime[$Model->alias]['model'] = ClassRegistry::init($className); } if (!empty($Model->translateTable) && $Model->translateTable !== $this->runtime[$Model->alias]['model']->useTable) { $this->runtime[$Model->alias]['model']->setSource($Model->translateTable); } elseif (empty($Model->translateTable) && empty($Model->translateModel)) { $this->runtime[$Model->alias]['model']->setSource('i18n'); } return $this->runtime[$Model->alias]['model']; } /** * Bind translation for fields, optionally with hasMany association for * fake field. * * *Note* You should avoid binding translations that overlap existing model properties. * This can cause un-expected and un-desirable behavior. * * @param Model $Model using this behavior of model * @param string|array $fields string with field or array(field1, field2=>AssocName, field3) * @param bool $reset Leave true to have the fields only modified for the next operation. * if false the field will be added for all future queries. * @return bool * @throws CakeException when attempting to bind a translating called name. This is not allowed * as it shadows Model::$name. */ public function bindTranslation(Model $Model, $fields, $reset = true) { if (is_string($fields)) { $fields = array($fields); } $associations = array(); $RuntimeModel = $this->translateModel($Model); $default = array( 'className' => $RuntimeModel->alias, 'foreignKey' => 'foreign_key', 'order' => 'id' ); foreach ($fields as $key => $value) { if (is_numeric($key)) { $field = $value; $association = null; } else { $field = $key; $association = $value; } if ($association === 'name') { throw new CakeException( __d('cake_dev', 'You cannot bind a translation named "name".') ); } $this->_removeField($Model, $field); if ($association === null) { if ($reset) { $this->runtime[$Model->alias]['fields'][] = $field; } else { $this->settings[$Model->alias][] = $field; } } else { if ($reset) { $this->runtime[$Model->alias]['fields'][$field] = $association; $this->runtime[$Model->alias]['restoreFields'][] = $field; } else { $this->settings[$Model->alias][$field] = $association; } foreach (array('hasOne', 'hasMany', 'belongsTo', 'hasAndBelongsToMany') as $type) { if (isset($Model->{$type}[$association]) || isset($Model->__backAssociation[$type][$association])) { trigger_error( __d('cake_dev', 'Association %s is already bound to model %s', $association, $Model->alias), E_USER_ERROR ); return false; } } $associations[$association] = array_merge($default, array('conditions' => array( 'model' => $Model->name, $RuntimeModel->displayField => $field ))); } } if (!empty($associations)) { $Model->bindModel(array('hasMany' => $associations), $reset); } return true; } /** * Update runtime setting for a given field. * * @param Model $Model Model using this behavior * @param string $field The field to update. * @return void */ protected function _removeField(Model $Model, $field) { if (array_key_exists($field, $this->settings[$Model->alias])) { unset($this->settings[$Model->alias][$field]); } elseif (in_array($field, $this->settings[$Model->alias])) { $this->settings[$Model->alias] = array_merge(array_diff($this->settings[$Model->alias], array($field))); } if (array_key_exists($field, $this->runtime[$Model->alias]['fields'])) { unset($this->runtime[$Model->alias]['fields'][$field]); } elseif (in_array($field, $this->runtime[$Model->alias]['fields'])) { $this->runtime[$Model->alias]['fields'] = array_merge(array_diff($this->runtime[$Model->alias]['fields'], array($field))); } } /** * Unbind translation for fields, optionally unbinds hasMany association for * fake field * * @param Model $Model using this behavior of model * @param string|array $fields string with field, or array(field1, field2=>AssocName, field3), or null for * unbind all original translations * @return bool */ public function unbindTranslation(Model $Model, $fields = null) { if (empty($fields) && empty($this->settings[$Model->alias])) { return false; } if (empty($fields)) { return $this->unbindTranslation($Model, $this->settings[$Model->alias]); } if (is_string($fields)) { $fields = array($fields); } $associations = array(); foreach ($fields as $key => $value) { if (is_numeric($key)) { $field = $value; $association = null; } else { $field = $key; $association = $value; } $this->_removeField($Model, $field); if ($association !== null && (isset($Model->hasMany[$association]) || isset($Model->__backAssociation['hasMany'][$association]))) { $associations[] = $association; } } if (!empty($associations)) { $Model->unbindModel(array('hasMany' => $associations), false); } return true; } } cakephp-2.8.0/lib/Cake/Model/Behavior/TreeBehavior.php000066400000000000000000001234131265552240500224460ustar00rootroot00000000000000 'parent_id', 'left' => 'lft', 'right' => 'rght', 'level' => null, 'scope' => '1 = 1', 'type' => 'nested', '__parentChange' => false, 'recursive' => -1 ); /** * Used to preserve state between delete callbacks. * * @var array */ protected $_deletedRow = array(); /** * Initiate Tree behavior * * @param Model $Model using this behavior of model * @param array $config array of configuration settings. * @return void */ public function setup(Model $Model, $config = array()) { if (isset($config[0])) { $config['type'] = $config[0]; unset($config[0]); } $settings = $config + $this->_defaults; if (in_array($settings['scope'], $Model->getAssociated('belongsTo'))) { $data = $Model->getAssociated($settings['scope']); $Parent = $Model->{$settings['scope']}; $settings['scope'] = $Model->escapeField($data['foreignKey']) . ' = ' . $Parent->escapeField(); $settings['recursive'] = 0; } $this->settings[$Model->alias] = $settings; } /** * After save method. Called after all saves * * Overridden to transparently manage setting the lft and rght fields if and only if the parent field is included in the * parameters to be saved. * * @param Model $Model Model using this behavior. * @param bool $created indicates whether the node just saved was created or updated * @param array $options Options passed from Model::save(). * @return bool true on success, false on failure */ public function afterSave(Model $Model, $created, $options = array()) { extract($this->settings[$Model->alias]); if ($created) { if ((isset($Model->data[$Model->alias][$parent])) && $Model->data[$Model->alias][$parent]) { return $this->_setParent($Model, $Model->data[$Model->alias][$parent], $created); } } elseif ($this->settings[$Model->alias]['__parentChange']) { $this->settings[$Model->alias]['__parentChange'] = false; if ($level) { $this->_setChildrenLevel($Model, $Model->id); } return $this->_setParent($Model, $Model->data[$Model->alias][$parent]); } } /** * Set level for descendents. * * @param Model $Model Model using this behavior. * @param int|string $id Record ID * @return void */ protected function _setChildrenLevel(Model $Model, $id) { $settings = $Model->Behaviors->Tree->settings[$Model->alias]; $primaryKey = $Model->primaryKey; $depths = array($id => (int)$Model->data[$Model->alias][$settings['level']]); $children = $Model->children( $id, false, array($primaryKey, $settings['parent'], $settings['level']), $settings['left'], null, 1, -1 ); foreach ($children as $node) { $parentIdValue = $node[$Model->alias][$settings['parent']]; $depth = (int)$depths[$parentIdValue] + 1; $depths[$node[$Model->alias][$primaryKey]] = $depth; $Model->updateAll( array($Model->escapeField($settings['level']) => $depth), array($Model->escapeField($primaryKey) => $node[$Model->alias][$primaryKey]) ); } } /** * Runs before a find() operation * * @param Model $Model Model using the behavior * @param array $query Query parameters as set by cake * @return array */ public function beforeFind(Model $Model, $query) { if ($Model->findQueryType === 'threaded' && !isset($query['parent'])) { $query['parent'] = $this->settings[$Model->alias]['parent']; } return $query; } /** * Stores the record about to be deleted. * * This is used to delete child nodes in the afterDelete. * * @param Model $Model Model using this behavior. * @param bool $cascade If true records that depend on this record will also be deleted * @return bool */ public function beforeDelete(Model $Model, $cascade = true) { extract($this->settings[$Model->alias]); $data = $Model->find('first', array( 'conditions' => array($Model->escapeField($Model->primaryKey) => $Model->id), 'fields' => array($Model->escapeField($left), $Model->escapeField($right)), 'order' => false, 'recursive' => -1)); if ($data) { $this->_deletedRow[$Model->alias] = current($data); } return true; } /** * After delete method. * * Will delete the current node and all children using the deleteAll method and sync the table * * @param Model $Model Model using this behavior * @return bool true to continue, false to abort the delete */ public function afterDelete(Model $Model) { extract($this->settings[$Model->alias]); $data = $this->_deletedRow[$Model->alias]; $this->_deletedRow[$Model->alias] = null; if (!$data[$right] || !$data[$left]) { return true; } $diff = $data[$right] - $data[$left] + 1; if ($diff > 2) { if (is_string($scope)) { $scope = array($scope); } $scope[][$Model->escapeField($left) . " BETWEEN ? AND ?"] = array($data[$left] + 1, $data[$right] - 1); $Model->deleteAll($scope); } $this->_sync($Model, $diff, '-', '> ' . $data[$right]); return true; } /** * Before save method. Called before all saves * * Overridden to transparently manage setting the lft and rght fields if and only if the parent field is included in the * parameters to be saved. For newly created nodes with NO parent the left and right field values are set directly by * this method bypassing the setParent logic. * * @param Model $Model Model using this behavior * @param array $options Options passed from Model::save(). * @return bool true to continue, false to abort the save * @see Model::save() */ public function beforeSave(Model $Model, $options = array()) { extract($this->settings[$Model->alias]); $this->_addToWhitelist($Model, array($left, $right)); if ($level) { $this->_addToWhitelist($Model, $level); } $parentIsSet = array_key_exists($parent, $Model->data[$Model->alias]); if (!$Model->id || !$Model->exists()) { if ($parentIsSet && $Model->data[$Model->alias][$parent]) { $parentNode = $this->_getNode($Model, $Model->data[$Model->alias][$parent]); if (!$parentNode) { return false; } $Model->data[$Model->alias][$left] = 0; $Model->data[$Model->alias][$right] = 0; if ($level) { $Model->data[$Model->alias][$level] = (int)$parentNode[$Model->alias][$level] + 1; } return true; } $edge = $this->_getMax($Model, $scope, $right, $recursive); $Model->data[$Model->alias][$left] = $edge + 1; $Model->data[$Model->alias][$right] = $edge + 2; if ($level) { $Model->data[$Model->alias][$level] = 0; } return true; } if ($parentIsSet) { if ($Model->data[$Model->alias][$parent] != $Model->field($parent)) { $this->settings[$Model->alias]['__parentChange'] = true; } if (!$Model->data[$Model->alias][$parent]) { $Model->data[$Model->alias][$parent] = null; $this->_addToWhitelist($Model, $parent); if ($level) { $Model->data[$Model->alias][$level] = 0; } return true; } $values = $this->_getNode($Model, $Model->id); if (empty($values)) { return false; } list($node) = array_values($values); $parentNode = $this->_getNode($Model, $Model->data[$Model->alias][$parent]); if (!$parentNode) { return false; } list($parentNode) = array_values($parentNode); if (($node[$left] < $parentNode[$left]) && ($parentNode[$right] < $node[$right])) { return false; } if ($node[$Model->primaryKey] === $parentNode[$Model->primaryKey]) { return false; } if ($level) { $Model->data[$Model->alias][$level] = (int)$parentNode[$level] + 1; } } return true; } /** * Returns a single node from the tree from its primary key * * @param Model $Model Model using this behavior * @param int|string $id The ID of the record to read * @return array|bool The record read or false */ protected function _getNode(Model $Model, $id) { $settings = $this->settings[$Model->alias]; $fields = array($Model->primaryKey, $settings['parent'], $settings['left'], $settings['right']); if ($settings['level']) { $fields[] = $settings['level']; } return $Model->find('first', array( 'conditions' => array($Model->escapeField() => $id), 'fields' => $fields, 'recursive' => $settings['recursive'], 'order' => false, )); } /** * Get the number of child nodes * * If the direct parameter is set to true, only the direct children are counted (based upon the parent_id field) * If false is passed for the id parameter, all top level nodes are counted, or all nodes are counted. * * @param Model $Model Model using this behavior * @param int|string|bool $id The ID of the record to read or false to read all top level nodes * @param bool $direct whether to count direct, or all, children * @return int number of child nodes * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::childCount */ public function childCount(Model $Model, $id = null, $direct = false) { if (is_array($id)) { extract(array_merge(array('id' => null), $id)); } if ($id === null && $Model->id) { $id = $Model->id; } elseif (!$id) { $id = null; } extract($this->settings[$Model->alias]); if ($direct) { return $Model->find('count', array('conditions' => array($scope, $Model->escapeField($parent) => $id))); } if ($id === null) { return $Model->find('count', array('conditions' => $scope)); } elseif ($Model->id === $id && isset($Model->data[$Model->alias][$left]) && isset($Model->data[$Model->alias][$right])) { $data = $Model->data[$Model->alias]; } else { $data = $this->_getNode($Model, $id); if (!$data) { return 0; } $data = $data[$Model->alias]; } return ($data[$right] - $data[$left] - 1) / 2; } /** * Get the child nodes of the current model * * If the direct parameter is set to true, only the direct children are returned (based upon the parent_id field) * If false is passed for the id parameter, top level, or all (depending on direct parameter appropriate) are counted. * * @param Model $Model Model using this behavior * @param int|string $id The ID of the record to read * @param bool $direct whether to return only the direct, or all, children * @param string|array $fields Either a single string of a field name, or an array of field names * @param string $order SQL ORDER BY conditions (e.g. "price DESC" or "name ASC") defaults to the tree order * @param int $limit SQL LIMIT clause, for calculating items per page. * @param int $page Page number, for accessing paged data * @param int $recursive The number of levels deep to fetch associated records * @return array Array of child nodes * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::children */ public function children(Model $Model, $id = null, $direct = false, $fields = null, $order = null, $limit = null, $page = 1, $recursive = null) { $options = array(); if (is_array($id)) { $options = $this->_getOptions($id); extract(array_merge(array('id' => null), $id)); } $overrideRecursive = $recursive; if ($id === null && $Model->id) { $id = $Model->id; } elseif (!$id) { $id = null; } extract($this->settings[$Model->alias]); if ($overrideRecursive !== null) { $recursive = $overrideRecursive; } if (!$order) { $order = $Model->escapeField($left) . " asc"; } if ($direct) { $conditions = array($scope, $Model->escapeField($parent) => $id); return $Model->find('all', compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive')); } if (!$id) { $conditions = $scope; } else { $result = array_values((array)$Model->find('first', array( 'conditions' => array($scope, $Model->escapeField() => $id), 'fields' => array($left, $right), 'recursive' => $recursive, 'order' => false, ))); if (empty($result) || !isset($result[0])) { return array(); } $conditions = array($scope, $Model->escapeField($right) . ' <' => $result[0][$right], $Model->escapeField($left) . ' >' => $result[0][$left] ); } $options = array_merge(compact( 'conditions', 'fields', 'order', 'limit', 'page', 'recursive' ), $options); return $Model->find('all', $options); } /** * A convenience method for returning a hierarchical array used for HTML select boxes * * @param Model $Model Model using this behavior * @param string|array $conditions SQL conditions as a string or as an array('field' =>'value',...) * @param string $keyPath A string path to the key, i.e. "{n}.Post.id" * @param string $valuePath A string path to the value, i.e. "{n}.Post.title" * @param string $spacer The character or characters which will be repeated * @param int $recursive The number of levels deep to fetch associated records * @return array An associative array of records, where the id is the key, and the display field is the value * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::generateTreeList */ public function generateTreeList(Model $Model, $conditions = null, $keyPath = null, $valuePath = null, $spacer = '_', $recursive = null) { $overrideRecursive = $recursive; extract($this->settings[$Model->alias]); if ($overrideRecursive !== null) { $recursive = $overrideRecursive; } $fields = null; if (!$keyPath && !$valuePath && $Model->hasField($Model->displayField)) { $fields = array($Model->primaryKey, $Model->displayField, $left, $right); } $conditions = (array)$conditions; if ($scope) { $conditions[] = $scope; } $order = $Model->escapeField($left) . ' asc'; $results = $Model->find('all', compact('conditions', 'fields', 'order', 'recursive')); return $this->formatTreeList($Model, $results, compact('keyPath', 'valuePath', 'spacer')); } /** * Formats result of a find() call to a hierarchical array used for HTML select boxes. * * Note that when using your own find() call this expects the order to be "left" field asc in order * to generate the same result as using generateTreeList() directly. * * Options: * * - 'keyPath': A string path to the key, i.e. "{n}.Post.id" * - 'valuePath': A string path to the value, i.e. "{n}.Post.title" * - 'spacer': The character or characters which will be repeated * * @param Model $Model Model using this behavior * @param array $results Result array of a find() call * @param array $options Options * @return array An associative array of records, where the id is the key, and the display field is the value */ public function formatTreeList(Model $Model, array $results, array $options = array()) { if (empty($results)) { return array(); } $defaults = array( 'keyPath' => null, 'valuePath' => null, 'spacer' => '_' ); $options += $defaults; extract($this->settings[$Model->alias]); if (!$options['keyPath']) { $options['keyPath'] = '{n}.' . $Model->alias . '.' . $Model->primaryKey; } if (!$options['valuePath']) { $options['valuePath'] = array('%s%s', '{n}.tree_prefix', '{n}.' . $Model->alias . '.' . $Model->displayField); } elseif (is_string($options['valuePath'])) { $options['valuePath'] = array('%s%s', '{n}.tree_prefix', $options['valuePath']); } else { array_unshift($options['valuePath'], '%s' . $options['valuePath'][0], '{n}.tree_prefix'); } $stack = array(); foreach ($results as $i => $result) { $count = count($stack); while ($stack && ($stack[$count - 1] < $result[$Model->alias][$right])) { array_pop($stack); $count--; } $results[$i]['tree_prefix'] = str_repeat($options['spacer'], $count); $stack[] = $result[$Model->alias][$right]; } return Hash::combine($results, $options['keyPath'], $options['valuePath']); } /** * Get the parent node * * reads the parent id and returns this node * * @param Model $Model Model using this behavior * @param int|string $id The ID of the record to read * @param string|array $fields Fields to get * @param int $recursive The number of levels deep to fetch associated records * @return array|bool Array of data for the parent node * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::getParentNode */ public function getParentNode(Model $Model, $id = null, $fields = null, $recursive = null) { $options = array(); if (is_array($id)) { $options = $this->_getOptions($id); extract(array_merge(array('id' => null), $id)); } $overrideRecursive = $recursive; if (empty($id)) { $id = $Model->id; } extract($this->settings[$Model->alias]); if ($overrideRecursive !== null) { $recursive = $overrideRecursive; } $parentId = $Model->find('first', array( 'conditions' => array($Model->primaryKey => $id), 'fields' => array($parent), 'order' => false, 'recursive' => -1 )); if ($parentId) { $parentId = $parentId[$Model->alias][$parent]; $options = array_merge(array( 'conditions' => array($Model->escapeField() => $parentId), 'fields' => $fields, 'order' => false, 'recursive' => $recursive ), $options); $parent = $Model->find('first', $options); return $parent; } return false; } /** * Convenience method to create default find() options from $arg when it is an * associative array. * * @param array $arg Array * @return array Options array */ protected function _getOptions($arg) { return count(array_filter(array_keys($arg), 'is_string') > 0) ? $arg : array(); } /** * Get the path to the given node * * @param Model $Model Model using this behavior * @param int|string $id The ID of the record to read * @param string|array $fields Either a single string of a field name, or an array of field names * @param int $recursive The number of levels deep to fetch associated records * @return array Array of nodes from top most parent to current node * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::getPath */ public function getPath(Model $Model, $id = null, $fields = null, $recursive = null) { $options = array(); if (is_array($id)) { $options = $this->_getOptions($id); extract(array_merge(array('id' => null), $id)); } if (!empty($options)) { $fields = null; if (!empty($options['fields'])) { $fields = $options['fields']; } if (!empty($options['recursive'])) { $recursive = $options['recursive']; } } $overrideRecursive = $recursive; if (empty($id)) { $id = $Model->id; } extract($this->settings[$Model->alias]); if ($overrideRecursive !== null) { $recursive = $overrideRecursive; } $result = $Model->find('first', array( 'conditions' => array($Model->escapeField() => $id), 'fields' => array($left, $right), 'order' => false, 'recursive' => $recursive )); if ($result) { $result = array_values($result); } else { return array(); } $item = $result[0]; $options = array_merge(array( 'conditions' => array( $scope, $Model->escapeField($left) . ' <=' => $item[$left], $Model->escapeField($right) . ' >=' => $item[$right], ), 'fields' => $fields, 'order' => array($Model->escapeField($left) => 'asc'), 'recursive' => $recursive ), $options); $results = $Model->find('all', $options); return $results; } /** * Reorder the node without changing the parent. * * If the node is the last child, or is a top level node with no subsequent node this method will return false * * @param Model $Model Model using this behavior * @param int|string $id The ID of the record to move * @param int|bool $number how many places to move the node or true to move to last position * @return bool true on success, false on failure * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::moveDown */ public function moveDown(Model $Model, $id = null, $number = 1) { if (is_array($id)) { extract(array_merge(array('id' => null), $id)); } if (!$number) { return false; } if (empty($id)) { $id = $Model->id; } extract($this->settings[$Model->alias]); list($node) = array_values($this->_getNode($Model, $id)); if ($node[$parent]) { list($parentNode) = array_values($this->_getNode($Model, $node[$parent])); if (($node[$right] + 1) == $parentNode[$right]) { return false; } } $nextNode = $Model->find('first', array( 'conditions' => array($scope, $Model->escapeField($left) => ($node[$right] + 1)), 'fields' => array($Model->primaryKey, $left, $right), 'order' => false, 'recursive' => $recursive) ); if ($nextNode) { list($nextNode) = array_values($nextNode); } else { return false; } $edge = $this->_getMax($Model, $scope, $right, $recursive); $this->_sync($Model, $edge - $node[$left] + 1, '+', 'BETWEEN ' . $node[$left] . ' AND ' . $node[$right]); $this->_sync($Model, $nextNode[$left] - $node[$left], '-', 'BETWEEN ' . $nextNode[$left] . ' AND ' . $nextNode[$right]); $this->_sync($Model, $edge - $node[$left] - ($nextNode[$right] - $nextNode[$left]), '-', '> ' . $edge); if (is_int($number)) { $number--; } if ($number) { $this->moveDown($Model, $id, $number); } return true; } /** * Reorder the node without changing the parent. * * If the node is the first child, or is a top level node with no previous node this method will return false * * @param Model $Model Model using this behavior * @param int|string $id The ID of the record to move * @param int|bool $number how many places to move the node, or true to move to first position * @return bool true on success, false on failure * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::moveUp */ public function moveUp(Model $Model, $id = null, $number = 1) { if (is_array($id)) { extract(array_merge(array('id' => null), $id)); } if (!$number) { return false; } if (empty($id)) { $id = $Model->id; } extract($this->settings[$Model->alias]); list($node) = array_values($this->_getNode($Model, $id)); if ($node[$parent]) { list($parentNode) = array_values($this->_getNode($Model, $node[$parent])); if (($node[$left] - 1) == $parentNode[$left]) { return false; } } $previousNode = $Model->find('first', array( 'conditions' => array($scope, $Model->escapeField($right) => ($node[$left] - 1)), 'fields' => array($Model->primaryKey, $left, $right), 'order' => false, 'recursive' => $recursive )); if ($previousNode) { list($previousNode) = array_values($previousNode); } else { return false; } $edge = $this->_getMax($Model, $scope, $right, $recursive); $this->_sync($Model, $edge - $previousNode[$left] + 1, '+', 'BETWEEN ' . $previousNode[$left] . ' AND ' . $previousNode[$right]); $this->_sync($Model, $node[$left] - $previousNode[$left], '-', 'BETWEEN ' . $node[$left] . ' AND ' . $node[$right]); $this->_sync($Model, $edge - $previousNode[$left] - ($node[$right] - $node[$left]), '-', '> ' . $edge); if (is_int($number)) { $number--; } if ($number) { $this->moveUp($Model, $id, $number); } return true; } /** * Recover a corrupted tree * * The mode parameter is used to specify the source of info that is valid/correct. The opposite source of data * will be populated based upon that source of info. E.g. if the MPTT fields are corrupt or empty, with the $mode * 'parent' the values of the parent_id field will be used to populate the left and right fields. The missingParentAction * parameter only applies to "parent" mode and determines what to do if the parent field contains an id that is not present. * * @param Model $Model Model using this behavior * @param string $mode parent or tree * @param string|int $missingParentAction 'return' to do nothing and return, 'delete' to * delete, or the id of the parent to set as the parent_id * @return bool true on success, false on failure * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::recover */ public function recover(Model $Model, $mode = 'parent', $missingParentAction = null) { if (is_array($mode)) { extract(array_merge(array('mode' => 'parent'), $mode)); } extract($this->settings[$Model->alias]); $Model->recursive = $recursive; if ($mode === 'parent') { $Model->bindModel(array('belongsTo' => array('VerifyParent' => array( 'className' => $Model->name, 'foreignKey' => $parent, 'fields' => array($Model->primaryKey, $left, $right, $parent), )))); $missingParents = $Model->find('list', array( 'recursive' => 0, 'conditions' => array($scope, array( 'NOT' => array($Model->escapeField($parent) => null), $Model->VerifyParent->escapeField() => null )), 'order' => false, )); $Model->unbindModel(array('belongsTo' => array('VerifyParent'))); if ($missingParents) { if ($missingParentAction === 'return') { foreach ($missingParents as $id => $display) { $this->errors[] = 'cannot find the parent for ' . $Model->alias . ' with id ' . $id . '(' . $display . ')'; } return false; } elseif ($missingParentAction === 'delete') { $Model->deleteAll(array($Model->escapeField($Model->primaryKey) => array_flip($missingParents)), false); } else { $Model->updateAll(array($Model->escapeField($parent) => $missingParentAction), array($Model->escapeField($Model->primaryKey) => array_flip($missingParents))); } } $this->_recoverByParentId($Model); } else { $db = ConnectionManager::getDataSource($Model->useDbConfig); foreach ($Model->find('all', array('conditions' => $scope, 'fields' => array($Model->primaryKey, $parent), 'order' => $left)) as $array) { $path = $this->getPath($Model, $array[$Model->alias][$Model->primaryKey]); $parentId = null; if (count($path) > 1) { $parentId = $path[count($path) - 2][$Model->alias][$Model->primaryKey]; } $Model->updateAll(array($parent => $db->value($parentId, $parent)), array($Model->escapeField() => $array[$Model->alias][$Model->primaryKey])); } } return true; } /** * _recoverByParentId * * Recursive helper function used by recover * * @param Model $Model Model instance. * @param int $counter Counter * @param mixed $parentId Parent record Id * @return int counter */ protected function _recoverByParentId(Model $Model, $counter = 1, $parentId = null) { $params = array( 'conditions' => array( $this->settings[$Model->alias]['parent'] => $parentId ), 'fields' => array($Model->primaryKey), 'page' => 1, 'limit' => 100, 'order' => array($Model->primaryKey) ); $scope = $this->settings[$Model->alias]['scope']; if ($scope && ($scope !== '1 = 1' && $scope !== true)) { $params['conditions'][] = $scope; } $children = $Model->find('all', $params); $hasChildren = (bool)$children; if ($parentId !== null) { if ($hasChildren) { $Model->updateAll( array($this->settings[$Model->alias]['left'] => $counter), array($Model->escapeField() => $parentId) ); $counter++; } else { $Model->updateAll( array( $this->settings[$Model->alias]['left'] => $counter, $this->settings[$Model->alias]['right'] => $counter + 1 ), array($Model->escapeField() => $parentId) ); $counter += 2; } } while ($children) { foreach ($children as $row) { $counter = $this->_recoverByParentId($Model, $counter, $row[$Model->alias][$Model->primaryKey]); } if (count($children) !== $params['limit']) { break; } $params['page']++; $children = $Model->find('all', $params); } if ($parentId !== null && $hasChildren) { $Model->updateAll( array($this->settings[$Model->alias]['right'] => $counter), array($Model->escapeField() => $parentId) ); $counter++; } return $counter; } /** * Reorder method. * * Reorders the nodes (and child nodes) of the tree according to the field and direction specified in the parameters. * This method does not change the parent of any node. * * Requires a valid tree, by default it verifies the tree before beginning. * * Options: * * - 'id' id of record to use as top node for reordering * - 'field' Which field to use in reordering defaults to displayField * - 'order' Direction to order either DESC or ASC (defaults to ASC) * - 'verify' Whether or not to verify the tree before reorder. defaults to true. * * @param Model $Model Model using this behavior * @param array $options array of options to use in reordering. * @return bool true on success, false on failure * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::reorder */ public function reorder(Model $Model, $options = array()) { $options += array('id' => null, 'field' => $Model->displayField, 'order' => 'ASC', 'verify' => true); extract($options); if ($verify && !$this->verify($Model)) { return false; } $verify = false; extract($this->settings[$Model->alias]); $fields = array($Model->primaryKey, $field, $left, $right); $sort = $field . ' ' . $order; $nodes = $this->children($Model, $id, true, $fields, $sort, null, null, $recursive); $cacheQueries = $Model->cacheQueries; $Model->cacheQueries = false; if ($nodes) { foreach ($nodes as $node) { $id = $node[$Model->alias][$Model->primaryKey]; $this->moveDown($Model, $id, true); if ($node[$Model->alias][$left] != $node[$Model->alias][$right] - 1) { $this->reorder($Model, compact('id', 'field', 'order', 'verify')); } } } $Model->cacheQueries = $cacheQueries; return true; } /** * Remove the current node from the tree, and reparent all children up one level. * * If the parameter delete is false, the node will become a new top level node. Otherwise the node will be deleted * after the children are reparented. * * @param Model $Model Model using this behavior * @param int|string $id The ID of the record to remove * @param bool $delete whether to delete the node after reparenting children (if any) * @return bool true on success, false on failure * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::removeFromTree */ public function removeFromTree(Model $Model, $id = null, $delete = false) { if (is_array($id)) { extract(array_merge(array('id' => null), $id)); } extract($this->settings[$Model->alias]); list($node) = array_values($this->_getNode($Model, $id)); if ($node[$right] == $node[$left] + 1) { if ($delete) { return $Model->delete($id); } $Model->id = $id; return $Model->saveField($parent, null); } elseif ($node[$parent]) { list($parentNode) = array_values($this->_getNode($Model, $node[$parent])); } else { $parentNode[$right] = $node[$right] + 1; } $db = ConnectionManager::getDataSource($Model->useDbConfig); $Model->updateAll( array($parent => $db->value($node[$parent], $parent)), array($Model->escapeField($parent) => $node[$Model->primaryKey]) ); $this->_sync($Model, 1, '-', 'BETWEEN ' . ($node[$left] + 1) . ' AND ' . ($node[$right] - 1)); $this->_sync($Model, 2, '-', '> ' . ($node[$right])); $Model->id = $id; if ($delete) { $Model->updateAll( array( $Model->escapeField($left) => 0, $Model->escapeField($right) => 0, $Model->escapeField($parent) => null ), array($Model->escapeField() => $id) ); return $Model->delete($id); } $edge = $this->_getMax($Model, $scope, $right, $recursive); if ($node[$right] == $edge) { $edge = $edge - 2; } $Model->id = $id; return $Model->save( array($left => $edge + 1, $right => $edge + 2, $parent => null), array('callbacks' => false, 'validate' => false) ); } /** * Check if the current tree is valid. * * Returns true if the tree is valid otherwise an array of (type, incorrect left/right index, message) * * @param Model $Model Model using this behavior * @return mixed true if the tree is valid or empty, otherwise an array of (error type [index, node], * [incorrect left/right index,node id], message) * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::verify */ public function verify(Model $Model) { extract($this->settings[$Model->alias]); if (!$Model->find('count', array('conditions' => $scope))) { return true; } $min = $this->_getMin($Model, $scope, $left, $recursive); $edge = $this->_getMax($Model, $scope, $right, $recursive); $errors = array(); for ($i = $min; $i <= $edge; $i++) { $count = $Model->find('count', array('conditions' => array( $scope, 'OR' => array($Model->escapeField($left) => $i, $Model->escapeField($right) => $i) ))); if ($count != 1) { if (!$count) { $errors[] = array('index', $i, 'missing'); } else { $errors[] = array('index', $i, 'duplicate'); } } } $node = $Model->find('first', array( 'conditions' => array($scope, $Model->escapeField($right) . '< ' . $Model->escapeField($left)), 'order' => false, 'recursive' => 0 )); if ($node) { $errors[] = array('node', $node[$Model->alias][$Model->primaryKey], 'left greater than right.'); } $Model->bindModel(array('belongsTo' => array('VerifyParent' => array( 'className' => $Model->name, 'foreignKey' => $parent, 'fields' => array($Model->primaryKey, $left, $right, $parent) )))); $rows = $Model->find('all', array('conditions' => $scope, 'recursive' => 0)); foreach ($rows as $instance) { if ($instance[$Model->alias][$left] === null || $instance[$Model->alias][$right] === null) { $errors[] = array('node', $instance[$Model->alias][$Model->primaryKey], 'has invalid left or right values'); } elseif ($instance[$Model->alias][$left] == $instance[$Model->alias][$right]) { $errors[] = array('node', $instance[$Model->alias][$Model->primaryKey], 'left and right values identical'); } elseif ($instance[$Model->alias][$parent]) { if (!$instance['VerifyParent'][$Model->primaryKey]) { $errors[] = array('node', $instance[$Model->alias][$Model->primaryKey], 'The parent node ' . $instance[$Model->alias][$parent] . ' doesn\'t exist'); } elseif ($instance[$Model->alias][$left] < $instance['VerifyParent'][$left]) { $errors[] = array('node', $instance[$Model->alias][$Model->primaryKey], 'left less than parent (node ' . $instance['VerifyParent'][$Model->primaryKey] . ').'); } elseif ($instance[$Model->alias][$right] > $instance['VerifyParent'][$right]) { $errors[] = array('node', $instance[$Model->alias][$Model->primaryKey], 'right greater than parent (node ' . $instance['VerifyParent'][$Model->primaryKey] . ').'); } } elseif ($Model->find('count', array('conditions' => array($scope, $Model->escapeField($left) . ' <' => $instance[$Model->alias][$left], $Model->escapeField($right) . ' >' => $instance[$Model->alias][$right]), 'recursive' => 0))) { $errors[] = array('node', $instance[$Model->alias][$Model->primaryKey], 'The parent field is blank, but has a parent'); } } if ($errors) { return $errors; } return true; } /** * Returns the depth level of a node in the tree. * * @param Model $Model Model using this behavior * @param int|string $id The primary key for record to get the level of. * @return int|bool Integer of the level or false if the node does not exist. */ public function getLevel(Model $Model, $id = null) { if ($id === null) { $id = $Model->id; } $node = $Model->find('first', array( 'conditions' => array($Model->escapeField() => $id), 'order' => false, 'recursive' => -1 )); if (empty($node)) { return false; } extract($this->settings[$Model->alias]); return $Model->find('count', array( 'conditions' => array( $scope, $left . ' <' => $node[$Model->alias][$left], $right . ' >' => $node[$Model->alias][$right] ), 'order' => false, 'recursive' => -1 )); } /** * Sets the parent of the given node * * The force parameter is used to override the "don't change the parent to the current parent" logic in the event * of recovering a corrupted table, or creating new nodes. Otherwise it should always be false. In reality this * method could be private, since calling save with parent_id set also calls setParent * * @param Model $Model Model using this behavior * @param int|string $parentId Parent record Id * @param bool $created True if newly created record else false. * @return bool true on success, false on failure */ protected function _setParent(Model $Model, $parentId = null, $created = false) { extract($this->settings[$Model->alias]); list($node) = array_values($this->_getNode($Model, $Model->id)); $edge = $this->_getMax($Model, $scope, $right, $recursive, $created); if (empty($parentId)) { $this->_sync($Model, $edge - $node[$left] + 1, '+', 'BETWEEN ' . $node[$left] . ' AND ' . $node[$right], $created); $this->_sync($Model, $node[$right] - $node[$left] + 1, '-', '> ' . $node[$left], $created); } else { $values = $this->_getNode($Model, $parentId); if ($values === false) { return false; } $parentNode = array_values($values); if (empty($parentNode) || empty($parentNode[0])) { return false; } $parentNode = $parentNode[0]; if (($Model->id === $parentId)) { return false; } elseif (($node[$left] < $parentNode[$left]) && ($parentNode[$right] < $node[$right])) { return false; } if (empty($node[$left]) && empty($node[$right])) { $this->_sync($Model, 2, '+', '>= ' . $parentNode[$right], $created); $result = $Model->save( array($left => $parentNode[$right], $right => $parentNode[$right] + 1, $parent => $parentId), array('validate' => false, 'callbacks' => false) ); $Model->data = $result; } else { $this->_sync($Model, $edge - $node[$left] + 1, '+', 'BETWEEN ' . $node[$left] . ' AND ' . $node[$right], $created); $diff = $node[$right] - $node[$left] + 1; if ($node[$left] > $parentNode[$left]) { if ($node[$right] < $parentNode[$right]) { $this->_sync($Model, $diff, '-', 'BETWEEN ' . $node[$right] . ' AND ' . ($parentNode[$right] - 1), $created); $this->_sync($Model, $edge - $parentNode[$right] + $diff + 1, '-', '> ' . $edge, $created); } else { $this->_sync($Model, $diff, '+', 'BETWEEN ' . $parentNode[$right] . ' AND ' . $node[$right], $created); $this->_sync($Model, $edge - $parentNode[$right] + 1, '-', '> ' . $edge, $created); } } else { $this->_sync($Model, $diff, '-', 'BETWEEN ' . $node[$right] . ' AND ' . ($parentNode[$right] - 1), $created); $this->_sync($Model, $edge - $parentNode[$right] + $diff + 1, '-', '> ' . $edge, $created); } } } return true; } /** * get the maximum index value in the table. * * @param Model $Model Model Instance. * @param string $scope Scoping conditions. * @param string $right Right value * @param int $recursive Recursive find value. * @param bool $created Whether it's a new record. * @return int */ protected function _getMax(Model $Model, $scope, $right, $recursive = -1, $created = false) { $db = ConnectionManager::getDataSource($Model->useDbConfig); if ($created) { if (is_string($scope)) { $scope .= " AND " . $Model->escapeField() . " <> "; $scope .= $db->value($Model->id, $Model->getColumnType($Model->primaryKey)); } else { $scope['NOT'][$Model->alias . '.' . $Model->primaryKey] = $Model->id; } } $name = $Model->escapeField($right); list($edge) = array_values($Model->find('first', array( 'conditions' => $scope, 'fields' => $db->calculate($Model, 'max', array($name, $right)), 'recursive' => $recursive, 'order' => false, 'callbacks' => false ))); return (empty($edge[$right])) ? 0 : $edge[$right]; } /** * get the minimum index value in the table. * * @param Model $Model Model instance. * @param string $scope Scoping conditions. * @param string $left Left value. * @param int $recursive Recurursive find value. * @return int */ protected function _getMin(Model $Model, $scope, $left, $recursive = -1) { $db = ConnectionManager::getDataSource($Model->useDbConfig); $name = $Model->escapeField($left); list($edge) = array_values($Model->find('first', array( 'conditions' => $scope, 'fields' => $db->calculate($Model, 'min', array($name, $left)), 'recursive' => $recursive, 'order' => false, 'callbacks' => false ))); return (empty($edge[$left])) ? 0 : $edge[$left]; } /** * Table sync method. * * Handles table sync operations, Taking account of the behavior scope. * * @param Model $Model Model instance. * @param int $shift Shift by. * @param string $dir Direction. * @param array $conditions Conditions. * @param bool $created Whether it's a new record. * @param string $field Field type. * @return void */ protected function _sync(Model $Model, $shift, $dir = '+', $conditions = array(), $created = false, $field = 'both') { $ModelRecursive = $Model->recursive; extract($this->settings[$Model->alias]); $Model->recursive = $recursive; if ($field === 'both') { $this->_sync($Model, $shift, $dir, $conditions, $created, $left); $field = $right; } if (is_string($conditions)) { $conditions = array($Model->escapeField($field) . " {$conditions}"); } if (($scope !== '1 = 1' && $scope !== true) && $scope) { $conditions[] = $scope; } if ($created) { $conditions['NOT'][$Model->escapeField()] = $Model->id; } $Model->updateAll(array($Model->escapeField($field) => $Model->escapeField($field) . ' ' . $dir . ' ' . $shift), $conditions); $Model->recursive = $ModelRecursive; } } cakephp-2.8.0/lib/Cake/Model/BehaviorCollection.php000066400000000000000000000212611265552240500221010ustar00rootroot00000000000000modelName = $modelName; if (!empty($behaviors)) { foreach (BehaviorCollection::normalizeObjectArray($behaviors) as $config) { $this->load($config['class'], $config['settings']); } } } /** * Backwards compatible alias for load() * * @param string $behavior Behavior name. * @param array $config Configuration options. * @return void * @deprecated 3.0.0 Will be removed in 3.0. Replaced with load(). */ public function attach($behavior, $config = array()) { return $this->load($behavior, $config); } /** * Loads a behavior into the collection. You can use use `$config['enabled'] = false` * to load a behavior with callbacks disabled. By default callbacks are enabled. Disable behaviors * can still be used as normal. * * You can alias your behavior as an existing behavior by setting the 'className' key, i.e., * ``` * public $actsAs = array( * 'Tree' => array( * 'className' => 'AliasedTree' * ); * ); * ``` * All calls to the `Tree` behavior would use `AliasedTree` instead. * * @param string $behavior CamelCased name of the behavior to load * @param array $config Behavior configuration parameters * @return bool True on success, false on failure * @throws MissingBehaviorException when a behavior could not be found. */ public function load($behavior, $config = array()) { if (isset($config['className'])) { $alias = $behavior; $behavior = $config['className']; } $configDisabled = isset($config['enabled']) && $config['enabled'] === false; $priority = isset($config['priority']) ? $config['priority'] : $this->defaultPriority; unset($config['enabled'], $config['className'], $config['priority']); list($plugin, $name) = pluginSplit($behavior, true); if (!isset($alias)) { $alias = $name; } $class = $name . 'Behavior'; App::uses($class, $plugin . 'Model/Behavior'); if (!class_exists($class)) { throw new MissingBehaviorException(array( 'class' => $class, 'plugin' => substr($plugin, 0, -1) )); } if (!isset($this->{$alias})) { if (ClassRegistry::isKeySet($class)) { $this->_loaded[$alias] = ClassRegistry::getObject($class); } else { $this->_loaded[$alias] = new $class(); ClassRegistry::addObject($class, $this->_loaded[$alias]); } } elseif (isset($this->_loaded[$alias]->settings) && isset($this->_loaded[$alias]->settings[$this->modelName])) { if ($config !== null && $config !== false) { $config = array_merge($this->_loaded[$alias]->settings[$this->modelName], $config); } else { $config = array(); } } if (empty($config)) { $config = array(); } $this->_loaded[$alias]->settings['priority'] = $priority; $this->_loaded[$alias]->setup(ClassRegistry::getObject($this->modelName), $config); foreach ($this->_loaded[$alias]->mapMethods as $method => $methodAlias) { $this->_mappedMethods[$method] = array($alias, $methodAlias); } $methods = get_class_methods($this->_loaded[$alias]); $parentMethods = array_flip(get_class_methods('ModelBehavior')); $callbacks = array( 'setup', 'cleanup', 'beforeFind', 'afterFind', 'beforeSave', 'afterSave', 'beforeDelete', 'afterDelete', 'onError' ); foreach ($methods as $m) { if (!isset($parentMethods[$m])) { $methodAllowed = ( $m[0] !== '_' && !array_key_exists($m, $this->_methods) && !in_array($m, $callbacks) ); if ($methodAllowed) { $this->_methods[$m] = array($alias, $m); } } } if ($configDisabled) { $this->disable($alias); } elseif (!$this->enabled($alias)) { $this->enable($alias); } else { $this->setPriority($alias, $priority); } return true; } /** * Detaches a behavior from a model * * @param string $name CamelCased name of the behavior to unload * @return void */ public function unload($name) { list(, $name) = pluginSplit($name); if (isset($this->_loaded[$name])) { $this->_loaded[$name]->cleanup(ClassRegistry::getObject($this->modelName)); parent::unload($name); } foreach ($this->_methods as $m => $callback) { if (is_array($callback) && $callback[0] === $name) { unset($this->_methods[$m]); } } } /** * Backwards compatible alias for unload() * * @param string $name Name of behavior * @return void * @deprecated 3.0.0 Will be removed in 3.0. Use unload instead. */ public function detach($name) { return $this->unload($name); } /** * Dispatches a behavior method. Will call either normal methods or mapped methods. * * If a method is not handled by the BehaviorCollection, and $strict is false, a * special return of `array('unhandled')` will be returned to signal the method was not found. * * @param Model $model The model the method was originally called on. * @param string $method The method called. * @param array $params Parameters for the called method. * @param bool $strict If methods are not found, trigger an error. * @return array All methods for all behaviors attached to this object */ public function dispatchMethod($model, $method, $params = array(), $strict = false) { $method = $this->hasMethod($method, true); if ($strict && empty($method)) { trigger_error(__d('cake_dev', '%s - Method %s not found in any attached behavior', 'BehaviorCollection::dispatchMethod()', $method), E_USER_WARNING); return null; } if (empty($method)) { return array('unhandled'); } if (count($method) === 3) { array_unshift($params, $method[2]); unset($method[2]); } return call_user_func_array( array($this->_loaded[$method[0]], $method[1]), array_merge(array(&$model), $params) ); } /** * Gets the method list for attached behaviors, i.e. all public, non-callback methods. * This does not include mappedMethods. * * @return array All public methods for all behaviors attached to this collection */ public function methods() { return $this->_methods; } /** * Check to see if a behavior in this collection implements the provided method. Will * also check mappedMethods. * * @param string $method The method to find. * @param bool $callback Return the callback for the method. * @return mixed If $callback is false, a boolean will be returned, if its true, an array * containing callback information will be returned. For mapped methods the array will have 3 elements. */ public function hasMethod($method, $callback = false) { if (isset($this->_methods[$method])) { return $callback ? $this->_methods[$method] : true; } foreach ($this->_mappedMethods as $pattern => $target) { if (preg_match($pattern . 'i', $method)) { if ($callback) { $target[] = $method; return $target; } return true; } } return false; } /** * Returns the implemented events that will get routed to the trigger function * in order to dispatch them separately on each behavior * * @return array */ public function implementedEvents() { return array( 'Model.beforeFind' => 'trigger', 'Model.afterFind' => 'trigger', 'Model.beforeValidate' => 'trigger', 'Model.afterValidate' => 'trigger', 'Model.beforeSave' => 'trigger', 'Model.afterSave' => 'trigger', 'Model.beforeDelete' => 'trigger', 'Model.afterDelete' => 'trigger' ); } } cakephp-2.8.0/lib/Cake/Model/CakeSchema.php000066400000000000000000000462741265552240500203250ustar00rootroot00000000000000name = preg_replace('/schema$/i', '', get_class($this)); } if (!empty($options['plugin'])) { $this->plugin = $options['plugin']; } if (strtolower($this->name) === 'cake') { $this->name = 'App'; } if (empty($options['path'])) { $this->path = APP . 'Config' . DS . 'Schema'; } $options = array_merge(get_object_vars($this), $options); $this->build($options); } /** * Builds schema object properties. * * @param array $data Loaded object properties. * @return void */ public function build($data) { $file = null; foreach ($data as $key => $val) { if (!empty($val)) { if (!in_array($key, array('plugin', 'name', 'path', 'file', 'connection', 'tables', '_log'))) { if ($key[0] === '_') { continue; } $this->tables[$key] = $val; unset($this->{$key}); } elseif ($key !== 'tables') { if ($key === 'name' && $val !== $this->name && !isset($data['file'])) { $file = Inflector::underscore($val) . '.php'; } $this->{$key} = $val; } } } if (file_exists($this->path . DS . $file) && is_file($this->path . DS . $file)) { $this->file = $file; } elseif (!empty($this->plugin)) { $this->path = CakePlugin::path($this->plugin) . 'Config' . DS . 'Schema'; } } /** * Before callback to be implemented in subclasses. * * @param array $event Schema object properties. * @return bool Should process continue. */ public function before($event = array()) { return true; } /** * After callback to be implemented in subclasses. * * @param array $event Schema object properties. * @return void */ public function after($event = array()) { } /** * Reads database and creates schema tables. * * @param array $options Schema object properties. * @return array Set of name and tables. */ public function load($options = array()) { if (is_string($options)) { $options = array('path' => $options); } $this->build($options); extract(get_object_vars($this)); $class = $name . 'Schema'; if (!class_exists($class) && !$this->_requireFile($path, $file)) { $class = Inflector::camelize(Inflector::slug(Configure::read('App.dir'))) . 'Schema'; if (!class_exists($class)) { $this->_requireFile($path, $file); } } if (class_exists($class)) { $Schema = new $class($options); return $Schema; } return false; } /** * Reads database and creates schema tables. * * Options * * - 'connection' - the db connection to use * - 'name' - name of the schema * - 'models' - a list of models to use, or false to ignore models * * @param array $options Schema object properties. * @return array Array indexed by name and tables. */ public function read($options = array()) { extract(array_merge( array( 'connection' => $this->connection, 'name' => $this->name, 'models' => true, ), $options )); $db = ConnectionManager::getDataSource($connection); if (isset($this->plugin)) { App::uses($this->plugin . 'AppModel', $this->plugin . '.Model'); } $tables = array(); $currentTables = (array)$db->listSources(); $prefix = null; if (isset($db->config['prefix'])) { $prefix = $db->config['prefix']; } if (!is_array($models) && $models !== false) { if (isset($this->plugin)) { $models = App::objects($this->plugin . '.Model', null, false); } else { $models = App::objects('Model'); } } if (is_array($models)) { foreach ($models as $model) { $importModel = $model; $plugin = null; if ($model === 'AppModel') { continue; } if (isset($this->plugin)) { if ($model === $this->plugin . 'AppModel') { continue; } $importModel = $model; $plugin = $this->plugin . '.'; } App::uses($importModel, $plugin . 'Model'); if (!class_exists($importModel)) { continue; } $vars = get_class_vars($model); if (empty($vars['useDbConfig']) || $vars['useDbConfig'] != $connection) { continue; } try { $Object = ClassRegistry::init(array('class' => $model, 'ds' => $connection)); } catch (CakeException $e) { continue; } if (!is_object($Object) || $Object->useTable === false) { continue; } $db = $Object->getDataSource(); $fulltable = $table = $db->fullTableName($Object, false, false); if ($prefix && strpos($table, $prefix) !== 0) { continue; } if (!in_array($fulltable, $currentTables)) { continue; } $table = $this->_noPrefixTable($prefix, $table); $key = array_search($fulltable, $currentTables); if (empty($tables[$table])) { $tables[$table] = $this->_columns($Object); $tables[$table]['indexes'] = $db->index($Object); $tables[$table]['tableParameters'] = $db->readTableParameters($fulltable); unset($currentTables[$key]); } if (empty($Object->hasAndBelongsToMany)) { continue; } foreach ($Object->hasAndBelongsToMany as $assocData) { if (isset($assocData['with'])) { $class = $assocData['with']; } if (!is_object($Object->$class)) { continue; } $withTable = $db->fullTableName($Object->$class, false, false); if ($prefix && strpos($withTable, $prefix) !== 0) { continue; } if (in_array($withTable, $currentTables)) { $key = array_search($withTable, $currentTables); $noPrefixWith = $this->_noPrefixTable($prefix, $withTable); $tables[$noPrefixWith] = $this->_columns($Object->$class); $tables[$noPrefixWith]['indexes'] = $db->index($Object->$class); $tables[$noPrefixWith]['tableParameters'] = $db->readTableParameters($withTable); unset($currentTables[$key]); } } } } if (!empty($currentTables)) { foreach ($currentTables as $table) { if ($prefix) { if (strpos($table, $prefix) !== 0) { continue; } $table = $this->_noPrefixTable($prefix, $table); } $Object = new AppModel(array( 'name' => Inflector::classify($table), 'table' => $table, 'ds' => $connection )); $systemTables = array( 'aros', 'acos', 'aros_acos', Configure::read('Session.table'), 'i18n' ); $fulltable = $db->fullTableName($Object, false, false); if (in_array($table, $systemTables)) { $tables[$Object->table] = $this->_columns($Object); $tables[$Object->table]['indexes'] = $db->index($Object); $tables[$Object->table]['tableParameters'] = $db->readTableParameters($fulltable); } elseif ($models === false) { $tables[$table] = $this->_columns($Object); $tables[$table]['indexes'] = $db->index($Object); $tables[$table]['tableParameters'] = $db->readTableParameters($fulltable); } else { $tables['missing'][$table] = $this->_columns($Object); $tables['missing'][$table]['indexes'] = $db->index($Object); $tables['missing'][$table]['tableParameters'] = $db->readTableParameters($fulltable); } } } ksort($tables); return compact('name', 'tables'); } /** * Writes schema file from object or options. * * @param array|object $object Schema object or options array. * @param array $options Schema object properties to override object. * @return mixed False or string written to file. */ public function write($object, $options = array()) { if (is_object($object)) { $object = get_object_vars($object); $this->build($object); } if (is_array($object)) { $options = $object; unset($object); } extract(array_merge( get_object_vars($this), $options )); $out = "class {$name}Schema extends CakeSchema {\n\n"; if ($path !== $this->path) { $out .= "\tpublic \$path = '{$path}';\n\n"; } if ($file !== $this->file) { $out .= "\tpublic \$file = '{$file}';\n\n"; } if ($connection !== 'default') { $out .= "\tpublic \$connection = '{$connection}';\n\n"; } $out .= "\tpublic function before(\$event = array()) {\n\t\treturn true;\n\t}\n\n\tpublic function after(\$event = array()) {\n\t}\n\n"; if (empty($tables)) { $this->read(); } foreach ($tables as $table => $fields) { if (!is_numeric($table) && $table !== 'missing') { $out .= $this->generateTable($table, $fields); } } $out .= "}\n"; $file = new File($path . DS . $file, true); $content = "write($content)) { return $content; } return false; } /** * Generate the schema code for a table. * * Takes a table name and $fields array and returns a completed, * escaped variable declaration to be used in schema classes. * * @param string $table Table name you want returned. * @param array $fields Array of field information to generate the table with. * @return string Variable declaration for a schema class. */ public function generateTable($table, $fields) { $out = "\tpublic \${$table} = array(\n"; if (is_array($fields)) { $cols = array(); foreach ($fields as $field => $value) { if ($field !== 'indexes' && $field !== 'tableParameters') { if (is_string($value)) { $type = $value; $value = array('type' => $type); } $col = "\t\t'{$field}' => array('type' => '" . $value['type'] . "', "; unset($value['type']); $col .= implode(', ', $this->_values($value)); } elseif ($field === 'indexes') { $col = "\t\t'indexes' => array(\n\t\t\t"; $props = array(); foreach ((array)$value as $key => $index) { $props[] = "'{$key}' => array(" . implode(', ', $this->_values($index)) . ")"; } $col .= implode(",\n\t\t\t", $props) . "\n\t\t"; } elseif ($field === 'tableParameters') { $col = "\t\t'tableParameters' => array("; $props = $this->_values($value); $col .= implode(', ', $props); } $col .= ")"; $cols[] = $col; } $out .= implode(",\n", $cols); } $out .= "\n\t);\n\n"; return $out; } /** * Compares two sets of schemas. * * @param array|object $old Schema object or array. * @param array|object $new Schema object or array. * @return array Tables (that are added, dropped, or changed.) */ public function compare($old, $new = null) { if (empty($new)) { $new = $this; } if (is_array($new)) { if (isset($new['tables'])) { $new = $new['tables']; } } else { $new = $new->tables; } if (is_array($old)) { if (isset($old['tables'])) { $old = $old['tables']; } } else { $old = $old->tables; } $tables = array(); foreach ($new as $table => $fields) { if ($table === 'missing') { continue; } if (!array_key_exists($table, $old)) { $tables[$table]['create'] = $fields; } else { $diff = $this->_arrayDiffAssoc($fields, $old[$table]); if (!empty($diff)) { $tables[$table]['add'] = $diff; } $diff = $this->_arrayDiffAssoc($old[$table], $fields); if (!empty($diff)) { $tables[$table]['drop'] = $diff; } } foreach ($fields as $field => $value) { if (!empty($old[$table][$field])) { $diff = $this->_arrayDiffAssoc($value, $old[$table][$field]); if (!empty($diff) && $field !== 'indexes' && $field !== 'tableParameters') { $tables[$table]['change'][$field] = $value; } } if (isset($tables[$table]['add'][$field]) && $field !== 'indexes' && $field !== 'tableParameters') { $wrapper = array_keys($fields); if ($column = array_search($field, $wrapper)) { if (isset($wrapper[$column - 1])) { $tables[$table]['add'][$field]['after'] = $wrapper[$column - 1]; } } } } if (isset($old[$table]['indexes']) && isset($new[$table]['indexes'])) { $diff = $this->_compareIndexes($new[$table]['indexes'], $old[$table]['indexes']); if ($diff) { if (!isset($tables[$table])) { $tables[$table] = array(); } if (isset($diff['drop'])) { $tables[$table]['drop']['indexes'] = $diff['drop']; } if ($diff && isset($diff['add'])) { $tables[$table]['add']['indexes'] = $diff['add']; } } } if (isset($old[$table]['tableParameters']) && isset($new[$table]['tableParameters'])) { $diff = $this->_compareTableParameters($new[$table]['tableParameters'], $old[$table]['tableParameters']); if ($diff) { $tables[$table]['change']['tableParameters'] = $diff; } } } return $tables; } /** * Extended array_diff_assoc noticing change from/to NULL values. * * It behaves almost the same way as array_diff_assoc except for NULL values: if * one of the values is not NULL - change is detected. It is useful in situation * where one value is strval('') ant other is strval(null) - in string comparing * methods this results as EQUAL, while it is not. * * @param array $array1 Base array. * @param array $array2 Corresponding array checked for equality. * @return array Difference as array with array(keys => values) from input array * where match was not found. */ protected function _arrayDiffAssoc($array1, $array2) { $difference = array(); foreach ($array1 as $key => $value) { if (!array_key_exists($key, $array2)) { $difference[$key] = $value; continue; } $correspondingValue = $array2[$key]; if (($value === null) !== ($correspondingValue === null)) { $difference[$key] = $value; continue; } if (is_bool($value) !== is_bool($correspondingValue)) { $difference[$key] = $value; continue; } if (is_array($value) && is_array($correspondingValue)) { continue; } if ($value === $correspondingValue) { continue; } $difference[$key] = $value; } return $difference; } /** * Formats Schema columns from Model Object. * * @param array $values Options keys(type, null, default, key, length, extra). * @return array Formatted values. */ protected function _values($values) { $vals = array(); if (is_array($values)) { foreach ($values as $key => $val) { if (is_array($val)) { $vals[] = "'{$key}' => array(" . implode(", ", $this->_values($val)) . ")"; } else { $val = var_export($val, true); if ($val === 'NULL') { $val = 'null'; } if (!is_numeric($key)) { $vals[] = "'{$key}' => {$val}"; } else { $vals[] = "{$val}"; } } } } return $vals; } /** * Formats Schema columns from Model Object. * * @param array &$Obj model object. * @return array Formatted columns. */ protected function _columns(&$Obj) { $db = $Obj->getDataSource(); $fields = $Obj->schema(true); $columns = array(); foreach ($fields as $name => $value) { if ($Obj->primaryKey === $name) { $value['key'] = 'primary'; } if (!isset($db->columns[$value['type']])) { trigger_error(__d('cake_dev', 'Schema generation error: invalid column type %s for %s.%s does not exist in DBO', $value['type'], $Obj->name, $name), E_USER_NOTICE); continue; } else { $defaultCol = $db->columns[$value['type']]; if (isset($defaultCol['limit']) && $defaultCol['limit'] == $value['length']) { unset($value['length']); } elseif (isset($defaultCol['length']) && $defaultCol['length'] == $value['length']) { unset($value['length']); } unset($value['limit']); } if (isset($value['default']) && ($value['default'] === '' || ($value['default'] === false && $value['type'] !== 'boolean'))) { unset($value['default']); } if (empty($value['length'])) { unset($value['length']); } if (empty($value['key'])) { unset($value['key']); } $columns[$name] = $value; } return $columns; } /** * Compare two schema files table Parameters. * * @param array $new New indexes. * @param array $old Old indexes. * @return mixed False on failure, or an array of parameters to add & drop. */ protected function _compareTableParameters($new, $old) { if (!is_array($new) || !is_array($old)) { return false; } $change = $this->_arrayDiffAssoc($new, $old); return $change; } /** * Compare two schema indexes. * * @param array $new New indexes. * @param array $old Old indexes. * @return mixed False on failure or array of indexes to add and drop. */ protected function _compareIndexes($new, $old) { if (!is_array($new) || !is_array($old)) { return false; } $add = $drop = array(); $diff = $this->_arrayDiffAssoc($new, $old); if (!empty($diff)) { $add = $diff; } $diff = $this->_arrayDiffAssoc($old, $new); if (!empty($diff)) { $drop = $diff; } foreach ($new as $name => $value) { if (isset($old[$name])) { $newUnique = isset($value['unique']) ? $value['unique'] : 0; $oldUnique = isset($old[$name]['unique']) ? $old[$name]['unique'] : 0; $newColumn = $value['column']; $oldColumn = $old[$name]['column']; $diff = false; if ($newUnique != $oldUnique) { $diff = true; } elseif (is_array($newColumn) && is_array($oldColumn)) { $diff = ($newColumn !== $oldColumn); } elseif (is_string($newColumn) && is_string($oldColumn)) { $diff = ($newColumn != $oldColumn); } else { $diff = true; } if ($diff) { $drop[$name] = null; $add[$name] = $value; } } } return array_filter(compact('add', 'drop')); } /** * Trim the table prefix from the full table name, and return the prefix-less * table. * * @param string $prefix Table prefix. * @param string $table Full table name. * @return string Prefix-less table name. */ protected function _noPrefixTable($prefix, $table) { return preg_replace('/^' . preg_quote($prefix) . '/', '', $table); } /** * Attempts to require the schema file specified. * * @param string $path Filesystem path to the file. * @param string $file Filesystem basename of the file. * @return bool True when a file was successfully included, false on failure. */ protected function _requireFile($path, $file) { if (file_exists($path . DS . $file) && is_file($path . DS . $file)) { require_once $path . DS . $file; return true; } elseif (file_exists($path . DS . 'schema.php') && is_file($path . DS . 'schema.php')) { require_once $path . DS . 'schema.php'; return true; } return false; } } cakephp-2.8.0/lib/Cake/Model/ConnectionManager.php000066400000000000000000000166011265552240500217220ustar00rootroot00000000000000 $class, 'plugin' => null, 'message' => 'Datasource is not found in Model/Datasource package.' )); } static::$_dataSources[$name] = new $class(static::$config->{$name}); static::$_dataSources[$name]->configKeyName = $name; return static::$_dataSources[$name]; } /** * Gets the list of available DataSource connections * This will only return the datasources instantiated by this manager * It differs from enumConnectionObjects, since the latter will return all configured connections * * @return array List of available connections */ public static function sourceList() { if (empty(static::$_init)) { static::_init(); } return array_keys(static::$_dataSources); } /** * Gets a DataSource name from an object reference. * * @param DataSource $source DataSource object * @return string|null Datasource name, or null if source is not present * in the ConnectionManager. */ public static function getSourceName($source) { if (empty(static::$_init)) { static::_init(); } foreach (static::$_dataSources as $name => $ds) { if ($ds === $source) { return $name; } } return null; } /** * Loads the DataSource class for the given connection name * * @param string|array $connName A string name of the connection, as defined in app/Config/database.php, * or an array containing the filename (without extension) and class name of the object, * to be found in app/Model/Datasource/ or lib/Cake/Model/Datasource/. * @return bool True on success, null on failure or false if the class is already loaded * @throws MissingDatasourceException */ public static function loadDataSource($connName) { if (empty(static::$_init)) { static::_init(); } if (is_array($connName)) { $conn = $connName; } else { $conn = static::$_connectionsEnum[$connName]; } if (class_exists($conn['classname'], false)) { return false; } $plugin = $package = null; if (!empty($conn['plugin'])) { $plugin = $conn['plugin'] . '.'; } if (!empty($conn['package'])) { $package = '/' . $conn['package']; } App::uses($conn['classname'], $plugin . 'Model/Datasource' . $package); if (!class_exists($conn['classname'])) { throw new MissingDatasourceException(array( 'class' => $conn['classname'], 'plugin' => substr($plugin, 0, -1) )); } return true; } /** * Returns a list of connections * * @return array An associative array of elements where the key is the connection name * (as defined in Connections), and the value is an array with keys 'filename' and 'classname'. */ public static function enumConnectionObjects() { if (empty(static::$_init)) { static::_init(); } return (array)static::$config; } /** * Dynamically creates a DataSource object at runtime, with the given name and settings * * @param string $name The DataSource name * @param array $config The DataSource configuration settings * @return DataSource|null A reference to the DataSource object, or null if creation failed */ public static function create($name = '', $config = array()) { if (empty(static::$_init)) { static::_init(); } if (empty($name) || empty($config) || array_key_exists($name, static::$_connectionsEnum)) { return null; } static::$config->{$name} = $config; static::$_connectionsEnum[$name] = static::_connectionData($config); $return = static::getDataSource($name); return $return; } /** * Removes a connection configuration at runtime given its name * * @param string $name the connection name as it was created * @return bool success if connection was removed, false if it does not exist */ public static function drop($name) { if (empty(static::$_init)) { static::_init(); } if (!isset(static::$config->{$name})) { return false; } unset(static::$_connectionsEnum[$name], static::$_dataSources[$name], static::$config->{$name}); return true; } /** * Gets a list of class and file names associated with the user-defined DataSource connections * * @param string $name Connection name * @return void * @throws MissingDatasourceConfigException */ protected static function _getConnectionObject($name) { if (!empty(static::$config->{$name})) { static::$_connectionsEnum[$name] = static::_connectionData(static::$config->{$name}); } else { throw new MissingDatasourceConfigException(array('config' => $name)); } } /** * Returns the file, class name, and parent for the given driver. * * @param array $config Array with connection configuration. Key 'datasource' is required * @return array An indexed array with: filename, classname, plugin and parent */ protected static function _connectionData($config) { $package = $classname = $plugin = null; list($plugin, $classname) = pluginSplit($config['datasource']); if (strpos($classname, '/') !== false) { $package = dirname($classname); $classname = basename($classname); } return compact('package', 'classname', 'plugin'); } } cakephp-2.8.0/lib/Cake/Model/Datasource/000077500000000000000000000000001265552240500177055ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Model/Datasource/CakeSession.php000066400000000000000000000463161265552240500226370ustar00rootroot00000000000000 values * @param array $new New set of variable => value * @return void */ protected static function _overwrite(&$old, $new) { if (!empty($old)) { foreach ($old as $key => $var) { if (!isset($new[$key])) { unset($old[$key]); } } } foreach ($new as $key => $var) { $old[$key] = $var; } } /** * Return error description for given error number. * * @param int $errorNumber Error to set * @return string Error as string */ protected static function _error($errorNumber) { if (!is_array(static::$error) || !array_key_exists($errorNumber, static::$error)) { return false; } return static::$error[$errorNumber]; } /** * Returns last occurred error as a string, if any. * * @return mixed Error description as a string, or false. */ public static function error() { if (static::$lastError) { return static::_error(static::$lastError); } return false; } /** * Returns true if session is valid. * * @return bool Success */ public static function valid() { if (static::start() && static::read('Config')) { if (static::_validAgentAndTime() && static::$error === false) { static::$valid = true; } else { static::$valid = false; static::_setError(1, 'Session Highjacking Attempted !!!'); } } return static::$valid; } /** * Tests that the user agent is valid and that the session hasn't 'timed out'. * Since timeouts are implemented in CakeSession it checks the current static::$time * against the time the session is set to expire. The User agent is only checked * if Session.checkAgent == true. * * @return bool */ protected static function _validAgentAndTime() { $userAgent = static::read('Config.userAgent'); $time = static::read('Config.time'); $validAgent = ( Configure::read('Session.checkAgent') === false || isset($userAgent) && static::$_userAgent === $userAgent ); return ($validAgent && static::$time <= $time); } /** * Get / Set the user agent * * @param string|null $userAgent Set the user agent * @return string Current user agent. */ public static function userAgent($userAgent = null) { if ($userAgent) { static::$_userAgent = $userAgent; } if (empty(static::$_userAgent)) { CakeSession::init(static::$path); } return static::$_userAgent; } /** * Returns given session variable, or all of them, if no parameters given. * * @param string|null $name The name of the session variable (or a path as sent to Set.extract) * @return mixed The value of the session variable, null if session not available, * session not started, or provided name not found in the session, false on failure. */ public static function read($name = null) { if (empty($name) && $name !== null) { return null; } if (!static::_hasSession() || !static::start()) { return null; } if ($name === null) { return static::_returnSessionVars(); } $result = Hash::get($_SESSION, $name); if (isset($result)) { return $result; } return null; } /** * Returns all session variables. * * @return mixed Full $_SESSION array, or false on error. */ protected static function _returnSessionVars() { if (!empty($_SESSION)) { return $_SESSION; } static::_setError(2, 'No Session vars set'); return false; } /** * Writes value to given session variable name. * * @param string|array $name Name of variable * @param string $value Value to write * @return bool True if the write was successful, false if the write failed */ public static function write($name, $value = null) { if (empty($name) || !static::start()) { return false; } $write = $name; if (!is_array($name)) { $write = array($name => $value); } foreach ($write as $key => $val) { static::_overwrite($_SESSION, Hash::insert($_SESSION, $key, $val)); if (Hash::get($_SESSION, $key) !== $val) { return false; } } return true; } /** * Reads and deletes a variable from session. * * @param string $name The key to read and remove (or a path as sent to Hash.extract). * @return mixed The value of the session variable, null if session not available, * session not started, or provided name not found in the session. */ public static function consume($name) { if (empty($name)) { return null; } $value = static::read($name); if ($value !== null) { static::_overwrite($_SESSION, Hash::remove($_SESSION, $name)); } return $value; } /** * Helper method to destroy invalid sessions. * * @return void */ public static function destroy() { if (!static::started()) { static::_startSession(); } if (static::started()) { if (session_id() && static::_hasSession()) { session_write_close(); session_start(); } session_destroy(); unset($_COOKIE[static::_cookieName()]); } $_SESSION = null; static::$id = null; static::$_cookieName = null; } /** * Clears the session. * * Optionally also clears the session id and renews the session. * * @param bool $renew If the session should also be renewed. Defaults to true. * @return void */ public static function clear($renew = true) { if (!$renew) { $_SESSION = array(); return; } $_SESSION = null; static::$id = null; static::renew(); } /** * Helper method to initialize a session, based on CakePHP core settings. * * Sessions can be configured with a few shortcut names as well as have any number of ini settings declared. * * @return void * @throws CakeSessionException Throws exceptions when ini_set() fails. */ protected static function _configureSession() { $sessionConfig = Configure::read('Session'); if (isset($sessionConfig['defaults'])) { $defaults = static::_defaultConfig($sessionConfig['defaults']); if ($defaults) { $sessionConfig = Hash::merge($defaults, $sessionConfig); } } if (!isset($sessionConfig['ini']['session.cookie_secure']) && env('HTTPS')) { $sessionConfig['ini']['session.cookie_secure'] = 1; } if (isset($sessionConfig['timeout']) && !isset($sessionConfig['cookieTimeout'])) { $sessionConfig['cookieTimeout'] = $sessionConfig['timeout']; } if (!isset($sessionConfig['ini']['session.cookie_lifetime'])) { $sessionConfig['ini']['session.cookie_lifetime'] = $sessionConfig['cookieTimeout'] * 60; } if (!isset($sessionConfig['ini']['session.name'])) { $sessionConfig['ini']['session.name'] = $sessionConfig['cookie']; } static::$_cookieName = $sessionConfig['ini']['session.name']; if (!empty($sessionConfig['handler'])) { $sessionConfig['ini']['session.save_handler'] = 'user'; } elseif (!empty($sessionConfig['session.save_path']) && Configure::read('debug')) { if (!is_dir($sessionConfig['session.save_path'])) { mkdir($sessionConfig['session.save_path'], 0775, true); } } if (!isset($sessionConfig['ini']['session.gc_maxlifetime'])) { $sessionConfig['ini']['session.gc_maxlifetime'] = $sessionConfig['timeout'] * 60; } if (!isset($sessionConfig['ini']['session.cookie_httponly'])) { $sessionConfig['ini']['session.cookie_httponly'] = 1; } // For IE<=8 if (!isset($sessionConfig['cacheLimiter'])) { $sessionConfig['cacheLimiter'] = 'must-revalidate'; } if (empty($_SESSION)) { if (!empty($sessionConfig['ini']) && is_array($sessionConfig['ini'])) { foreach ($sessionConfig['ini'] as $setting => $value) { if (ini_set($setting, $value) === false) { throw new CakeSessionException(__d('cake_dev', 'Unable to configure the session, setting %s failed.', $setting)); } } } } if (!empty($sessionConfig['handler']) && !isset($sessionConfig['handler']['engine'])) { call_user_func_array('session_set_save_handler', $sessionConfig['handler']); } if (!empty($sessionConfig['handler']['engine'])) { $handler = static::_getHandler($sessionConfig['handler']['engine']); session_set_save_handler( array($handler, 'open'), array($handler, 'close'), array($handler, 'read'), array($handler, 'write'), array($handler, 'destroy'), array($handler, 'gc') ); } Configure::write('Session', $sessionConfig); static::$sessionTime = static::$time + ($sessionConfig['timeout'] * 60); } /** * Get session cookie name. * * @return string */ protected static function _cookieName() { if (static::$_cookieName !== null) { return static::$_cookieName; } static::init(); static::_configureSession(); return static::$_cookieName = session_name(); } /** * Returns whether a session exists * * @return bool */ protected static function _hasSession() { return static::started() || isset($_COOKIE[static::_cookieName()]) || (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg'); } /** * Find the handler class and make sure it implements the correct interface. * * @param string $handler Handler name. * @return void * @throws CakeSessionException */ protected static function _getHandler($handler) { list($plugin, $class) = pluginSplit($handler, true); App::uses($class, $plugin . 'Model/Datasource/Session'); if (!class_exists($class)) { throw new CakeSessionException(__d('cake_dev', 'Could not load %s to handle the session.', $class)); } $handler = new $class(); if ($handler instanceof CakeSessionHandlerInterface) { return $handler; } throw new CakeSessionException(__d('cake_dev', 'Chosen SessionHandler does not implement CakeSessionHandlerInterface it cannot be used with an engine key.')); } /** * Get one of the prebaked default session configurations. * * @param string $name Config name. * @return bool|array */ protected static function _defaultConfig($name) { $defaults = array( 'php' => array( 'cookie' => 'CAKEPHP', 'timeout' => 240, 'ini' => array( 'session.use_trans_sid' => 0, 'session.cookie_path' => static::$path ) ), 'cake' => array( 'cookie' => 'CAKEPHP', 'timeout' => 240, 'ini' => array( 'session.use_trans_sid' => 0, 'url_rewriter.tags' => '', 'session.serialize_handler' => 'php', 'session.use_cookies' => 1, 'session.cookie_path' => static::$path, 'session.save_path' => TMP . 'sessions', 'session.save_handler' => 'files' ) ), 'cache' => array( 'cookie' => 'CAKEPHP', 'timeout' => 240, 'ini' => array( 'session.use_trans_sid' => 0, 'url_rewriter.tags' => '', 'session.use_cookies' => 1, 'session.cookie_path' => static::$path, 'session.save_handler' => 'user', ), 'handler' => array( 'engine' => 'CacheSession', 'config' => 'default' ) ), 'database' => array( 'cookie' => 'CAKEPHP', 'timeout' => 240, 'ini' => array( 'session.use_trans_sid' => 0, 'url_rewriter.tags' => '', 'session.use_cookies' => 1, 'session.cookie_path' => static::$path, 'session.save_handler' => 'user', 'session.serialize_handler' => 'php', ), 'handler' => array( 'engine' => 'DatabaseSession', 'model' => 'Session' ) ) ); if (isset($defaults[$name])) { return $defaults[$name]; } return false; } /** * Helper method to start a session * * @return bool Success */ protected static function _startSession() { static::init(); session_write_close(); static::_configureSession(); if (headers_sent()) { if (empty($_SESSION)) { $_SESSION = array(); } } else { $limit = Configure::read('Session.cacheLimiter'); if (!empty($limit)) { session_cache_limiter($limit); } session_start(); } return true; } /** * Helper method to create a new session. * * @return void */ protected static function _checkValid() { $config = static::read('Config'); if ($config) { $sessionConfig = Configure::read('Session'); if (static::valid()) { static::write('Config.time', static::$sessionTime); if (isset($sessionConfig['autoRegenerate']) && $sessionConfig['autoRegenerate'] === true) { $check = $config['countdown']; $check -= 1; static::write('Config.countdown', $check); if ($check < 1) { static::renew(); static::write('Config.countdown', static::$requestCountdown); } } } else { $_SESSION = array(); static::destroy(); static::_setError(1, 'Session Highjacking Attempted !!!'); static::_startSession(); static::_writeConfig(); } } else { static::_writeConfig(); } } /** * Writes configuration variables to the session * * @return void */ protected static function _writeConfig() { static::write('Config.userAgent', static::$_userAgent); static::write('Config.time', static::$sessionTime); static::write('Config.countdown', static::$requestCountdown); } /** * Restarts this session. * * @return void */ public static function renew() { if (session_id() === '') { return; } if (isset($_COOKIE[static::_cookieName()])) { setcookie(Configure::read('Session.cookie'), '', time() - 42000, static::$path); } if (!headers_sent()) { session_write_close(); session_start(); session_regenerate_id(true); } } /** * Helper method to set an internal error message. * * @param int $errorNumber Number of the error * @param string $errorMessage Description of the error * @return void */ protected static function _setError($errorNumber, $errorMessage) { if (static::$error === false) { static::$error = array(); } static::$error[$errorNumber] = $errorMessage; static::$lastError = $errorNumber; } } cakephp-2.8.0/lib/Cake/Model/Datasource/DataSource.php000066400000000000000000000243651265552240500224620ustar00rootroot00000000000000setConfig($config); } /** * Caches/returns cached results for child instances * * @param mixed $data Unused in this class. * @return array|null Array of sources available in this datasource. */ public function listSources($data = null) { if ($this->cacheSources === false) { return null; } if ($this->_sources !== null) { return $this->_sources; } $key = ConnectionManager::getSourceName($this) . '_' . $this->config['database'] . '_list'; $key = preg_replace('/[^A-Za-z0-9_\-.+]/', '_', $key); $sources = Cache::read($key, '_cake_model_'); if (empty($sources)) { $sources = $data; Cache::write($key, $data, '_cake_model_'); } return $this->_sources = $sources; } /** * Returns a Model description (metadata) or null if none found. * * @param Model|string $model The model to describe. * @return array|null Array of Metadata for the $model */ public function describe($model) { if ($this->cacheSources === false) { return null; } if (is_string($model)) { $table = $model; } else { $table = $model->tablePrefix . $model->table; } if (isset($this->_descriptions[$table])) { return $this->_descriptions[$table]; } $cache = $this->_cacheDescription($table); if ($cache !== null) { $this->_descriptions[$table] =& $cache; return $cache; } return null; } /** * Begin a transaction * * @return bool Returns true if a transaction is not in progress */ public function begin() { return !$this->_transactionStarted; } /** * Commit a transaction * * @return bool Returns true if a transaction is in progress */ public function commit() { return $this->_transactionStarted; } /** * Rollback a transaction * * @return bool Returns true if a transaction is in progress */ public function rollback() { return $this->_transactionStarted; } /** * Converts column types to basic types * * @param string $real Real column type (i.e. "varchar(255)") * @return string Abstract column type (i.e. "string") */ public function column($real) { return false; } /** * Used to create new records. The "C" CRUD. * * To-be-overridden in subclasses. * * @param Model $Model The Model to be created. * @param array $fields An Array of fields to be saved. * @param array $values An Array of values to save. * @return bool success */ public function create(Model $Model, $fields = null, $values = null) { return false; } /** * Used to read records from the Datasource. The "R" in CRUD * * To-be-overridden in subclasses. * * @param Model $Model The model being read. * @param array $queryData An array of query data used to find the data you want * @param int $recursive Number of levels of association * @return mixed */ public function read(Model $Model, $queryData = array(), $recursive = null) { return false; } /** * Update a record(s) in the datasource. * * To-be-overridden in subclasses. * * @param Model $Model Instance of the model class being updated * @param array $fields Array of fields to be updated * @param array $values Array of values to be update $fields to. * @param mixed $conditions The array of conditions to use. * @return bool Success */ public function update(Model $Model, $fields = null, $values = null, $conditions = null) { return false; } /** * Delete a record(s) in the datasource. * * To-be-overridden in subclasses. * * @param Model $Model The model class having record(s) deleted * @param mixed $conditions The conditions to use for deleting. * @return bool Success */ public function delete(Model $Model, $conditions = null) { return false; } /** * Returns the ID generated from the previous INSERT operation. * * @param mixed $source The source name. * @return mixed Last ID key generated in previous INSERT */ public function lastInsertId($source = null) { return false; } /** * Returns the number of rows returned by last operation. * * @param mixed $source The source name. * @return int Number of rows returned by last operation */ public function lastNumRows($source = null) { return false; } /** * Returns the number of rows affected by last query. * * @param mixed $source The source name. * @return int Number of rows affected by last query. */ public function lastAffected($source = null) { return false; } /** * Check whether the conditions for the Datasource being available * are satisfied. Often used from connect() to check for support * before establishing a connection. * * @return bool Whether or not the Datasources conditions for use are met. */ public function enabled() { return true; } /** * Sets the configuration for the DataSource. * Merges the $config information with the _baseConfig and the existing $config property. * * @param array $config The configuration array * @return void */ public function setConfig($config = array()) { $this->config = array_merge($this->_baseConfig, $this->config, $config); } /** * Cache the DataSource description * * @param string $object The name of the object (model) to cache * @param mixed $data The description of the model, usually a string or array * @return mixed */ protected function _cacheDescription($object, $data = null) { if ($this->cacheSources === false) { return null; } if ($data !== null) { $this->_descriptions[$object] =& $data; } $key = ConnectionManager::getSourceName($this) . '_' . $object; $cache = Cache::read($key, '_cake_model_'); if (empty($cache)) { $cache = $data; Cache::write($key, $cache, '_cake_model_'); } return $cache; } /** * Replaces `{$__cakeID__$}` and `{$__cakeForeignKey__$}` placeholders in query data. * * @param string $query Query string needing replacements done. * @param array $data Array of data with values that will be inserted in placeholders. * @param string $association Name of association model being replaced. * @param Model $Model Model instance. * @param array $stack The context stack. * @return mixed String of query data with placeholders replaced, or false on failure. */ public function insertQueryData($query, $data, $association, Model $Model, $stack) { $keys = array('{$__cakeID__$}', '{$__cakeForeignKey__$}'); $modelAlias = $Model->alias; foreach ($keys as $key) { if (strpos($query, $key) === false) { continue; } $insertKey = $InsertModel = null; switch ($key) { case '{$__cakeID__$}': $InsertModel = $Model; $insertKey = $Model->primaryKey; break; case '{$__cakeForeignKey__$}': foreach ($Model->associations() as $type) { foreach ($Model->{$type} as $assoc => $assocData) { if ($assoc !== $association) { continue; } if (isset($assocData['foreignKey'])) { $InsertModel = $Model->{$assoc}; $insertKey = $assocData['foreignKey']; } break 3; } } break; } $val = $dataType = null; if (!empty($insertKey) && !empty($InsertModel)) { if (isset($data[$modelAlias][$insertKey])) { $val = $data[$modelAlias][$insertKey]; } elseif (isset($data[$association][$insertKey])) { $val = $data[$association][$insertKey]; } else { $found = false; foreach (array_reverse($stack) as $assocData) { if (isset($data[$assocData]) && isset($data[$assocData][$insertKey])) { $val = $data[$assocData][$insertKey]; $found = true; break; } } if (!$found) { $val = ''; } } $dataType = $InsertModel->getColumnType($InsertModel->primaryKey); } if (empty($val) && $val !== '0') { return false; } $query = str_replace($key, $this->value($val, $dataType), $query); } return $query; } /** * To-be-overridden in subclasses. * * @param Model $Model Model instance * @param string $key Key name to make * @return string Key name for model. */ public function resolveKey(Model $Model, $key) { return $Model->alias . $key; } /** * Returns the schema name. Override this in subclasses. * * @return string|null The schema name */ public function getSchemaName() { return null; } /** * Closes a connection. Override in subclasses. * * @return bool */ public function close() { return $this->connected = false; } /** * Closes the current datasource. */ public function __destruct() { if ($this->_transactionStarted) { $this->rollback(); } if ($this->connected) { $this->close(); } } } cakephp-2.8.0/lib/Cake/Model/Datasource/Database/000077500000000000000000000000001265552240500214115ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Model/Datasource/Database/Mysql.php000066400000000000000000000570421265552240500232370ustar00rootroot00000000000000 true, 'host' => 'localhost', 'login' => 'root', 'password' => '', 'database' => 'cake', 'port' => '3306', 'flags' => array() ); /** * Reference to the PDO object connection * * @var PDO */ protected $_connection = null; /** * Start quote * * @var string */ public $startQuote = "`"; /** * End quote * * @var string */ public $endQuote = "`"; /** * use alias for update and delete. Set to true if version >= 4.1 * * @var bool */ protected $_useAlias = true; /** * List of engine specific additional field parameters used on table creating * * @var array */ public $fieldParameters = array( 'charset' => array('value' => 'CHARACTER SET', 'quote' => false, 'join' => ' ', 'column' => false, 'position' => 'beforeDefault'), 'collate' => array('value' => 'COLLATE', 'quote' => false, 'join' => ' ', 'column' => 'Collation', 'position' => 'beforeDefault'), 'comment' => array('value' => 'COMMENT', 'quote' => true, 'join' => ' ', 'column' => 'Comment', 'position' => 'afterDefault'), 'unsigned' => array( 'value' => 'UNSIGNED', 'quote' => false, 'join' => ' ', 'column' => false, 'position' => 'beforeDefault', 'noVal' => true, 'options' => array(true), 'types' => array('integer', 'float', 'decimal', 'biginteger') ) ); /** * List of table engine specific parameters used on table creating * * @var array */ public $tableParameters = array( 'charset' => array('value' => 'DEFAULT CHARSET', 'quote' => false, 'join' => '=', 'column' => 'charset'), 'collate' => array('value' => 'COLLATE', 'quote' => false, 'join' => '=', 'column' => 'Collation'), 'engine' => array('value' => 'ENGINE', 'quote' => false, 'join' => '=', 'column' => 'Engine'), 'comment' => array('value' => 'COMMENT', 'quote' => true, 'join' => '=', 'column' => 'Comment'), ); /** * MySQL column definition * * @var array */ public $columns = array( 'primary_key' => array('name' => 'NOT NULL AUTO_INCREMENT'), 'string' => array('name' => 'varchar', 'limit' => '255'), 'text' => array('name' => 'text'), 'biginteger' => array('name' => 'bigint', 'limit' => '20'), 'integer' => array('name' => 'int', 'limit' => '11', 'formatter' => 'intval'), 'float' => array('name' => 'float', 'formatter' => 'floatval'), 'decimal' => array('name' => 'decimal', 'formatter' => 'floatval'), 'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'), 'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'), 'time' => array('name' => 'time', 'format' => 'H:i:s', 'formatter' => 'date'), 'date' => array('name' => 'date', 'format' => 'Y-m-d', 'formatter' => 'date'), 'binary' => array('name' => 'blob'), 'boolean' => array('name' => 'tinyint', 'limit' => '1') ); /** * Mapping of collation names to character set names * * @var array */ protected $_charsets = array(); /** * Connects to the database using options in the given configuration array. * * MySQL supports a few additional options that other drivers do not: * * - `unix_socket` Set to the path of the MySQL sock file. Can be used in place * of host + port. * - `ssl_key` SSL key file for connecting via SSL. Must be combined with `ssl_cert`. * - `ssl_cert` The SSL certificate to use when connecting via SSL. Must be * combined with `ssl_key`. * - `ssl_ca` The certificate authority for SSL connections. * * @return bool True if the database could be connected, else false * @throws MissingConnectionException */ public function connect() { $config = $this->config; $this->connected = false; $flags = $config['flags'] + array( PDO::ATTR_PERSISTENT => $config['persistent'], PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ); if (!empty($config['encoding'])) { $flags[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET NAMES ' . $config['encoding']; } if (!empty($config['ssl_key']) && !empty($config['ssl_cert'])) { $flags[PDO::MYSQL_ATTR_SSL_KEY] = $config['ssl_key']; $flags[PDO::MYSQL_ATTR_SSL_CERT] = $config['ssl_cert']; } if (!empty($config['ssl_ca'])) { $flags[PDO::MYSQL_ATTR_SSL_CA] = $config['ssl_ca']; } if (empty($config['unix_socket'])) { $dsn = "mysql:host={$config['host']};port={$config['port']};dbname={$config['database']}"; } else { $dsn = "mysql:unix_socket={$config['unix_socket']};dbname={$config['database']}"; } try { $this->_connection = new PDO( $dsn, $config['login'], $config['password'], $flags ); $this->connected = true; if (!empty($config['settings'])) { foreach ($config['settings'] as $key => $value) { $this->_execute("SET $key=$value"); } } } catch (PDOException $e) { throw new MissingConnectionException(array( 'class' => get_class($this), 'message' => $e->getMessage() )); } $this->_charsets = array(); $this->_useAlias = (bool)version_compare($this->getVersion(), "4.1", ">="); return $this->connected; } /** * Check whether the MySQL extension is installed/loaded * * @return bool */ public function enabled() { return in_array('mysql', PDO::getAvailableDrivers()); } /** * Returns an array of sources (tables) in the database. * * @param mixed $data List of tables. * @return array Array of table names in the database */ public function listSources($data = null) { $cache = parent::listSources(); if ($cache) { return $cache; } $result = $this->_execute('SHOW TABLES FROM ' . $this->name($this->config['database'])); if (!$result) { $result->closeCursor(); return array(); } $tables = array(); while ($line = $result->fetch(PDO::FETCH_NUM)) { $tables[] = $line[0]; } $result->closeCursor(); parent::listSources($tables); return $tables; } /** * Builds a map of the columns contained in a result * * @param PDOStatement $results The results to format. * @return void */ public function resultSet($results) { $this->map = array(); $numFields = $results->columnCount(); $index = 0; while ($numFields-- > 0) { $column = $results->getColumnMeta($index); if ($column['len'] === 1 && (empty($column['native_type']) || $column['native_type'] === 'TINY')) { $type = 'boolean'; } else { $type = empty($column['native_type']) ? 'string' : $column['native_type']; } if (!empty($column['table']) && strpos($column['name'], $this->virtualFieldSeparator) === false) { $this->map[$index++] = array($column['table'], $column['name'], $type); } else { $this->map[$index++] = array(0, $column['name'], $type); } } } /** * Fetches the next row from the current result set * * @return mixed array with results fetched and mapped to column names or false if there is no results left to fetch */ public function fetchResult() { if ($row = $this->_result->fetch(PDO::FETCH_NUM)) { $resultRow = array(); foreach ($this->map as $col => $meta) { list($table, $column, $type) = $meta; $resultRow[$table][$column] = $row[$col]; if ($type === 'boolean' && $row[$col] !== null) { $resultRow[$table][$column] = $this->boolean($resultRow[$table][$column]); } } return $resultRow; } $this->_result->closeCursor(); return false; } /** * Gets the database encoding * * @return string The database encoding */ public function getEncoding() { return $this->_execute('SHOW VARIABLES LIKE ?', array('character_set_client'))->fetchObject()->Value; } /** * Query charset by collation * * @param string $name Collation name * @return string Character set name */ public function getCharsetName($name) { if ((bool)version_compare($this->getVersion(), "5", "<")) { return false; } if (isset($this->_charsets[$name])) { return $this->_charsets[$name]; } $r = $this->_execute( 'SELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.COLLATIONS WHERE COLLATION_NAME = ?', array($name) ); $cols = $r->fetch(PDO::FETCH_ASSOC); if (isset($cols['CHARACTER_SET_NAME'])) { $this->_charsets[$name] = $cols['CHARACTER_SET_NAME']; } else { $this->_charsets[$name] = false; } return $this->_charsets[$name]; } /** * Returns an array of the fields in given table name. * * @param Model|string $model Name of database table to inspect or model instance * @return array Fields in table. Keys are name and type * @throws CakeException */ public function describe($model) { $key = $this->fullTableName($model, false); $cache = parent::describe($key); if ($cache) { return $cache; } $table = $this->fullTableName($model); $fields = false; $cols = $this->_execute('SHOW FULL COLUMNS FROM ' . $table); if (!$cols) { throw new CakeException(__d('cake_dev', 'Could not describe table for %s', $table)); } while ($column = $cols->fetch(PDO::FETCH_OBJ)) { $fields[$column->Field] = array( 'type' => $this->column($column->Type), 'null' => ($column->Null === 'YES' ? true : false), 'default' => $column->Default, 'length' => $this->length($column->Type) ); if (in_array($fields[$column->Field]['type'], $this->fieldParameters['unsigned']['types'], true)) { $fields[$column->Field]['unsigned'] = $this->_unsigned($column->Type); } if (in_array($fields[$column->Field]['type'], array('timestamp', 'datetime')) && strtoupper($column->Default) === 'CURRENT_TIMESTAMP') { $fields[$column->Field]['default'] = null; } if (!empty($column->Key) && isset($this->index[$column->Key])) { $fields[$column->Field]['key'] = $this->index[$column->Key]; } foreach ($this->fieldParameters as $name => $value) { if (!empty($column->{$value['column']})) { $fields[$column->Field][$name] = $column->{$value['column']}; } } if (isset($fields[$column->Field]['collate'])) { $charset = $this->getCharsetName($fields[$column->Field]['collate']); if ($charset) { $fields[$column->Field]['charset'] = $charset; } } } $this->_cacheDescription($key, $fields); $cols->closeCursor(); return $fields; } /** * Generates and executes an SQL UPDATE statement for given model, fields, and values. * * @param Model $model The model to update. * @param array $fields The fields to update. * @param array $values The values to set. * @param mixed $conditions The conditions to use. * @return array */ public function update(Model $model, $fields = array(), $values = null, $conditions = null) { if (!$this->_useAlias) { return parent::update($model, $fields, $values, $conditions); } if (!$values) { $combined = $fields; } else { $combined = array_combine($fields, $values); } $alias = $joins = false; $fields = $this->_prepareUpdateFields($model, $combined, empty($conditions), !empty($conditions)); $fields = implode(', ', $fields); $table = $this->fullTableName($model); if (!empty($conditions)) { $alias = $this->name($model->alias); if ($model->name === $model->alias) { $joins = implode(' ', $this->_getJoins($model)); } } $conditions = $this->conditions($this->defaultConditions($model, $conditions, $alias), true, true, $model); if ($conditions === false) { return false; } if (!$this->execute($this->renderStatement('update', compact('table', 'alias', 'joins', 'fields', 'conditions')))) { $model->onError(); return false; } return true; } /** * Generates and executes an SQL DELETE statement for given id/conditions on given model. * * @param Model $model The model to delete from. * @param mixed $conditions The conditions to use. * @return bool Success */ public function delete(Model $model, $conditions = null) { if (!$this->_useAlias) { return parent::delete($model, $conditions); } $alias = $this->name($model->alias); $table = $this->fullTableName($model); $joins = implode(' ', $this->_getJoins($model)); if (empty($conditions)) { $alias = $joins = false; } $complexConditions = false; foreach ((array)$conditions as $key => $value) { if (strpos($key, $model->alias) === false) { $complexConditions = true; break; } } if (!$complexConditions) { $joins = false; } $conditions = $this->conditions($this->defaultConditions($model, $conditions, $alias), true, true, $model); if ($conditions === false) { return false; } if ($this->execute($this->renderStatement('delete', compact('alias', 'table', 'joins', 'conditions'))) === false) { $model->onError(); return false; } return true; } /** * Sets the database encoding * * @param string $enc Database encoding * @return bool */ public function setEncoding($enc) { return $this->_execute('SET NAMES ' . $enc) !== false; } /** * Returns an array of the indexes in given datasource name. * * @param string $model Name of model to inspect * @return array Fields in table. Keys are column and unique */ public function index($model) { $index = array(); $table = $this->fullTableName($model); $old = version_compare($this->getVersion(), '4.1', '<='); if ($table) { $indexes = $this->_execute('SHOW INDEX FROM ' . $table); // @codingStandardsIgnoreStart // MySQL columns don't match the cakephp conventions. while ($idx = $indexes->fetch(PDO::FETCH_OBJ)) { if ($old) { $idx = (object)current((array)$idx); } if (!isset($index[$idx->Key_name]['column'])) { $col = array(); $index[$idx->Key_name]['column'] = $idx->Column_name; if ($idx->Index_type === 'FULLTEXT') { $index[$idx->Key_name]['type'] = strtolower($idx->Index_type); } else { $index[$idx->Key_name]['unique'] = (int)($idx->Non_unique == 0); } } else { if (!empty($index[$idx->Key_name]['column']) && !is_array($index[$idx->Key_name]['column'])) { $col[] = $index[$idx->Key_name]['column']; } $col[] = $idx->Column_name; $index[$idx->Key_name]['column'] = $col; } if (!empty($idx->Sub_part)) { if (!isset($index[$idx->Key_name]['length'])) { $index[$idx->Key_name]['length'] = array(); } $index[$idx->Key_name]['length'][$idx->Column_name] = $idx->Sub_part; } } // @codingStandardsIgnoreEnd $indexes->closeCursor(); } return $index; } /** * Generate a MySQL Alter Table syntax for the given Schema comparison * * @param array $compare Result of a CakeSchema::compare() * @param string $table The table name. * @return array Array of alter statements to make. */ public function alterSchema($compare, $table = null) { if (!is_array($compare)) { return false; } $out = ''; $colList = array(); foreach ($compare as $curTable => $types) { $indexes = $tableParameters = $colList = array(); if (!$table || $table === $curTable) { $out .= 'ALTER TABLE ' . $this->fullTableName($curTable) . " \n"; foreach ($types as $type => $column) { if (isset($column['indexes'])) { $indexes[$type] = $column['indexes']; unset($column['indexes']); } if (isset($column['tableParameters'])) { $tableParameters[$type] = $column['tableParameters']; unset($column['tableParameters']); } switch ($type) { case 'add': foreach ($column as $field => $col) { $col['name'] = $field; $alter = 'ADD ' . $this->buildColumn($col); if (isset($col['after'])) { $alter .= ' AFTER ' . $this->name($col['after']); } $colList[] = $alter; } break; case 'drop': foreach ($column as $field => $col) { $col['name'] = $field; $colList[] = 'DROP ' . $this->name($field); } break; case 'change': foreach ($column as $field => $col) { if (!isset($col['name'])) { $col['name'] = $field; } $alter = 'CHANGE ' . $this->name($field) . ' ' . $this->buildColumn($col); if (isset($col['after'])) { $alter .= ' AFTER ' . $this->name($col['after']); } $colList[] = $alter; } break; } } $colList = array_merge($colList, $this->_alterIndexes($curTable, $indexes)); $colList = array_merge($colList, $this->_alterTableParameters($curTable, $tableParameters)); $out .= "\t" . implode(",\n\t", $colList) . ";\n\n"; } } return $out; } /** * Generate a "drop table" statement for the given table * * @param type $table Name of the table to drop * @return string Drop table SQL statement */ protected function _dropTable($table) { return 'DROP TABLE IF EXISTS ' . $this->fullTableName($table) . ";"; } /** * Generate MySQL table parameter alteration statements for a table. * * @param string $table Table to alter parameters for. * @param array $parameters Parameters to add & drop. * @return array Array of table property alteration statements. */ protected function _alterTableParameters($table, $parameters) { if (isset($parameters['change'])) { return $this->buildTableParameters($parameters['change']); } return array(); } /** * Format indexes for create table * * @param array $indexes An array of indexes to generate SQL from * @param string $table Optional table name, not used * @return array An array of SQL statements for indexes * @see DboSource::buildIndex() */ public function buildIndex($indexes, $table = null) { $join = array(); foreach ($indexes as $name => $value) { $out = ''; if ($name === 'PRIMARY') { $out .= 'PRIMARY '; $name = null; } else { if (!empty($value['unique'])) { $out .= 'UNIQUE '; } $name = $this->startQuote . $name . $this->endQuote; } if (isset($value['type']) && strtolower($value['type']) === 'fulltext') { $out .= 'FULLTEXT '; } $out .= 'KEY ' . $name . ' ('; if (is_array($value['column'])) { if (isset($value['length'])) { $vals = array(); foreach ($value['column'] as $column) { $name = $this->name($column); if (isset($value['length'])) { $name .= $this->_buildIndexSubPart($value['length'], $column); } $vals[] = $name; } $out .= implode(', ', $vals); } else { $out .= implode(', ', array_map(array(&$this, 'name'), $value['column'])); } } else { $out .= $this->name($value['column']); if (isset($value['length'])) { $out .= $this->_buildIndexSubPart($value['length'], $value['column']); } } $out .= ')'; $join[] = $out; } return $join; } /** * Generate MySQL index alteration statements for a table. * * @param string $table Table to alter indexes for * @param array $indexes Indexes to add and drop * @return array Index alteration statements */ protected function _alterIndexes($table, $indexes) { $alter = array(); if (isset($indexes['drop'])) { foreach ($indexes['drop'] as $name => $value) { $out = 'DROP '; if ($name === 'PRIMARY') { $out .= 'PRIMARY KEY'; } else { $out .= 'KEY ' . $this->startQuote . $name . $this->endQuote; } $alter[] = $out; } } if (isset($indexes['add'])) { $add = $this->buildIndex($indexes['add']); foreach ($add as $index) { $alter[] = 'ADD ' . $index; } } return $alter; } /** * Format length for text indexes * * @param array $lengths An array of lengths for a single index * @param string $column The column for which to generate the index length * @return string Formatted length part of an index field */ protected function _buildIndexSubPart($lengths, $column) { if ($lengths === null) { return ''; } if (!isset($lengths[$column])) { return ''; } return '(' . $lengths[$column] . ')'; } /** * Returns a detailed array of sources (tables) in the database. * * @param string $name Table name to get parameters * @return array Array of table names in the database */ public function listDetailedSources($name = null) { $condition = ''; if (is_string($name)) { $condition = ' WHERE name = ' . $this->value($name); } $result = $this->_connection->query('SHOW TABLE STATUS ' . $condition, PDO::FETCH_ASSOC); if (!$result) { $result->closeCursor(); return array(); } $tables = array(); foreach ($result as $row) { $tables[$row['Name']] = (array)$row; unset($tables[$row['Name']]['queryString']); if (!empty($row['Collation'])) { $charset = $this->getCharsetName($row['Collation']); if ($charset) { $tables[$row['Name']]['charset'] = $charset; } } } $result->closeCursor(); if (is_string($name) && isset($tables[$name])) { return $tables[$name]; } return $tables; } /** * Converts database-layer column types to basic types * * @param string $real Real database-layer column type (i.e. "varchar(255)") * @return string Abstract column type (i.e. "string") */ public function column($real) { if (is_array($real)) { $col = $real['name']; if (isset($real['limit'])) { $col .= '(' . $real['limit'] . ')'; } return $col; } $col = str_replace(')', '', $real); $limit = $this->length($real); if (strpos($col, '(') !== false) { list($col, $vals) = explode('(', $col); } if (in_array($col, array('date', 'time', 'datetime', 'timestamp'))) { return $col; } if (($col === 'tinyint' && $limit === 1) || $col === 'boolean') { return 'boolean'; } if (strpos($col, 'bigint') !== false || $col === 'bigint') { return 'biginteger'; } if (strpos($col, 'int') !== false) { return 'integer'; } if (strpos($col, 'char') !== false || $col === 'tinytext') { return 'string'; } if (strpos($col, 'text') !== false) { return 'text'; } if (strpos($col, 'blob') !== false || $col === 'binary') { return 'binary'; } if (strpos($col, 'float') !== false || strpos($col, 'double') !== false) { return 'float'; } if (strpos($col, 'decimal') !== false || strpos($col, 'numeric') !== false) { return 'decimal'; } if (strpos($col, 'enum') !== false) { return "enum($vals)"; } if (strpos($col, 'set') !== false) { return "set($vals)"; } return 'text'; } /** * {@inheritDoc} */ public function value($data, $column = null, $null = true) { $value = parent::value($data, $column, $null); if (is_numeric($value) && substr($column, 0, 3) === 'set') { return $this->_connection->quote($value); } return $value; } /** * Gets the schema name * * @return string The schema name */ public function getSchemaName() { return $this->config['database']; } /** * Check if the server support nested transactions * * @return bool */ public function nestedTransactionSupported() { return $this->useNestedTransactions && version_compare($this->getVersion(), '4.1', '>='); } /** * Check if column type is unsigned * * @param string $real Real database-layer column type (i.e. "varchar(255)") * @return bool True if column is unsigned, false otherwise */ protected function _unsigned($real) { return strpos(strtolower($real), 'unsigned') !== false; } } cakephp-2.8.0/lib/Cake/Model/Datasource/Database/Postgres.php000066400000000000000000000673671265552240500237530ustar00rootroot00000000000000 true, 'host' => 'localhost', 'login' => 'root', 'password' => '', 'database' => 'cake', 'schema' => 'public', 'port' => 5432, 'encoding' => '', 'sslmode' => 'allow', 'flags' => array() ); /** * Columns * * @var array */ public $columns = array( 'primary_key' => array('name' => 'serial NOT NULL'), 'string' => array('name' => 'varchar', 'limit' => '255'), 'text' => array('name' => 'text'), 'integer' => array('name' => 'integer', 'formatter' => 'intval'), 'biginteger' => array('name' => 'bigint', 'limit' => '20'), 'float' => array('name' => 'float', 'formatter' => 'floatval'), 'decimal' => array('name' => 'decimal', 'formatter' => 'floatval'), 'datetime' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'), 'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'), 'time' => array('name' => 'time', 'format' => 'H:i:s', 'formatter' => 'date'), 'date' => array('name' => 'date', 'format' => 'Y-m-d', 'formatter' => 'date'), 'binary' => array('name' => 'bytea'), 'boolean' => array('name' => 'boolean'), 'number' => array('name' => 'numeric'), 'inet' => array('name' => 'inet') ); /** * Starting Quote * * @var string */ public $startQuote = '"'; /** * Ending Quote * * @var string */ public $endQuote = '"'; /** * Contains mappings of custom auto-increment sequences, if a table uses a sequence name * other than what is dictated by convention. * * @var array */ protected $_sequenceMap = array(); /** * The set of valid SQL operations usable in a WHERE statement * * @var array */ protected $_sqlOps = array('like', 'ilike', 'or', 'not', 'in', 'between', '~', '~\*', '\!~', '\!~\*', 'similar to'); /** * Connects to the database using options in the given configuration array. * * @return bool True if successfully connected. * @throws MissingConnectionException */ public function connect() { $config = $this->config; $this->connected = false; $flags = $config['flags'] + array( PDO::ATTR_PERSISTENT => $config['persistent'], PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ); try { $this->_connection = new PDO( "pgsql:host={$config['host']};port={$config['port']};dbname={$config['database']};sslmode={$config['sslmode']}", $config['login'], $config['password'], $flags ); $this->connected = true; if (!empty($config['encoding'])) { $this->setEncoding($config['encoding']); } if (!empty($config['schema'])) { $this->_execute('SET search_path TO "' . $config['schema'] . '"'); } if (!empty($config['settings'])) { foreach ($config['settings'] as $key => $value) { $this->_execute("SET $key TO $value"); } } } catch (PDOException $e) { throw new MissingConnectionException(array( 'class' => get_class($this), 'message' => $e->getMessage() )); } return $this->connected; } /** * Check if PostgreSQL is enabled/loaded * * @return bool */ public function enabled() { return in_array('pgsql', PDO::getAvailableDrivers()); } /** * Returns an array of tables in the database. If there are no tables, an error is raised and the application exits. * * @param mixed $data The sources to list. * @return array Array of table names in the database */ public function listSources($data = null) { $cache = parent::listSources(); if ($cache) { return $cache; } $schema = $this->config['schema']; $sql = "SELECT table_name as name FROM INFORMATION_SCHEMA.tables WHERE table_schema = ?"; $result = $this->_execute($sql, array($schema)); if (!$result) { return array(); } $tables = array(); foreach ($result as $item) { $tables[] = $item->name; } $result->closeCursor(); parent::listSources($tables); return $tables; } /** * Returns an array of the fields in given table name. * * @param Model|string $model Name of database table to inspect * @return array Fields in table. Keys are name and type */ public function describe($model) { $table = $this->fullTableName($model, false, false); $fields = parent::describe($table); $this->_sequenceMap[$table] = array(); $cols = null; if ($fields === null) { $cols = $this->_execute( "SELECT DISTINCT table_schema AS schema, column_name AS name, data_type AS type, is_nullable AS null, column_default AS default, ordinal_position AS position, character_maximum_length AS char_length, character_octet_length AS oct_length FROM information_schema.columns WHERE table_name = ? AND table_schema = ? ORDER BY position", array($table, $this->config['schema']) ); // @codingStandardsIgnoreStart // Postgres columns don't match the coding standards. foreach ($cols as $c) { $type = $c->type; if (!empty($c->oct_length) && $c->char_length === null) { if ($c->type === 'character varying') { $length = null; $type = 'text'; } elseif ($c->type === 'uuid') { $length = 36; } else { $length = (int)$c->oct_length; } } elseif (!empty($c->char_length)) { $length = (int)$c->char_length; } else { $length = $this->length($c->type); } if (empty($length)) { $length = null; } $fields[$c->name] = array( 'type' => $this->column($type), 'null' => ($c->null === 'NO' ? false : true), 'default' => preg_replace( "/^'(.*)'$/", "$1", preg_replace('/::.*/', '', $c->default) ), 'length' => $length ); if ($model instanceof Model) { if ($c->name === $model->primaryKey) { $fields[$c->name]['key'] = 'primary'; if ($fields[$c->name]['type'] !== 'string') { $fields[$c->name]['length'] = 11; } } } if ( $fields[$c->name]['default'] === 'NULL' || $c->default === null || preg_match('/nextval\([\'"]?([\w.]+)/', $c->default, $seq) ) { $fields[$c->name]['default'] = null; if (!empty($seq) && isset($seq[1])) { if (strpos($seq[1], '.') === false) { $sequenceName = $c->schema . '.' . $seq[1]; } else { $sequenceName = $seq[1]; } $this->_sequenceMap[$table][$c->name] = $sequenceName; } } if ($fields[$c->name]['type'] === 'timestamp' && $fields[$c->name]['default'] === '') { $fields[$c->name]['default'] = null; } if ($fields[$c->name]['type'] === 'boolean' && !empty($fields[$c->name]['default'])) { $fields[$c->name]['default'] = constant($fields[$c->name]['default']); } } $this->_cacheDescription($table, $fields); } // @codingStandardsIgnoreEnd if (isset($model->sequence)) { $this->_sequenceMap[$table][$model->primaryKey] = $model->sequence; } if ($cols) { $cols->closeCursor(); } return $fields; } /** * Returns the ID generated from the previous INSERT operation. * * @param string $source Name of the database table * @param string $field Name of the ID database field. Defaults to "id" * @return int */ public function lastInsertId($source = null, $field = 'id') { $seq = $this->getSequence($source, $field); return $this->_connection->lastInsertId($seq); } /** * Gets the associated sequence for the given table/field * * @param string|Model $table Either a full table name (with prefix) as a string, or a model object * @param string $field Name of the ID database field. Defaults to "id" * @return string The associated sequence name from the sequence map, defaults to "{$table}_{$field}_seq" */ public function getSequence($table, $field = 'id') { if (is_object($table)) { $table = $this->fullTableName($table, false, false); } if (!isset($this->_sequenceMap[$table])) { $this->describe($table); } if (isset($this->_sequenceMap[$table][$field])) { return $this->_sequenceMap[$table][$field]; } return "{$table}_{$field}_seq"; } /** * Reset a sequence based on the MAX() value of $column. Useful * for resetting sequences after using insertMulti(). * * @param string $table The name of the table to update. * @param string $column The column to use when resetting the sequence value, * the sequence name will be fetched using Postgres::getSequence(); * @return bool success. */ public function resetSequence($table, $column) { $tableName = $this->fullTableName($table, false, false); $fullTable = $this->fullTableName($table); $sequence = $this->value($this->getSequence($tableName, $column)); $column = $this->name($column); $this->execute("SELECT setval($sequence, (SELECT MAX($column) FROM $fullTable))"); return true; } /** * Deletes all the records in a table and drops all associated auto-increment sequences * * @param string|Model $table A string or model class representing the table to be truncated * @param bool $reset true for resetting the sequence, false to leave it as is. * and if 1, sequences are not modified * @return bool SQL TRUNCATE TABLE statement, false if not applicable. */ public function truncate($table, $reset = false) { $table = $this->fullTableName($table, false, false); if (!isset($this->_sequenceMap[$table])) { $cache = $this->cacheSources; $this->cacheSources = false; $this->describe($table); $this->cacheSources = $cache; } if ($this->execute('DELETE FROM ' . $this->fullTableName($table))) { if (isset($this->_sequenceMap[$table]) && $reset != true) { foreach ($this->_sequenceMap[$table] as $sequence) { $quoted = $this->name($sequence); $this->_execute("ALTER SEQUENCE {$quoted} RESTART WITH 1"); } } return true; } return false; } /** * Prepares field names to be quoted by parent * * @param string $data The name to format. * @return string SQL field */ public function name($data) { if (is_string($data)) { $data = str_replace('"__"', '__', $data); } return parent::name($data); } /** * Generates the fields list of an SQL query. * * @param Model $model The model to get fields for. * @param string $alias Alias table name. * @param mixed $fields The list of fields to get. * @param bool $quote Whether or not to quote identifiers. * @return array */ public function fields(Model $model, $alias = null, $fields = array(), $quote = true) { if (empty($alias)) { $alias = $model->alias; } $fields = parent::fields($model, $alias, $fields, false); if (!$quote) { return $fields; } $count = count($fields); if ($count >= 1 && !preg_match('/^\s*COUNT\(\*/', $fields[0])) { $result = array(); for ($i = 0; $i < $count; $i++) { if (!preg_match('/^.+\\(.*\\)/', $fields[$i]) && !preg_match('/\s+AS\s+/', $fields[$i])) { if (substr($fields[$i], -1) === '*') { if (strpos($fields[$i], '.') !== false && $fields[$i] != $alias . '.*') { $build = explode('.', $fields[$i]); $AssociatedModel = $model->{$build[0]}; } else { $AssociatedModel = $model; } $_fields = $this->fields($AssociatedModel, $AssociatedModel->alias, array_keys($AssociatedModel->schema())); $result = array_merge($result, $_fields); continue; } $prepend = ''; if (strpos($fields[$i], 'DISTINCT') !== false) { $prepend = 'DISTINCT '; $fields[$i] = trim(str_replace('DISTINCT', '', $fields[$i])); } if (strrpos($fields[$i], '.') === false) { $fields[$i] = $prepend . $this->name($alias) . '.' . $this->name($fields[$i]) . ' AS ' . $this->name($alias . '__' . $fields[$i]); } else { $build = explode('.', $fields[$i]); $fields[$i] = $prepend . $this->name($build[0]) . '.' . $this->name($build[1]) . ' AS ' . $this->name($build[0] . '__' . $build[1]); } } else { $fields[$i] = preg_replace_callback('/\(([\s\.\w]+)\)/', array(&$this, '_quoteFunctionField'), $fields[$i]); } $result[] = $fields[$i]; } return $result; } return $fields; } /** * Auxiliary function to quote matched `(Model.fields)` from a preg_replace_callback call * Quotes the fields in a function call. * * @param string $match matched string * @return string quoted string */ protected function _quoteFunctionField($match) { $prepend = ''; if (strpos($match[1], 'DISTINCT') !== false) { $prepend = 'DISTINCT '; $match[1] = trim(str_replace('DISTINCT', '', $match[1])); } $constant = preg_match('/^\d+|NULL|FALSE|TRUE$/i', $match[1]); if (!$constant && strpos($match[1], '.') === false) { $match[1] = $this->name($match[1]); } elseif (!$constant) { $parts = explode('.', $match[1]); if (!Hash::numeric($parts)) { $match[1] = $this->name($match[1]); } } return '(' . $prepend . $match[1] . ')'; } /** * Returns an array of the indexes in given datasource name. * * @param string $model Name of model to inspect * @return array Fields in table. Keys are column and unique */ public function index($model) { $index = array(); $table = $this->fullTableName($model, false, false); if ($table) { $indexes = $this->query("SELECT c2.relname, i.indisprimary, i.indisunique, i.indisclustered, i.indisvalid, pg_catalog.pg_get_indexdef(i.indexrelid, 0, true) as statement, c2.reltablespace FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i WHERE c.oid = ( SELECT c.oid FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace WHERE c.relname ~ '^(" . $table . ")$' AND pg_catalog.pg_table_is_visible(c.oid) AND n.nspname ~ '^(" . $this->config['schema'] . ")$' ) AND c.oid = i.indrelid AND i.indexrelid = c2.oid ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname", false); foreach ($indexes as $info) { $key = array_pop($info); if ($key['indisprimary']) { $key['relname'] = 'PRIMARY'; } preg_match('/\(([^\)]+)\)/', $key['statement'], $indexColumns); $parsedColumn = $indexColumns[1]; if (strpos($indexColumns[1], ',') !== false) { $parsedColumn = explode(', ', $indexColumns[1]); } $index[$key['relname']]['unique'] = $key['indisunique']; $index[$key['relname']]['column'] = $parsedColumn; } } return $index; } /** * Alter the Schema of a table. * * @param array $compare Results of CakeSchema::compare() * @param string $table name of the table * @return array */ public function alterSchema($compare, $table = null) { if (!is_array($compare)) { return false; } $out = ''; $colList = array(); foreach ($compare as $curTable => $types) { $indexes = $colList = array(); if (!$table || $table === $curTable) { $out .= 'ALTER TABLE ' . $this->fullTableName($curTable) . " \n"; foreach ($types as $type => $column) { if (isset($column['indexes'])) { $indexes[$type] = $column['indexes']; unset($column['indexes']); } switch ($type) { case 'add': foreach ($column as $field => $col) { $col['name'] = $field; $colList[] = 'ADD COLUMN ' . $this->buildColumn($col); } break; case 'drop': foreach ($column as $field => $col) { $col['name'] = $field; $colList[] = 'DROP COLUMN ' . $this->name($field); } break; case 'change': $schema = $this->describe($curTable); foreach ($column as $field => $col) { if (!isset($col['name'])) { $col['name'] = $field; } $original = $schema[$field]; $fieldName = $this->name($field); $default = isset($col['default']) ? $col['default'] : null; $nullable = isset($col['null']) ? $col['null'] : null; $boolToInt = $original['type'] === 'boolean' && $col['type'] === 'integer'; unset($col['default'], $col['null']); if ($field !== $col['name']) { $newName = $this->name($col['name']); $out .= "\tRENAME {$fieldName} TO {$newName};\n"; $out .= 'ALTER TABLE ' . $this->fullTableName($curTable) . " \n"; $fieldName = $newName; } if ($boolToInt) { $colList[] = 'ALTER COLUMN ' . $fieldName . ' SET DEFAULT NULL'; $colList[] = 'ALTER COLUMN ' . $fieldName . ' TYPE ' . str_replace(array($fieldName, 'NOT NULL'), '', $this->buildColumn($col)) . ' USING CASE WHEN TRUE THEN 1 ELSE 0 END'; } else { if ($original['type'] === 'text' && $col['type'] === 'integer') { $colList[] = 'ALTER COLUMN ' . $fieldName . ' TYPE ' . str_replace(array($fieldName, 'NOT NULL'), '', $this->buildColumn($col)) . " USING cast({$fieldName} as INTEGER)"; } else { $colList[] = 'ALTER COLUMN ' . $fieldName . ' TYPE ' . str_replace(array($fieldName, 'NOT NULL'), '', $this->buildColumn($col)); } } if (isset($nullable)) { $nullable = ($nullable) ? 'DROP NOT NULL' : 'SET NOT NULL'; $colList[] = 'ALTER COLUMN ' . $fieldName . ' ' . $nullable; } if (isset($default)) { if (!$boolToInt) { $colList[] = 'ALTER COLUMN ' . $fieldName . ' SET DEFAULT ' . $this->value($default, $col['type']); } } else { $colList[] = 'ALTER COLUMN ' . $fieldName . ' DROP DEFAULT'; } } break; } } if (isset($indexes['drop']['PRIMARY'])) { $colList[] = 'DROP CONSTRAINT ' . $curTable . '_pkey'; } if (isset($indexes['add']['PRIMARY'])) { $cols = $indexes['add']['PRIMARY']['column']; if (is_array($cols)) { $cols = implode(', ', $cols); } $colList[] = 'ADD PRIMARY KEY (' . $cols . ')'; } if (!empty($colList)) { $out .= "\t" . implode(",\n\t", $colList) . ";\n\n"; } else { $out = ''; } $out .= implode(";\n\t", $this->_alterIndexes($curTable, $indexes)); } } return $out; } /** * Generate PostgreSQL index alteration statements for a table. * * @param string $table Table to alter indexes for * @param array $indexes Indexes to add and drop * @return array Index alteration statements */ protected function _alterIndexes($table, $indexes) { $alter = array(); if (isset($indexes['drop'])) { foreach ($indexes['drop'] as $name => $value) { $out = 'DROP '; if ($name === 'PRIMARY') { continue; } else { $out .= 'INDEX ' . $name; } $alter[] = $out; } } if (isset($indexes['add'])) { foreach ($indexes['add'] as $name => $value) { $out = 'CREATE '; if ($name === 'PRIMARY') { continue; } else { if (!empty($value['unique'])) { $out .= 'UNIQUE '; } $out .= 'INDEX '; } if (is_array($value['column'])) { $out .= $name . ' ON ' . $table . ' (' . implode(', ', array_map(array(&$this, 'name'), $value['column'])) . ')'; } else { $out .= $name . ' ON ' . $table . ' (' . $this->name($value['column']) . ')'; } $alter[] = $out; } } return $alter; } /** * Returns a limit statement in the correct format for the particular database. * * @param int $limit Limit of results returned * @param int $offset Offset from which to start results * @return string SQL limit/offset statement */ public function limit($limit, $offset = null) { if ($limit) { $rt = sprintf(' LIMIT %u', $limit); if ($offset) { $rt .= sprintf(' OFFSET %u', $offset); } return $rt; } return null; } /** * Converts database-layer column types to basic types * * @param string $real Real database-layer column type (i.e. "varchar(255)") * @return string Abstract column type (i.e. "string") */ public function column($real) { if (is_array($real)) { $col = $real['name']; if (isset($real['limit'])) { $col .= '(' . $real['limit'] . ')'; } return $col; } $col = str_replace(')', '', $real); if (strpos($col, '(') !== false) { list($col, $limit) = explode('(', $col); } $floats = array( 'float', 'float4', 'float8', 'double', 'double precision', 'real' ); switch (true) { case (in_array($col, array('date', 'time', 'inet', 'boolean'))): return $col; case (strpos($col, 'timestamp') !== false): return 'datetime'; case (strpos($col, 'time') === 0): return 'time'; case ($col === 'bigint'): return 'biginteger'; case (strpos($col, 'int') !== false && $col !== 'interval'): return 'integer'; case (strpos($col, 'char') !== false || $col === 'uuid'): return 'string'; case (strpos($col, 'text') !== false): return 'text'; case (strpos($col, 'bytea') !== false): return 'binary'; case ($col === 'decimal' || $col === 'numeric'): return 'decimal'; case (in_array($col, $floats)): return 'float'; default: return 'text'; } } /** * Gets the length of a database-native column description, or null if no length * * @param string $real Real database-layer column type (i.e. "varchar(255)") * @return int An integer representing the length of the column */ public function length($real) { $col = str_replace(array(')', 'unsigned'), '', $real); $limit = null; if (strpos($col, '(') !== false) { list($col, $limit) = explode('(', $col); } if ($col === 'uuid') { return 36; } if ($limit) { return (int)$limit; } return null; } /** * resultSet method * * @param array &$results The results * @return void */ public function resultSet(&$results) { $this->map = array(); $numFields = $results->columnCount(); $index = 0; $j = 0; while ($j < $numFields) { $column = $results->getColumnMeta($j); if (strpos($column['name'], '__')) { list($table, $name) = explode('__', $column['name']); $this->map[$index++] = array($table, $name, $column['native_type']); } else { $this->map[$index++] = array(0, $column['name'], $column['native_type']); } $j++; } } /** * Fetches the next row from the current result set * * @return array */ public function fetchResult() { if ($row = $this->_result->fetch(PDO::FETCH_NUM)) { $resultRow = array(); foreach ($this->map as $index => $meta) { list($table, $column, $type) = $meta; switch ($type) { case 'bool': $resultRow[$table][$column] = $row[$index] === null ? null : $this->boolean($row[$index]); break; case 'binary': case 'bytea': $resultRow[$table][$column] = $row[$index] === null ? null : stream_get_contents($row[$index]); break; default: $resultRow[$table][$column] = $row[$index]; } } return $resultRow; } $this->_result->closeCursor(); return false; } /** * Translates between PHP boolean values and PostgreSQL boolean values * * @param mixed $data Value to be translated * @param bool $quote true to quote a boolean to be used in a query, false to return the boolean value * @return bool Converted boolean value */ public function boolean($data, $quote = false) { switch (true) { case ($data === true || $data === false): $result = $data; break; case ($data === 't' || $data === 'f'): $result = ($data === 't'); break; case ($data === 'true' || $data === 'false'): $result = ($data === 'true'); break; case ($data === 'TRUE' || $data === 'FALSE'): $result = ($data === 'TRUE'); break; default: $result = (bool)$data; } if ($quote) { return ($result) ? 'TRUE' : 'FALSE'; } return (bool)$result; } /** * Sets the database encoding * * @param mixed $enc Database encoding * @return bool True on success, false on failure */ public function setEncoding($enc) { return $this->_execute('SET NAMES ' . $this->value($enc)) !== false; } /** * Gets the database encoding * * @return string The database encoding */ public function getEncoding() { $result = $this->_execute('SHOW client_encoding')->fetch(); if ($result === false) { return false; } return (isset($result['client_encoding'])) ? $result['client_encoding'] : false; } /** * Generate a Postgres-native column schema string * * @param array $column An array structured like the following: * array('name'=>'value', 'type'=>'value'[, options]), * where options can be 'default', 'length', or 'key'. * @return string */ public function buildColumn($column) { $col = $this->columns[$column['type']]; if (!isset($col['length']) && !isset($col['limit'])) { unset($column['length']); } $out = parent::buildColumn($column); $out = preg_replace( '/integer\([0-9]+\)/', 'integer', $out ); $out = preg_replace( '/bigint\([0-9]+\)/', 'bigint', $out ); $out = str_replace('integer serial', 'serial', $out); $out = str_replace('bigint serial', 'bigserial', $out); if (strpos($out, 'timestamp DEFAULT')) { if (isset($column['null']) && $column['null']) { $out = str_replace('DEFAULT NULL', '', $out); } else { $out = str_replace('DEFAULT NOT NULL', '', $out); } } if (strpos($out, 'DEFAULT DEFAULT')) { if (isset($column['null']) && $column['null']) { $out = str_replace('DEFAULT DEFAULT', 'DEFAULT NULL', $out); } elseif (in_array($column['type'], array('integer', 'float'))) { $out = str_replace('DEFAULT DEFAULT', 'DEFAULT 0', $out); } elseif ($column['type'] === 'boolean') { $out = str_replace('DEFAULT DEFAULT', 'DEFAULT FALSE', $out); } } return $out; } /** * Format indexes for create table * * @param array $indexes The index to build * @param string $table The table name. * @return string */ public function buildIndex($indexes, $table = null) { $join = array(); if (!is_array($indexes)) { return array(); } foreach ($indexes as $name => $value) { if ($name === 'PRIMARY') { $out = 'PRIMARY KEY (' . $this->name($value['column']) . ')'; } else { $out = 'CREATE '; if (!empty($value['unique'])) { $out .= 'UNIQUE '; } if (is_array($value['column'])) { $value['column'] = implode(', ', array_map(array(&$this, 'name'), $value['column'])); } else { $value['column'] = $this->name($value['column']); } $out .= "INDEX {$name} ON {$table}({$value['column']});"; } $join[] = $out; } return $join; } /** * Overrides DboSource::renderStatement to handle schema generation with Postgres-style indexes * * @param string $type The query type. * @param array $data The array of data to render. * @return string */ public function renderStatement($type, $data) { switch (strtolower($type)) { case 'schema': extract($data); foreach ($indexes as $i => $index) { if (preg_match('/PRIMARY KEY/', $index)) { unset($indexes[$i]); $columns[] = $index; break; } } $join = array('columns' => ",\n\t", 'indexes' => "\n"); foreach (array('columns', 'indexes') as $var) { if (is_array(${$var})) { ${$var} = implode($join[$var], array_filter(${$var})); } } return "CREATE TABLE {$table} (\n\t{$columns}\n);\n{$indexes}"; default: return parent::renderStatement($type, $data); } } /** * Gets the schema name * * @return string The schema name */ public function getSchemaName() { return $this->config['schema']; } /** * Check if the server support nested transactions * * @return bool */ public function nestedTransactionSupported() { return $this->useNestedTransactions && version_compare($this->getVersion(), '8.0', '>='); } } cakephp-2.8.0/lib/Cake/Model/Datasource/Database/Sqlite.php000066400000000000000000000376451265552240500234020ustar00rootroot00000000000000 false, 'database' => null, 'flags' => array() ); /** * SQLite3 column definition * * @var array */ public $columns = array( 'primary_key' => array('name' => 'integer primary key autoincrement'), 'string' => array('name' => 'varchar', 'limit' => '255'), 'text' => array('name' => 'text'), 'integer' => array('name' => 'integer', 'limit' => null, 'formatter' => 'intval'), 'biginteger' => array('name' => 'bigint', 'limit' => 20), 'float' => array('name' => 'float', 'formatter' => 'floatval'), 'decimal' => array('name' => 'decimal', 'formatter' => 'floatval'), 'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'), 'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'), 'time' => array('name' => 'time', 'format' => 'H:i:s', 'formatter' => 'date'), 'date' => array('name' => 'date', 'format' => 'Y-m-d', 'formatter' => 'date'), 'binary' => array('name' => 'blob'), 'boolean' => array('name' => 'boolean') ); /** * List of engine specific additional field parameters used on table creating * * @var array */ public $fieldParameters = array( 'collate' => array( 'value' => 'COLLATE', 'quote' => false, 'join' => ' ', 'column' => 'Collate', 'position' => 'afterDefault', 'options' => array( 'BINARY', 'NOCASE', 'RTRIM' ) ), ); /** * Connects to the database using config['database'] as a filename. * * @return bool * @throws MissingConnectionException */ public function connect() { $config = $this->config; $flags = $config['flags'] + array( PDO::ATTR_PERSISTENT => $config['persistent'], PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ); try { $this->_connection = new PDO('sqlite:' . $config['database'], null, null, $flags); $this->connected = true; } catch(PDOException $e) { throw new MissingConnectionException(array( 'class' => get_class($this), 'message' => $e->getMessage() )); } return $this->connected; } /** * Check whether the SQLite extension is installed/loaded * * @return bool */ public function enabled() { return in_array('sqlite', PDO::getAvailableDrivers()); } /** * Returns an array of tables in the database. If there are no tables, an error is raised and the application exits. * * @param mixed $data Unused. * @return array Array of table names in the database */ public function listSources($data = null) { $cache = parent::listSources(); if ($cache) { return $cache; } $result = $this->fetchAll("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;", false); if (!$result || empty($result)) { return array(); } $tables = array(); foreach ($result as $table) { $tables[] = $table[0]['name']; } parent::listSources($tables); return $tables; } /** * Returns an array of the fields in given table name. * * @param Model|string $model Either the model or table name you want described. * @return array Fields in table. Keys are name and type */ public function describe($model) { $table = $this->fullTableName($model, false, false); $cache = parent::describe($table); if ($cache) { return $cache; } $fields = array(); $result = $this->_execute( 'PRAGMA table_info(' . $this->value($table, 'string') . ')' ); foreach ($result as $column) { $column = (array)$column; $default = ($column['dflt_value'] === 'NULL') ? null : trim($column['dflt_value'], "'"); $fields[$column['name']] = array( 'type' => $this->column($column['type']), 'null' => !$column['notnull'], 'default' => $default, 'length' => $this->length($column['type']) ); if ($column['pk'] == 1) { $fields[$column['name']]['key'] = $this->index['PRI']; $fields[$column['name']]['null'] = false; if (empty($fields[$column['name']]['length'])) { $fields[$column['name']]['length'] = 11; } } } $result->closeCursor(); $this->_cacheDescription($table, $fields); return $fields; } /** * Generates and executes an SQL UPDATE statement for given model, fields, and values. * * @param Model $model The model instance to update. * @param array $fields The fields to update. * @param array $values The values to set columns to. * @param mixed $conditions array of conditions to use. * @return array */ public function update(Model $model, $fields = array(), $values = null, $conditions = null) { if (empty($values) && !empty($fields)) { foreach ($fields as $field => $value) { if (strpos($field, $model->alias . '.') !== false) { unset($fields[$field]); $field = str_replace($model->alias . '.', "", $field); $field = str_replace($model->alias . '.', "", $field); $fields[$field] = $value; } } } return parent::update($model, $fields, $values, $conditions); } /** * Deletes all the records in a table and resets the count of the auto-incrementing * primary key, where applicable. * * @param string|Model $table A string or model class representing the table to be truncated * @return bool SQL TRUNCATE TABLE statement, false if not applicable. */ public function truncate($table) { if (in_array('sqlite_sequence', $this->listSources())) { $this->_execute('DELETE FROM sqlite_sequence where name=' . $this->startQuote . $this->fullTableName($table, false, false) . $this->endQuote); } return $this->execute('DELETE FROM ' . $this->fullTableName($table)); } /** * Converts database-layer column types to basic types * * @param string $real Real database-layer column type (i.e. "varchar(255)") * @return string Abstract column type (i.e. "string") */ public function column($real) { if (is_array($real)) { $col = $real['name']; if (isset($real['limit'])) { $col .= '(' . $real['limit'] . ')'; } return $col; } $col = strtolower(str_replace(')', '', $real)); if (strpos($col, '(') !== false) { list($col) = explode('(', $col); } $standard = array( 'text', 'integer', 'float', 'boolean', 'timestamp', 'date', 'datetime', 'time' ); if (in_array($col, $standard)) { return $col; } if ($col === 'bigint') { return 'biginteger'; } if (strpos($col, 'char') !== false) { return 'string'; } if (in_array($col, array('blob', 'clob'))) { return 'binary'; } if (strpos($col, 'numeric') !== false || strpos($col, 'decimal') !== false) { return 'decimal'; } return 'text'; } /** * Generate ResultSet * * @param mixed $results The results to modify. * @return void */ public function resultSet($results) { $this->results = $results; $this->map = array(); $numFields = $results->columnCount(); $index = 0; $j = 0; // PDO::getColumnMeta is experimental and does not work with sqlite3, // so try to figure it out based on the querystring $querystring = $results->queryString; if (stripos($querystring, 'SELECT') === 0 && stripos($querystring, 'FROM') > 0) { $selectpart = substr($querystring, 7); $selects = array(); foreach (CakeText::tokenize($selectpart, ',', '(', ')') as $part) { $fromPos = stripos($part, ' FROM '); if ($fromPos !== false) { $selects[] = trim(substr($part, 0, $fromPos)); break; } $selects[] = $part; } } elseif (strpos($querystring, 'PRAGMA table_info') === 0) { $selects = array('cid', 'name', 'type', 'notnull', 'dflt_value', 'pk'); } elseif (strpos($querystring, 'PRAGMA index_list') === 0) { $selects = array('seq', 'name', 'unique'); } elseif (strpos($querystring, 'PRAGMA index_info') === 0) { $selects = array('seqno', 'cid', 'name'); } while ($j < $numFields) { if (!isset($selects[$j])) { $j++; continue; } if (preg_match('/\bAS(?!.*\bAS\b)\s+(.*)/i', $selects[$j], $matches)) { $columnName = trim($matches[1], '"'); } else { $columnName = trim(str_replace('"', '', $selects[$j])); } if (strpos($selects[$j], 'DISTINCT') === 0) { $columnName = str_ireplace('DISTINCT', '', $columnName); } $metaType = false; try { $metaData = (array)$results->getColumnMeta($j); if (!empty($metaData['sqlite:decl_type'])) { $metaType = trim($metaData['sqlite:decl_type']); } } catch (Exception $e) { } if (strpos($columnName, '.')) { $parts = explode('.', $columnName); $this->map[$index++] = array(trim($parts[0]), trim($parts[1]), $metaType); } else { $this->map[$index++] = array(0, $columnName, $metaType); } $j++; } } /** * Fetches the next row from the current result set * * @return mixed array with results fetched and mapped to column names or false if there is no results left to fetch */ public function fetchResult() { if ($row = $this->_result->fetch(PDO::FETCH_NUM)) { $resultRow = array(); foreach ($this->map as $col => $meta) { list($table, $column, $type) = $meta; $resultRow[$table][$column] = $row[$col]; if ($type === 'boolean' && $row[$col] !== null) { $resultRow[$table][$column] = $this->boolean($resultRow[$table][$column]); } } return $resultRow; } $this->_result->closeCursor(); return false; } /** * Returns a limit statement in the correct format for the particular database. * * @param int $limit Limit of results returned * @param int $offset Offset from which to start results * @return string SQL limit/offset statement */ public function limit($limit, $offset = null) { if ($limit) { $rt = sprintf(' LIMIT %u', $limit); if ($offset) { $rt .= sprintf(' OFFSET %u', $offset); } return $rt; } return null; } /** * Generate a database-native column schema string * * @param array $column An array structured like the following: array('name'=>'value', 'type'=>'value'[, options]), * where options can be 'default', 'length', or 'key'. * @return string */ public function buildColumn($column) { $name = $type = null; $column += array('null' => true); extract($column); if (empty($name) || empty($type)) { trigger_error(__d('cake_dev', 'Column name or type not defined in schema'), E_USER_WARNING); return null; } if (!isset($this->columns[$type])) { trigger_error(__d('cake_dev', 'Column type %s does not exist', $type), E_USER_WARNING); return null; } $isPrimary = (isset($column['key']) && $column['key'] === 'primary'); if ($isPrimary && $type === 'integer') { return $this->name($name) . ' ' . $this->columns['primary_key']['name']; } $out = parent::buildColumn($column); if ($isPrimary && $type === 'biginteger') { $replacement = 'PRIMARY KEY'; if ($column['null'] === false) { $replacement = 'NOT NULL ' . $replacement; } return str_replace($this->columns['primary_key']['name'], $replacement, $out); } return $out; } /** * Sets the database encoding * * @param string $enc Database encoding * @return bool */ public function setEncoding($enc) { if (!in_array($enc, array("UTF-8", "UTF-16", "UTF-16le", "UTF-16be"))) { return false; } return $this->_execute("PRAGMA encoding = \"{$enc}\"") !== false; } /** * Gets the database encoding * * @return string The database encoding */ public function getEncoding() { return $this->fetchRow('PRAGMA encoding'); } /** * Removes redundant primary key indexes, as they are handled in the column def of the key. * * @param array $indexes The indexes to build. * @param string $table The table name. * @return string The completed index. */ public function buildIndex($indexes, $table = null) { $join = array(); $table = str_replace('"', '', $table); list($dbname, $table) = explode('.', $table); $dbname = $this->name($dbname); foreach ($indexes as $name => $value) { if ($name === 'PRIMARY') { continue; } $out = 'CREATE '; if (!empty($value['unique'])) { $out .= 'UNIQUE '; } if (is_array($value['column'])) { $value['column'] = implode(', ', array_map(array(&$this, 'name'), $value['column'])); } else { $value['column'] = $this->name($value['column']); } $t = trim($table, '"'); $indexname = $this->name($t . '_' . $name); $table = $this->name($table); $out .= "INDEX {$dbname}.{$indexname} ON {$table}({$value['column']});"; $join[] = $out; } return $join; } /** * Overrides DboSource::index to handle SQLite index introspection * Returns an array of the indexes in given table name. * * @param string $model Name of model to inspect * @return array Fields in table. Keys are column and unique */ public function index($model) { $index = array(); $table = $this->fullTableName($model, false, false); if ($table) { $indexes = $this->query('PRAGMA index_list(' . $table . ')'); if (is_bool($indexes)) { return array(); } foreach ($indexes as $info) { $key = array_pop($info); $keyInfo = $this->query('PRAGMA index_info("' . $key['name'] . '")'); foreach ($keyInfo as $keyCol) { if (!isset($index[$key['name']])) { $col = array(); if (preg_match('/autoindex/', $key['name'])) { $key['name'] = 'PRIMARY'; } $index[$key['name']]['column'] = $keyCol[0]['name']; $index[$key['name']]['unique'] = (int)$key['unique'] === 1; } else { if (!is_array($index[$key['name']]['column'])) { $col[] = $index[$key['name']]['column']; } $col[] = $keyCol[0]['name']; $index[$key['name']]['column'] = $col; } } } } return $index; } /** * Overrides DboSource::renderStatement to handle schema generation with SQLite-style indexes * * @param string $type The type of statement being rendered. * @param array $data The data to convert to SQL. * @return string */ public function renderStatement($type, $data) { switch (strtolower($type)) { case 'schema': extract($data); if (is_array($columns)) { $columns = "\t" . implode(",\n\t", array_filter($columns)); } if (is_array($indexes)) { $indexes = "\t" . implode("\n\t", array_filter($indexes)); } return "CREATE TABLE {$table} (\n{$columns});\n{$indexes}"; default: return parent::renderStatement($type, $data); } } /** * PDO deals in objects, not resources, so overload accordingly. * * @return bool */ public function hasResult() { return is_object($this->_result); } /** * Generate a "drop table" statement for the given table * * @param type $table Name of the table to drop * @return string Drop table SQL statement */ protected function _dropTable($table) { return 'DROP TABLE IF EXISTS ' . $this->fullTableName($table) . ";"; } /** * Gets the schema name * * @return string The schema name */ public function getSchemaName() { return "main"; // Sqlite Datasource does not support multidb } /** * Check if the server support nested transactions * * @return bool */ public function nestedTransactionSupported() { return $this->useNestedTransactions && version_compare($this->getVersion(), '3.6.8', '>='); } } cakephp-2.8.0/lib/Cake/Model/Datasource/Database/Sqlserver.php000066400000000000000000000571421265552240500241210ustar00rootroot00000000000000 true, 'host' => 'localhost\SQLEXPRESS', 'login' => '', 'password' => '', 'database' => 'cake', 'schema' => '', 'flags' => array() ); /** * MS SQL column definition * * @var array */ public $columns = array( 'primary_key' => array('name' => 'IDENTITY (1, 1) NOT NULL'), 'string' => array('name' => 'nvarchar', 'limit' => '255'), 'text' => array('name' => 'nvarchar', 'limit' => 'MAX'), 'integer' => array('name' => 'int', 'formatter' => 'intval'), 'biginteger' => array('name' => 'bigint'), 'numeric' => array('name' => 'decimal', 'formatter' => 'floatval'), 'decimal' => array('name' => 'decimal', 'formatter' => 'floatval'), 'float' => array('name' => 'float', 'formatter' => 'floatval'), 'real' => array('name' => 'float', 'formatter' => 'floatval'), 'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'), 'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'), 'time' => array('name' => 'datetime', 'format' => 'H:i:s', 'formatter' => 'date'), 'date' => array('name' => 'datetime', 'format' => 'Y-m-d', 'formatter' => 'date'), 'binary' => array('name' => 'varbinary'), 'boolean' => array('name' => 'bit') ); /** * Magic column name used to provide pagination support for SQLServer 2008 * which lacks proper limit/offset support. * * @var string */ const ROW_COUNTER = '_cake_page_rownum_'; /** * Connects to the database using options in the given configuration array. * * @return bool True if the database could be connected, else false * @throws MissingConnectionException */ public function connect() { $config = $this->config; $this->connected = false; $flags = $config['flags'] + array( PDO::ATTR_PERSISTENT => $config['persistent'], PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ); if (!empty($config['encoding'])) { $flags[PDO::SQLSRV_ATTR_ENCODING] = $config['encoding']; } try { $this->_connection = new PDO( "sqlsrv:server={$config['host']};Database={$config['database']}", $config['login'], $config['password'], $flags ); $this->connected = true; if (!empty($config['settings'])) { foreach ($config['settings'] as $key => $value) { $this->_execute("SET $key $value"); } } } catch (PDOException $e) { throw new MissingConnectionException(array( 'class' => get_class($this), 'message' => $e->getMessage() )); } return $this->connected; } /** * Check that PDO SQL Server is installed/loaded * * @return bool */ public function enabled() { return in_array('sqlsrv', PDO::getAvailableDrivers()); } /** * Returns an array of sources (tables) in the database. * * @param mixed $data The names * @return array Array of table names in the database */ public function listSources($data = null) { $cache = parent::listSources(); if ($cache !== null) { return $cache; } $result = $this->_execute("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES"); if (!$result) { $result->closeCursor(); return array(); } $tables = array(); while ($line = $result->fetch(PDO::FETCH_NUM)) { $tables[] = $line[0]; } $result->closeCursor(); parent::listSources($tables); return $tables; } /** * Returns an array of the fields in given table name. * * @param Model|string $model Model object to describe, or a string table name. * @return array Fields in table. Keys are name and type * @throws CakeException */ public function describe($model) { $table = $this->fullTableName($model, false, false); $fulltable = $this->fullTableName($model, false, true); $cache = parent::describe($fulltable); if ($cache) { return $cache; } $fields = array(); $schema = is_object($model) ? $model->schemaName : false; $cols = $this->_execute( "SELECT COLUMN_NAME as Field, DATA_TYPE as Type, COL_LENGTH('" . ($schema ? $fulltable : $table) . "', COLUMN_NAME) as Length, IS_NULLABLE As [Null], COLUMN_DEFAULT as [Default], COLUMNPROPERTY(OBJECT_ID('" . ($schema ? $fulltable : $table) . "'), COLUMN_NAME, 'IsIdentity') as [Key], NUMERIC_SCALE as Size FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '" . $table . "'" . ($schema ? " AND TABLE_SCHEMA = '" . $schema . "'" : '') ); if (!$cols) { throw new CakeException(__d('cake_dev', 'Could not describe table for %s', $table)); } while ($column = $cols->fetch(PDO::FETCH_OBJ)) { $field = $column->Field; $fields[$field] = array( 'type' => $this->column($column), 'null' => ($column->Null === 'YES' ? true : false), 'default' => $column->Default, 'length' => $this->length($column), 'key' => ($column->Key == '1') ? 'primary' : false ); if ($fields[$field]['default'] === 'null') { $fields[$field]['default'] = null; } if ($fields[$field]['default'] !== null) { $fields[$field]['default'] = preg_replace( "/^[(]{1,2}'?([^')]*)?'?[)]{1,2}$/", "$1", $fields[$field]['default'] ); $this->value($fields[$field]['default'], $fields[$field]['type']); } if ($fields[$field]['key'] !== false && $fields[$field]['type'] === 'integer') { $fields[$field]['length'] = 11; } elseif ($fields[$field]['key'] === false) { unset($fields[$field]['key']); } if (in_array($fields[$field]['type'], array('date', 'time', 'datetime', 'timestamp'))) { $fields[$field]['length'] = null; } if ($fields[$field]['type'] === 'float' && !empty($column->Size)) { $fields[$field]['length'] = $fields[$field]['length'] . ',' . $column->Size; } } $this->_cacheDescription($table, $fields); $cols->closeCursor(); return $fields; } /** * Generates the fields list of an SQL query. * * @param Model $model The model to get fields for. * @param string $alias Alias table name * @param array $fields The fields so far. * @param bool $quote Whether or not to quote identfiers. * @return array */ public function fields(Model $model, $alias = null, $fields = array(), $quote = true) { if (empty($alias)) { $alias = $model->alias; } $fields = parent::fields($model, $alias, $fields, false); $count = count($fields); if ($count >= 1 && strpos($fields[0], 'COUNT(*)') === false) { $result = array(); for ($i = 0; $i < $count; $i++) { $prepend = ''; if (strpos($fields[$i], 'DISTINCT') !== false && strpos($fields[$i], 'COUNT') === false) { $prepend = 'DISTINCT '; $fields[$i] = trim(str_replace('DISTINCT', '', $fields[$i])); } if (!preg_match('/\s+AS\s+/i', $fields[$i])) { if (substr($fields[$i], -1) === '*') { if (strpos($fields[$i], '.') !== false && $fields[$i] != $alias . '.*') { $build = explode('.', $fields[$i]); $AssociatedModel = $model->{$build[0]}; } else { $AssociatedModel = $model; } $_fields = $this->fields($AssociatedModel, $AssociatedModel->alias, array_keys($AssociatedModel->schema())); $result = array_merge($result, $_fields); continue; } if (strpos($fields[$i], '.') === false) { $this->_fieldMappings[$alias . '__' . $fields[$i]] = $alias . '.' . $fields[$i]; $fieldName = $this->name($alias . '.' . $fields[$i]); $fieldAlias = $this->name($alias . '__' . $fields[$i]); } else { $build = explode('.', $fields[$i]); $build[0] = trim($build[0], '[]'); $build[1] = trim($build[1], '[]'); $name = $build[0] . '.' . $build[1]; $alias = $build[0] . '__' . $build[1]; $this->_fieldMappings[$alias] = $name; $fieldName = $this->name($name); $fieldAlias = $this->name($alias); } if ($model->getColumnType($fields[$i]) === 'datetime') { $fieldName = "CONVERT(VARCHAR(20), {$fieldName}, 20)"; } $fields[$i] = "{$fieldName} AS {$fieldAlias}"; } $result[] = $prepend . $fields[$i]; } return $result; } return $fields; } /** * Generates and executes an SQL INSERT statement for given model, fields, and values. * Removes Identity (primary key) column from update data before returning to parent, if * value is empty. * * @param Model $model The model to insert into. * @param array $fields The fields to set. * @param array $values The values to set. * @return array */ public function create(Model $model, $fields = null, $values = null) { if (!empty($values)) { $fields = array_combine($fields, $values); } $primaryKey = $this->_getPrimaryKey($model); if (array_key_exists($primaryKey, $fields)) { if (empty($fields[$primaryKey])) { unset($fields[$primaryKey]); } else { $this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($model) . ' ON'); } } $result = parent::create($model, array_keys($fields), array_values($fields)); if (array_key_exists($primaryKey, $fields) && !empty($fields[$primaryKey])) { $this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($model) . ' OFF'); } return $result; } /** * Generates and executes an SQL UPDATE statement for given model, fields, and values. * Removes Identity (primary key) column from update data before returning to parent. * * @param Model $model The model to update. * @param array $fields The fields to set. * @param array $values The values to set. * @param mixed $conditions The conditions to use. * @return array */ public function update(Model $model, $fields = array(), $values = null, $conditions = null) { if (!empty($values)) { $fields = array_combine($fields, $values); } if (isset($fields[$model->primaryKey])) { unset($fields[$model->primaryKey]); } if (empty($fields)) { return true; } return parent::update($model, array_keys($fields), array_values($fields), $conditions); } /** * Returns a limit statement in the correct format for the particular database. * * @param int $limit Limit of results returned * @param int $offset Offset from which to start results * @return string SQL limit/offset statement */ public function limit($limit, $offset = null) { if ($limit) { $rt = ''; if (!strpos(strtolower($limit), 'top') || strpos(strtolower($limit), 'top') === 0) { $rt = ' TOP'; } $rt .= sprintf(' %u', $limit); if (is_int($offset) && $offset > 0) { $rt = sprintf(' OFFSET %u ROWS FETCH FIRST %u ROWS ONLY', $offset, $limit); } return $rt; } return null; } /** * Converts database-layer column types to basic types * * @param mixed $real Either the string value of the fields type. * or the Result object from Sqlserver::describe() * @return string Abstract column type (i.e. "string") */ public function column($real) { $limit = null; $col = $real; if (is_object($real) && isset($real->Field)) { $limit = $real->Length; $col = $real->Type; } if ($col === 'datetime2') { return 'datetime'; } if (in_array($col, array('date', 'time', 'datetime', 'timestamp'))) { return $col; } if ($col === 'bit') { return 'boolean'; } if (strpos($col, 'bigint') !== false) { return 'biginteger'; } if (strpos($col, 'int') !== false) { return 'integer'; } if (strpos($col, 'char') !== false && $limit == -1) { return 'text'; } if (strpos($col, 'char') !== false) { return 'string'; } if (strpos($col, 'text') !== false) { return 'text'; } if (strpos($col, 'binary') !== false || $col === 'image') { return 'binary'; } if (in_array($col, array('float', 'real'))) { return 'float'; } if (in_array($col, array('decimal', 'numeric'))) { return 'decimal'; } return 'text'; } /** * Handle SQLServer specific length properties. * SQLServer handles text types as nvarchar/varchar with a length of -1. * * @param mixed $length Either the length as a string, or a Column descriptor object. * @return mixed null|integer with length of column. */ public function length($length) { if (is_object($length) && isset($length->Length)) { if ($length->Length == -1 && strpos($length->Type, 'char') !== false) { return null; } if (in_array($length->Type, array('nchar', 'nvarchar'))) { return floor($length->Length / 2); } if ($length->Type === 'text') { return null; } return $length->Length; } return parent::length($length); } /** * Builds a map of the columns contained in a result * * @param PDOStatement $results The result to modify. * @return void */ public function resultSet($results) { $this->map = array(); $numFields = $results->columnCount(); $index = 0; while ($numFields-- > 0) { $column = $results->getColumnMeta($index); $name = $column['name']; if (strpos($name, '__')) { if (isset($this->_fieldMappings[$name]) && strpos($this->_fieldMappings[$name], '.')) { $map = explode('.', $this->_fieldMappings[$name]); } elseif (isset($this->_fieldMappings[$name])) { $map = array(0, $this->_fieldMappings[$name]); } else { $map = array(0, $name); } } else { $map = array(0, $name); } $map[] = ($column['sqlsrv:decl_type'] === 'bit') ? 'boolean' : $column['native_type']; $this->map[$index++] = $map; } } /** * Builds final SQL statement * * @param string $type Query type * @param array $data Query data * @return string */ public function renderStatement($type, $data) { switch (strtolower($type)) { case 'select': extract($data); $fields = trim($fields); if (strpos($limit, 'TOP') !== false && strpos($fields, 'DISTINCT ') === 0) { $limit = 'DISTINCT ' . trim($limit); $fields = substr($fields, 9); } // hack order as SQLServer requires an order if there is a limit. if ($limit && !$order) { $order = 'ORDER BY (SELECT NULL)'; } // For older versions use the subquery version of pagination. if (version_compare($this->getVersion(), '11', '<') && preg_match('/FETCH\sFIRST\s+([0-9]+)/i', $limit, $offset)) { preg_match('/OFFSET\s*(\d+)\s*.*?(\d+)\s*ROWS/', $limit, $limitOffset); $limit = 'TOP ' . (int)$limitOffset[2]; $page = (int)($limitOffset[1] / $limitOffset[2]); $offset = (int)($limitOffset[2] * $page); $rowCounter = static::ROW_COUNTER; $sql = "SELECT {$limit} * FROM ( SELECT {$fields}, ROW_NUMBER() OVER ({$order}) AS {$rowCounter} FROM {$table} {$alias} {$joins} {$conditions} {$group} ) AS _cake_paging_ WHERE _cake_paging_.{$rowCounter} > {$offset} ORDER BY _cake_paging_.{$rowCounter} "; return trim($sql); } if (strpos($limit, 'FETCH') !== false) { return trim("SELECT {$fields} FROM {$table} {$alias} {$joins} {$conditions} {$group} {$order} {$limit}"); } return trim("SELECT {$limit} {$fields} FROM {$table} {$alias} {$joins} {$conditions} {$group} {$order}"); case "schema": extract($data); foreach ($indexes as $i => $index) { if (preg_match('/PRIMARY KEY/', $index)) { unset($indexes[$i]); break; } } foreach (array('columns', 'indexes') as $var) { if (is_array(${$var})) { ${$var} = "\t" . implode(",\n\t", array_filter(${$var})); } } return trim("CREATE TABLE {$table} (\n{$columns});\n{$indexes}"); default: return parent::renderStatement($type, $data); } } /** * Returns a quoted and escaped string of $data for use in an SQL statement. * * @param string $data String to be prepared for use in an SQL statement * @param string $column The column into which this data will be inserted * @param bool $null Column allows NULL values * @return string Quoted and escaped data */ public function value($data, $column = null, $null = true) { if ($data === null || is_array($data) || is_object($data)) { return parent::value($data, $column, $null); } if (in_array($data, array('{$__cakeID__$}', '{$__cakeForeignKey__$}'), true)) { return $data; } if (empty($column)) { $column = $this->introspectType($data); } switch ($column) { case 'string': case 'text': return 'N' . $this->_connection->quote($data, PDO::PARAM_STR); default: return parent::value($data, $column, $null); } } /** * Returns an array of all result rows for a given SQL query. * Returns false if no rows matched. * * @param Model $model The model to read from * @param array $queryData The query data * @param int $recursive How many layers to go. * @return array|false Array of resultset rows, or false if no rows matched */ public function read(Model $model, $queryData = array(), $recursive = null) { $results = parent::read($model, $queryData, $recursive); $this->_fieldMappings = array(); return $results; } /** * Fetches the next row from the current result set. * Eats the magic ROW_COUNTER variable. * * @return mixed */ public function fetchResult() { if ($row = $this->_result->fetch(PDO::FETCH_NUM)) { $resultRow = array(); foreach ($this->map as $col => $meta) { list($table, $column, $type) = $meta; if ($table === 0 && $column === static::ROW_COUNTER) { continue; } $resultRow[$table][$column] = $row[$col]; if ($type === 'boolean' && $row[$col] !== null) { $resultRow[$table][$column] = $this->boolean($resultRow[$table][$column]); } } return $resultRow; } $this->_result->closeCursor(); return false; } /** * Inserts multiple values into a table * * @param string $table The table to insert into. * @param string $fields The fields to set. * @param array $values The values to set. * @return void */ public function insertMulti($table, $fields, $values) { $primaryKey = $this->_getPrimaryKey($table); $hasPrimaryKey = $primaryKey && ( (is_array($fields) && in_array($primaryKey, $fields) || (is_string($fields) && strpos($fields, $this->startQuote . $primaryKey . $this->endQuote) !== false)) ); if ($hasPrimaryKey) { $this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($table) . ' ON'); } parent::insertMulti($table, $fields, $values); if ($hasPrimaryKey) { $this->_execute('SET IDENTITY_INSERT ' . $this->fullTableName($table) . ' OFF'); } } /** * Generate a database-native column schema string * * @param array $column An array structured like the * following: array('name'=>'value', 'type'=>'value'[, options]), * where options can be 'default', 'length', or 'key'. * @return string */ public function buildColumn($column) { $result = parent::buildColumn($column); $result = preg_replace('/(bigint|int|integer)\([0-9]+\)/i', '$1', $result); $result = preg_replace('/(bit)\([0-9]+\)/i', '$1', $result); if (strpos($result, 'DEFAULT NULL') !== false) { if (isset($column['default']) && $column['default'] === '') { $result = str_replace('DEFAULT NULL', "DEFAULT ''", $result); } else { $result = str_replace('DEFAULT NULL', 'NULL', $result); } } elseif (array_keys($column) === array('type', 'name')) { $result .= ' NULL'; } elseif (strpos($result, "DEFAULT N'")) { $result = str_replace("DEFAULT N'", "DEFAULT '", $result); } return $result; } /** * Format indexes for create table * * @param array $indexes The indexes to build * @param string $table The table to make indexes for. * @return string */ public function buildIndex($indexes, $table = null) { $join = array(); foreach ($indexes as $name => $value) { if ($name === 'PRIMARY') { $join[] = 'PRIMARY KEY (' . $this->name($value['column']) . ')'; } elseif (isset($value['unique']) && $value['unique']) { $out = "ALTER TABLE {$table} ADD CONSTRAINT {$name} UNIQUE"; if (is_array($value['column'])) { $value['column'] = implode(', ', array_map(array(&$this, 'name'), $value['column'])); } else { $value['column'] = $this->name($value['column']); } $out .= "({$value['column']});"; $join[] = $out; } } return $join; } /** * Makes sure it will return the primary key * * @param Model|string $model Model instance of table name * @return string */ protected function _getPrimaryKey($model) { $schema = $this->describe($model); foreach ($schema as $field => $props) { if (isset($props['key']) && $props['key'] === 'primary') { return $field; } } return null; } /** * Returns number of affected rows in previous database operation. If no previous operation exists, * this returns false. * * @param mixed $source Unused * @return int Number of affected rows */ public function lastAffected($source = null) { $affected = parent::lastAffected(); if ($affected === null && $this->_lastAffected !== false) { return $this->_lastAffected; } return $affected; } /** * Executes given SQL statement. * * @param string $sql SQL statement * @param array $params list of params to be bound to query (supported only in select) * @param array $prepareOptions Options to be used in the prepare statement * @return mixed PDOStatement if query executes with no problem, true as the result of a successful, false on error * query returning no rows, such as a CREATE statement, false otherwise * @throws PDOException */ protected function _execute($sql, $params = array(), $prepareOptions = array()) { $this->_lastAffected = false; $sql = trim($sql); 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); } try { $this->_lastAffected = $this->_connection->exec($sql); if ($this->_lastAffected === false) { $this->_results = null; $error = $this->_connection->errorInfo(); $this->error = $error[2]; return false; } return true; } catch (PDOException $e) { if (isset($query->queryString)) { $e->queryString = $query->queryString; } else { $e->queryString = $sql; } throw $e; } } /** * Generate a "drop table" statement for the given table * * @param type $table Name of the table to drop * @return string Drop table SQL statement */ protected function _dropTable($table) { return "IF OBJECT_ID('" . $this->fullTableName($table, false) . "', 'U') IS NOT NULL DROP TABLE " . $this->fullTableName($table) . ";"; } /** * Gets the schema name * * @return string The schema name */ public function getSchemaName() { return $this->config['schema']; } } cakephp-2.8.0/lib/Cake/Model/Datasource/DboSource.php000066400000000000000000003143301265552240500223070ustar00rootroot00000000000000 'primary', 'MUL' => 'index', 'UNI' => 'unique'); /** * Database keyword used to assign aliases to identifiers. * * @var string */ public $alias = 'AS '; /** * Caches result from query parsing operations. Cached results for both DboSource::name() and * DboSource::conditions() will be stored here. Method caching uses `md5()`. If you have * problems with collisions, set DboSource::$cacheMethods to false. * * @var array */ public static $methodCache = array(); /** * Whether or not to cache the results of DboSource::name() and DboSource::conditions() * into the memory cache. Set to false to disable the use of the memory cache. * * @var bool */ public $cacheMethods = true; /** * Flag to support nested transactions. If it is set to false, you will be able to use * the transaction methods (begin/commit/rollback), but just the global transaction will * be executed. * * @var bool */ public $useNestedTransactions = false; /** * Print full query debug info? * * @var bool */ public $fullDebug = false; /** * String to hold how many rows were affected by the last SQL operation. * * @var string */ public $affected = null; /** * Number of rows in current resultset * * @var int */ public $numRows = null; /** * Time the last query took * * @var int */ public $took = null; /** * Result * * @var array */ protected $_result = null; /** * Queries count. * * @var int */ protected $_queriesCnt = 0; /** * Total duration of all queries. * * @var int */ protected $_queriesTime = null; /** * Log of queries executed by this DataSource * * @var array */ protected $_queriesLog = array(); /** * Maximum number of items in query log * * This is to prevent query log taking over too much memory. * * @var int */ protected $_queriesLogMax = 200; /** * Caches serialized results of executed queries * * @var array */ protected $_queryCache = array(); /** * A reference to the physical connection of this DataSource * * @var array */ protected $_connection = null; /** * The DataSource configuration key name * * @var string */ public $configKeyName = null; /** * The starting character that this DataSource uses for quoted identifiers. * * @var string */ public $startQuote = null; /** * The ending character that this DataSource uses for quoted identifiers. * * @var string */ public $endQuote = null; /** * The set of valid SQL operations usable in a WHERE statement * * @var array */ protected $_sqlOps = array('like', 'ilike', 'rlike', 'or', 'not', 'in', 'between', 'regexp', 'similar to'); /** * Indicates the level of nested transactions * * @var int */ protected $_transactionNesting = 0; /** * Default fields that are used by the DBO * * @var array */ protected $_queryDefaults = array( 'conditions' => array(), 'fields' => null, 'table' => null, 'alias' => null, 'order' => null, 'limit' => null, 'joins' => array(), 'group' => null, 'offset' => null ); /** * Separator string for virtualField composition * * @var string */ public $virtualFieldSeparator = '__'; /** * List of table engine specific parameters used on table creating * * @var array */ public $tableParameters = array(); /** * List of engine specific additional field parameters used on table creating * * @var array */ public $fieldParameters = array(); /** * Indicates whether there was a change on the cached results on the methods of this class * This will be used for storing in a more persistent cache * * @var bool */ protected $_methodCacheChange = false; /** * Constructor * * @param array $config Array of configuration information for the Datasource. * @param bool $autoConnect Whether or not the datasource should automatically connect. * @throws MissingConnectionException when a connection cannot be made. */ public function __construct($config = null, $autoConnect = true) { if (!isset($config['prefix'])) { $config['prefix'] = ''; } parent::__construct($config); $this->fullDebug = Configure::read('debug') > 1; if (!$this->enabled()) { throw new MissingConnectionException(array( 'class' => get_class($this), 'message' => __d('cake_dev', 'Selected driver is not enabled'), 'enabled' => false )); } if ($autoConnect) { $this->connect(); } } /** * Reconnects to database server with optional new settings * * @param array $config An array defining the new configuration settings * @return bool True on success, false on failure */ public function reconnect($config = array()) { $this->disconnect(); $this->setConfig($config); $this->_sources = null; return $this->connect(); } /** * Disconnects from database. * * @return bool Always true */ public function disconnect() { if ($this->_result instanceof PDOStatement) { $this->_result->closeCursor(); } $this->_connection = null; $this->connected = false; return true; } /** * Get the underlying connection object. * * @return PDO */ public function getConnection() { return $this->_connection; } /** * Gets the version string of the database server * * @return string The database version */ public function getVersion() { return $this->_connection->getAttribute(PDO::ATTR_SERVER_VERSION); } /** * Returns a quoted and escaped string of $data for use in an SQL statement. * * @param string $data String to be prepared for use in an SQL statement * @param string $column The column datatype into which this data will be inserted. * @param bool $null Column allows NULL values * @return string Quoted and escaped data */ public function value($data, $column = null, $null = true) { if (is_array($data) && !empty($data)) { return array_map( array(&$this, 'value'), $data, array_fill(0, count($data), $column) ); } elseif (is_object($data) && isset($data->type, $data->value)) { if ($data->type === 'identifier') { return $this->name($data->value); } elseif ($data->type === 'expression') { return $data->value; } } elseif (in_array($data, array('{$__cakeID__$}', '{$__cakeForeignKey__$}'), true)) { return $data; } if ($data === null || (is_array($data) && empty($data))) { return 'NULL'; } if (empty($column)) { $column = $this->introspectType($data); } switch ($column) { case 'binary': return $this->_connection->quote($data, PDO::PARAM_LOB); case 'boolean': return $this->_connection->quote($this->boolean($data, true), PDO::PARAM_BOOL); case 'string': case 'text': return $this->_connection->quote($data, PDO::PARAM_STR); default: if ($data === '') { return $null ? 'NULL' : '""'; } if (is_float($data)) { return str_replace(',', '.', strval($data)); } if ((is_int($data) || $data === '0') || ( is_numeric($data) && strpos($data, ',') === false && $data[0] != '0' && strpos($data, 'e') === false) ) { return $data; } return $this->_connection->quote($data); } } /** * Returns an object to represent a database identifier in a query. Expression objects * are not sanitized or escaped. * * @param string $identifier A SQL expression to be used as an identifier * @return stdClass An object representing a database identifier to be used in a query */ public function identifier($identifier) { $obj = new stdClass(); $obj->type = 'identifier'; $obj->value = $identifier; return $obj; } /** * Returns an object to represent a database expression in a query. Expression objects * are not sanitized or escaped. * * @param string $expression An arbitrary SQL expression to be inserted into a query. * @return stdClass An object representing a database expression to be used in a query */ public function expression($expression) { $obj = new stdClass(); $obj->type = 'expression'; $obj->value = $expression; return $obj; } /** * Executes given SQL statement. * * @param string $sql SQL statement * @param array $params Additional options for the query. * @return mixed Resource or object representing the result set, or false on failure */ public function rawQuery($sql, $params = array()) { $this->took = $this->numRows = false; return $this->execute($sql, array(), $params); } /** * Queries the database with given SQL statement, and obtains some metadata about the result * (rows affected, timing, any errors, number of rows in resultset). The query is also logged. * If Configure::read('debug') is set, the log is shown all the time, else it is only shown on errors. * * ### Options * * - log - Whether or not the query should be logged to the memory log. * * @param string $sql SQL statement * @param array $options The options for executing the query. * @param array $params values to be bound to the query. * @return mixed Resource or object representing the result set, or false on failure */ public function execute($sql, $options = array(), $params = array()) { $options += array('log' => $this->fullDebug); $t = microtime(true); $this->_result = $this->_execute($sql, $params); if ($options['log']) { $this->took = round((microtime(true) - $t) * 1000, 0); $this->numRows = $this->affected = $this->lastAffected(); $this->logQuery($sql, $params); } return $this->_result; } /** * Executes given SQL statement. * * @param string $sql SQL statement * @param array $params list of params to be bound to query * @param array $prepareOptions Options to be used in the prepare statement * @return mixed PDOStatement if query executes with no problem, true as the result of a successful, false on error * query returning no rows, such as a CREATE statement, false otherwise * @throws PDOException */ protected function _execute($sql, $params = array(), $prepareOptions = array()) { $sql = trim($sql); if (preg_match('/^(?:CREATE|ALTER|DROP)\s+(?:TABLE|INDEX)/i', $sql)) { $statements = array_filter(explode(';', $sql)); if (count($statements) > 1) { $result = array_map(array($this, '_execute'), $statements); return array_search(false, $result) === false; } } try { $query = $this->_connection->prepare($sql, $prepareOptions); $query->setFetchMode(PDO::FETCH_LAZY); if (!$query->execute($params)) { $this->_results = $query; $query->closeCursor(); return false; } if (!$query->columnCount()) { $query->closeCursor(); if (!$query->rowCount()) { return true; } } return $query; } catch (PDOException $e) { if (isset($query->queryString)) { $e->queryString = $query->queryString; } else { $e->queryString = $sql; } throw $e; } } /** * Returns a formatted error message from previous database operation. * * @param PDOStatement $query the query to extract the error from if any * @return string Error message with error number */ public function lastError(PDOStatement $query = null) { if ($query) { $error = $query->errorInfo(); } else { $error = $this->_connection->errorInfo(); } if (empty($error[2])) { return null; } return $error[1] . ': ' . $error[2]; } /** * Returns number of affected rows in previous database operation. If no previous operation exists, * this returns false. * * @param mixed $source The source to check. * @return int Number of affected rows */ public function lastAffected($source = null) { if ($this->hasResult()) { return $this->_result->rowCount(); } return 0; } /** * Returns number of rows in previous resultset. If no previous resultset exists, * this returns false. * * @param mixed $source Not used * @return int Number of rows in resultset */ public function lastNumRows($source = null) { return $this->lastAffected(); } /** * DataSource Query abstraction * * @return resource Result resource identifier. */ public function query() { $args = func_get_args(); $fields = null; $order = null; $limit = null; $page = null; $recursive = null; if (count($args) === 1) { return $this->fetchAll($args[0]); } elseif (count($args) > 1 && preg_match('/^find(\w*)By(.+)/', $args[0], $matches)) { $params = $args[1]; $findType = lcfirst($matches[1]); $field = Inflector::underscore($matches[2]); $or = (strpos($field, '_or_') !== false); if ($or) { $field = explode('_or_', $field); } else { $field = explode('_and_', $field); } $off = count($field) - 1; if (isset($params[1 + $off])) { $fields = $params[1 + $off]; } if (isset($params[2 + $off])) { $order = $params[2 + $off]; } if (!array_key_exists(0, $params)) { return false; } $c = 0; $conditions = array(); foreach ($field as $f) { $conditions[$args[2]->alias . '.' . $f] = $params[$c++]; } if ($or) { $conditions = array('OR' => $conditions); } if ($findType !== 'first' && $findType !== '') { if (isset($params[3 + $off])) { $limit = $params[3 + $off]; } if (isset($params[4 + $off])) { $page = $params[4 + $off]; } if (isset($params[5 + $off])) { $recursive = $params[5 + $off]; } return $args[2]->find($findType, compact('conditions', 'fields', 'order', 'limit', 'page', 'recursive')); } if (isset($params[3 + $off])) { $recursive = $params[3 + $off]; } return $args[2]->find('first', compact('conditions', 'fields', 'order', 'recursive')); } if (isset($args[1]) && $args[1] === true) { return $this->fetchAll($args[0], true); } elseif (isset($args[1]) && !is_array($args[1])) { return $this->fetchAll($args[0], false); } elseif (isset($args[1]) && is_array($args[1])) { if (isset($args[2])) { $cache = $args[2]; } else { $cache = true; } return $this->fetchAll($args[0], $args[1], array('cache' => $cache)); } } /** * Returns a row from current resultset as an array * * @param string $sql Some SQL to be executed. * @return array The fetched row as an array */ public function fetchRow($sql = null) { if (is_string($sql) && strlen($sql) > 5 && !$this->execute($sql)) { return null; } if ($this->hasResult()) { $this->resultSet($this->_result); $resultRow = $this->fetchResult(); if (isset($resultRow[0])) { $this->fetchVirtualField($resultRow); } return $resultRow; } return null; } /** * Returns an array of all result rows for a given SQL query. * * Returns false if no rows matched. * * ### Options * * - `cache` - Returns the cached version of the query, if exists and stores the result in cache. * This is a non-persistent cache, and only lasts for a single request. This option * defaults to true. If you are directly calling this method, you can disable caching * by setting $options to `false` * * @param string $sql SQL statement * @param array|bool $params Either parameters to be bound as values for the SQL statement, * or a boolean to control query caching. * @param array $options additional options for the query. * @return bool|array Array of resultset rows, or false if no rows matched */ public function fetchAll($sql, $params = array(), $options = array()) { if (is_string($options)) { $options = array('modelName' => $options); } if (is_bool($params)) { $options['cache'] = $params; $params = array(); } $options += array('cache' => true); $cache = $options['cache']; if ($cache && ($cached = $this->getQueryCache($sql, $params)) !== false) { return $cached; } $result = $this->execute($sql, array(), $params); if ($result) { $out = array(); if ($this->hasResult()) { $first = $this->fetchRow(); if ($first) { $out[] = $first; } while ($item = $this->fetchResult()) { if (isset($item[0])) { $this->fetchVirtualField($item); } $out[] = $item; } } if (!is_bool($result) && $cache) { $this->_writeQueryCache($sql, $out, $params); } if (empty($out) && is_bool($this->_result)) { return $this->_result; } return $out; } return false; } /** * Fetches the next row from the current result set * * @return bool */ public function fetchResult() { return false; } /** * Modifies $result array to place virtual fields in model entry where they belongs to * * @param array &$result Reference to the fetched row * @return void */ public function fetchVirtualField(&$result) { if (isset($result[0]) && is_array($result[0])) { foreach ($result[0] as $field => $value) { if (strpos($field, $this->virtualFieldSeparator) === false) { continue; } list($alias, $virtual) = explode($this->virtualFieldSeparator, $field); if (!ClassRegistry::isKeySet($alias)) { return; } $Model = ClassRegistry::getObject($alias); if ($Model->isVirtualField($virtual)) { $result[$alias][$virtual] = $value; unset($result[0][$field]); } } if (empty($result[0])) { unset($result[0]); } } } /** * Returns a single field of the first of query results for a given SQL query, or false if empty. * * @param string $name The name of the field to get. * @param string $sql The SQL query. * @return mixed Value of field read, or false if not found. */ public function field($name, $sql) { $data = $this->fetchRow($sql); if (empty($data[$name])) { return false; } return $data[$name]; } /** * Empties the method caches. * These caches are used by DboSource::name() and DboSource::conditions() * * @return void */ public function flushMethodCache() { $this->_methodCacheChange = true; static::$methodCache = array(); } /** * Cache a value into the methodCaches. Will respect the value of DboSource::$cacheMethods. * Will retrieve a value from the cache if $value is null. * * If caching is disabled and a write is attempted, the $value will be returned. * A read will either return the value or null. * * @param string $method Name of the method being cached. * @param string $key The key name for the cache operation. * @param mixed $value The value to cache into memory. * @return mixed Either null on failure, or the value if its set. */ public function cacheMethod($method, $key, $value = null) { if ($this->cacheMethods === false) { return $value; } if (!$this->_methodCacheChange && empty(static::$methodCache)) { static::$methodCache = (array)Cache::read('method_cache', '_cake_core_'); } if ($value === null) { return (isset(static::$methodCache[$method][$key])) ? static::$methodCache[$method][$key] : null; } $this->_methodCacheChange = true; return static::$methodCache[$method][$key] = $value; } /** * Returns a quoted name of $data for use in an SQL statement. * Strips fields out of SQL functions before quoting. * * Results of this method are stored in a memory cache. This improves performance, but * because the method uses a hashing algorithm it can have collisions. * Setting DboSource::$cacheMethods to false will disable the memory cache. * * @param mixed $data Either a string with a column to quote. An array of columns to quote or an * object from DboSource::expression() or DboSource::identifier() * @return string SQL field */ public function name($data) { if (is_object($data) && isset($data->type)) { return $data->value; } if ($data === '*') { return '*'; } if (is_array($data)) { foreach ($data as $i => $dataItem) { $data[$i] = $this->name($dataItem); } return $data; } $cacheKey = md5($this->startQuote . $data . $this->endQuote); if ($return = $this->cacheMethod(__FUNCTION__, $cacheKey)) { return $return; } $data = trim($data); if (preg_match('/^[\w-]+(?:\.[^ \*]*)*$/', $data)) { // string, string.string if (strpos($data, '.') === false) { // string return $this->cacheMethod(__FUNCTION__, $cacheKey, $this->startQuote . $data . $this->endQuote); } $items = explode('.', $data); return $this->cacheMethod(__FUNCTION__, $cacheKey, $this->startQuote . implode($this->endQuote . '.' . $this->startQuote, $items) . $this->endQuote ); } if (preg_match('/^[\w-]+\.\*$/', $data)) { // string.* return $this->cacheMethod(__FUNCTION__, $cacheKey, $this->startQuote . str_replace('.*', $this->endQuote . '.*', $data) ); } if (preg_match('/^([\w-]+)\((.*)\)$/', $data, $matches)) { // Functions return $this->cacheMethod(__FUNCTION__, $cacheKey, $matches[1] . '(' . $this->name($matches[2]) . ')' ); } if (preg_match('/^([\w-]+(\.[\w-]+|\(.*\))*)\s+' . preg_quote($this->alias) . '\s*([\w-]+)$/i', $data, $matches)) { return $this->cacheMethod( __FUNCTION__, $cacheKey, preg_replace( '/\s{2,}/', ' ', $this->name($matches[1]) . ' ' . $this->alias . ' ' . $this->name($matches[3]) ) ); } if (preg_match('/^[\w-_\s]*[\w-_]+/', $data)) { return $this->cacheMethod(__FUNCTION__, $cacheKey, $this->startQuote . $data . $this->endQuote); } return $this->cacheMethod(__FUNCTION__, $cacheKey, $data); } /** * Checks if the source is connected to the database. * * @return bool True if the database is connected, else false */ public function isConnected() { if ($this->_connection === null) { $connected = false; } else { try { $connected = $this->_connection->query('SELECT 1'); } catch (Exception $e) { $connected = false; } } $this->connected = !empty($connected); return $this->connected; } /** * Checks if the result is valid * * @return bool True if the result is valid else false */ public function hasResult() { return $this->_result instanceof PDOStatement; } /** * Get the query log as an array. * * @param bool $sorted Get the queries sorted by time taken, defaults to false. * @param bool $clear If True the existing log will cleared. * @return array Array of queries run as an array */ public function getLog($sorted = false, $clear = true) { if ($sorted) { $log = sortByKey($this->_queriesLog, 'took', 'desc', SORT_NUMERIC); } else { $log = $this->_queriesLog; } if ($clear) { $this->_queriesLog = array(); } return array('log' => $log, 'count' => $this->_queriesCnt, 'time' => $this->_queriesTime); } /** * Outputs the contents of the queries log. If in a non-CLI environment the sql_log element * will be rendered and output. If in a CLI environment, a plain text log is generated. * * @param bool $sorted Get the queries sorted by time taken, defaults to false. * @return void */ public function showLog($sorted = false) { $log = $this->getLog($sorted, false); if (empty($log['log'])) { return; } if (PHP_SAPI !== 'cli') { $controller = null; $View = new View($controller, false); $View->set('sqlLogs', array($this->configKeyName => $log)); echo $View->element('sql_dump', array('_forced_from_dbo_' => true)); } else { foreach ($log['log'] as $k => $i) { print (($k + 1) . ". {$i['query']}\n"); } } } /** * Log given SQL query. * * @param string $sql SQL statement * @param array $params Values binded to the query (prepared statements) * @return void */ public function logQuery($sql, $params = array()) { $this->_queriesCnt++; $this->_queriesTime += $this->took; $this->_queriesLog[] = array( 'query' => $sql, 'params' => $params, 'affected' => $this->affected, 'numRows' => $this->numRows, 'took' => $this->took ); if (count($this->_queriesLog) > $this->_queriesLogMax) { array_shift($this->_queriesLog); } } /** * Gets full table name including prefix * * @param Model|string $model Either a Model object or a string table name. * @param bool $quote Whether you want the table name quoted. * @param bool $schema Whether you want the schema name included. * @return string Full quoted table name */ public function fullTableName($model, $quote = true, $schema = true) { if (is_object($model)) { $schemaName = $model->schemaName; $table = $model->tablePrefix . $model->table; } elseif (!empty($this->config['prefix']) && strpos($model, $this->config['prefix']) !== 0) { $table = $this->config['prefix'] . strval($model); } else { $table = strval($model); } if ($schema && !isset($schemaName)) { $schemaName = $this->getSchemaName(); } if ($quote) { if ($schema && !empty($schemaName)) { if (strstr($table, '.') === false) { return $this->name($schemaName) . '.' . $this->name($table); } } return $this->name($table); } if ($schema && !empty($schemaName)) { if (strstr($table, '.') === false) { return $schemaName . '.' . $table; } } return $table; } /** * The "C" in CRUD * * Creates new records in the database. * * @param Model $Model Model object that the record is for. * @param array $fields An array of field names to insert. If null, $Model->data will be * used to generate field names. * @param array $values An array of values with keys matching the fields. If null, $Model->data will * be used to generate values. * @return bool Success */ public function create(Model $Model, $fields = null, $values = null) { $id = null; if (!$fields) { unset($fields, $values); $fields = array_keys($Model->data); $values = array_values($Model->data); } $count = count($fields); for ($i = 0; $i < $count; $i++) { $schema = $Model->schema(); $valueInsert[] = $this->value($values[$i], $Model->getColumnType($fields[$i]), isset($schema[$fields[$i]]) ? $schema[$fields[$i]]['null'] : true); $fieldInsert[] = $this->name($fields[$i]); if ($fields[$i] === $Model->primaryKey) { $id = $values[$i]; } } $query = array( 'table' => $this->fullTableName($Model), 'fields' => implode(', ', $fieldInsert), 'values' => implode(', ', $valueInsert) ); if ($this->execute($this->renderStatement('create', $query))) { if (empty($id)) { $id = $this->lastInsertId($this->fullTableName($Model, false, false), $Model->primaryKey); } $Model->setInsertID($id); $Model->id = $id; return true; } $Model->onError(); return false; } /** * The "R" in CRUD * * Reads record(s) from the database. * * @param Model $Model A Model object that the query is for. * @param array $queryData An array of queryData information containing keys similar to Model::find(). * @param int $recursive Number of levels of association * @return mixed boolean false on error/failure. An array of results on success. */ public function read(Model $Model, $queryData = array(), $recursive = null) { $queryData = $this->_scrubQueryData($queryData); $array = array('callbacks' => $queryData['callbacks']); if ($recursive === null && isset($queryData['recursive'])) { $recursive = $queryData['recursive']; } if ($recursive !== null) { $modelRecursive = $Model->recursive; $Model->recursive = $recursive; } if (!empty($queryData['fields'])) { $noAssocFields = true; $queryData['fields'] = $this->fields($Model, null, $queryData['fields']); } else { $noAssocFields = false; $queryData['fields'] = $this->fields($Model); } if ($Model->recursive === -1) { // Primary model data only, no joins. $associations = array(); } else { $associations = $Model->associations(); if ($Model->recursive === 0) { // Primary model data and its domain. unset($associations[2], $associations[3]); } } $originalJoins = $queryData['joins']; $queryData['joins'] = array(); // Generate hasOne and belongsTo associations inside $queryData $linkedModels = array(); foreach ($associations as $type) { if ($type !== 'hasOne' && $type !== 'belongsTo') { continue; } foreach ($Model->{$type} as $assoc => $assocData) { $LinkModel = $Model->{$assoc}; if ($Model->useDbConfig !== $LinkModel->useDbConfig) { continue; } if ($noAssocFields) { $assocData['fields'] = false; } $external = isset($assocData['external']); if ($this->generateAssociationQuery($Model, $LinkModel, $type, $assoc, $assocData, $queryData, $external) === true) { $linkedModels[$type . '/' . $assoc] = true; } } } if (!empty($originalJoins)) { $queryData['joins'] = array_merge($queryData['joins'], $originalJoins); } // Build SQL statement with the primary model, plus hasOne and belongsTo associations $query = $this->buildAssociationQuery($Model, $queryData); $resultSet = $this->fetchAll($query, $Model->cacheQueries); unset($query); if ($resultSet === false) { $Model->onError(); return false; } $filtered = array(); // Deep associations if ($Model->recursive > -1) { $joined = array(); if (isset($queryData['joins'][0]['alias'])) { $joined[$Model->alias] = (array)Hash::extract($queryData['joins'], '{n}.alias'); } foreach ($associations as $type) { foreach ($Model->{$type} as $assoc => $assocData) { $LinkModel = $Model->{$assoc}; if (!isset($linkedModels[$type . '/' . $assoc])) { $db = $Model->useDbConfig === $LinkModel->useDbConfig ? $this : $LinkModel->getDataSource(); } elseif ($Model->recursive > 1) { $db = $this; } if (isset($db) && method_exists($db, 'queryAssociation')) { $stack = array($assoc); $stack['_joined'] = $joined; $db->queryAssociation($Model, $LinkModel, $type, $assoc, $assocData, $array, true, $resultSet, $Model->recursive - 1, $stack); unset($db); if ($type === 'hasMany' || $type === 'hasAndBelongsToMany') { $filtered[] = $assoc; } } } } } if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') { $this->_filterResults($resultSet, $Model, $filtered); } if ($recursive !== null) { $Model->recursive = $modelRecursive; } return $resultSet; } /** * Passes association results through afterFind filters of the corresponding model. * * The primary model is always excluded, because the filtering is later done by Model::_filterResults(). * * @param array &$resultSet Reference of resultset to be filtered. * @param Model $Model Instance of model to operate against. * @param array $filtered List of classes already filtered, to be skipped. * @return array Array of results that have been filtered through $Model->afterFind. */ protected function _filterResults(&$resultSet, Model $Model, $filtered = array()) { if (!is_array($resultSet)) { return array(); } $current = reset($resultSet); if (!is_array($current)) { return array(); } $keys = array_diff(array_keys($current), $filtered, array($Model->alias)); $filtering = array(); foreach ($keys as $className) { if (!isset($Model->{$className}) || !is_object($Model->{$className})) { continue; } $LinkedModel = $Model->{$className}; $filtering[] = $className; foreach ($resultSet as $key => &$result) { $data = $LinkedModel->afterFind(array(array($className => $result[$className])), false); if (isset($data[0][$className])) { $result[$className] = $data[0][$className]; } else { unset($resultSet[$key]); } } } return $filtering; } /** * Passes association results through afterFind filters of the corresponding model. * * Similar to DboSource::_filterResults(), but this filters only specified models. * The primary model can not be specified, because this call DboSource::_filterResults() internally. * * @param array &$resultSet Reference of resultset to be filtered. * @param Model $Model Instance of model to operate against. * @param array $toBeFiltered List of classes to be filtered. * @return array Array of results that have been filtered through $Model->afterFind. */ protected function _filterResultsInclusive(&$resultSet, Model $Model, $toBeFiltered = array()) { $exclude = array(); if (is_array($resultSet)) { $current = reset($resultSet); if (is_array($current)) { $exclude = array_diff(array_keys($current), $toBeFiltered); } } return $this->_filterResults($resultSet, $Model, $exclude); } /** * Queries associations. * * Used to fetch results on recursive models. * * - 'hasMany' associations with no limit set: * Fetch, filter and merge is done recursively for every level. * * - 'hasAndBelongsToMany' associations: * Fetch and filter is done unaffected by the (recursive) level set. * * @param Model $Model Primary Model object. * @param Model $LinkModel Linked model object. * @param string $type Association type, one of the model association types ie. hasMany. * @param string $association Association name. * @param array $assocData Association data. * @param array &$queryData An array of queryData information containing keys similar to Model::find(). * @param bool $external Whether or not the association query is on an external datasource. * @param array &$resultSet Existing results. * @param int $recursive Number of levels of association. * @param array $stack A list with joined models. * @return mixed * @throws CakeException when results cannot be created. */ public function queryAssociation(Model $Model, Model $LinkModel, $type, $association, $assocData, &$queryData, $external, &$resultSet, $recursive, $stack) { if (isset($stack['_joined'])) { $joined = $stack['_joined']; unset($stack['_joined']); } $queryTemplate = $this->generateAssociationQuery($Model, $LinkModel, $type, $association, $assocData, $queryData, $external); if (empty($queryTemplate)) { return null; } if (!is_array($resultSet)) { throw new CakeException(__d('cake_dev', 'Error in Model %s', get_class($Model))); } if ($type === 'hasMany' && empty($assocData['limit']) && !empty($assocData['foreignKey'])) { // 'hasMany' associations with no limit set. $assocIds = array(); foreach ($resultSet as $result) { $assocIds[] = $this->insertQueryData('{$__cakeID__$}', $result, $association, $Model, $stack); } $assocIds = array_filter($assocIds); // Fetch $assocResultSet = array(); if (!empty($assocIds)) { $assocResultSet = $this->_fetchHasMany($Model, $queryTemplate, $assocIds); } // Recursively query associations if ($recursive > 0 && !empty($assocResultSet) && is_array($assocResultSet)) { foreach ($LinkModel->associations() as $type1) { foreach ($LinkModel->{$type1} as $assoc1 => $assocData1) { $DeepModel = $LinkModel->{$assoc1}; $tmpStack = $stack; $tmpStack[] = $assoc1; $db = $LinkModel->useDbConfig === $DeepModel->useDbConfig ? $this : $DeepModel->getDataSource(); $db->queryAssociation($LinkModel, $DeepModel, $type1, $assoc1, $assocData1, $queryData, true, $assocResultSet, $recursive - 1, $tmpStack); } } } // Filter if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') { $this->_filterResultsInclusive($assocResultSet, $Model, array($association)); } // Merge return $this->_mergeHasMany($resultSet, $assocResultSet, $association, $Model); } elseif ($type === 'hasAndBelongsToMany') { // 'hasAndBelongsToMany' associations. $assocIds = array(); foreach ($resultSet as $result) { $assocIds[] = $this->insertQueryData('{$__cakeID__$}', $result, $association, $Model, $stack); } $assocIds = array_filter($assocIds); // Fetch $assocResultSet = array(); if (!empty($assocIds)) { $assocResultSet = $this->_fetchHasAndBelongsToMany($Model, $queryTemplate, $assocIds, $association); } $habtmAssocData = $Model->hasAndBelongsToMany[$association]; $foreignKey = $habtmAssocData['foreignKey']; $joinKeys = array($foreignKey, $habtmAssocData['associationForeignKey']); list($with, $habtmFields) = $Model->joinModel($habtmAssocData['with'], $joinKeys); $habtmFieldsCount = count($habtmFields); // Filter if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') { $this->_filterResultsInclusive($assocResultSet, $Model, array($association, $with)); } } $modelAlias = $Model->alias; $primaryKey = $Model->primaryKey; $selfJoin = ($Model->name === $LinkModel->name); foreach ($resultSet as &$row) { if ($type === 'hasOne' || $type === 'belongsTo' || $type === 'hasMany') { $assocResultSet = array(); $prefetched = false; if (($type === 'hasOne' || $type === 'belongsTo') && isset($row[$LinkModel->alias], $joined[$Model->alias]) && in_array($LinkModel->alias, $joined[$Model->alias]) ) { $joinedData = Hash::filter($row[$LinkModel->alias]); if (!empty($joinedData)) { $assocResultSet[0] = array($LinkModel->alias => $row[$LinkModel->alias]); } $prefetched = true; } else { $query = $this->insertQueryData($queryTemplate, $row, $association, $Model, $stack); if ($query !== false) { $assocResultSet = $this->fetchAll($query, $Model->cacheQueries); } } } if (!empty($assocResultSet) && is_array($assocResultSet)) { if ($recursive > 0) { foreach ($LinkModel->associations() as $type1) { foreach ($LinkModel->{$type1} as $assoc1 => $assocData1) { $DeepModel = $LinkModel->{$assoc1}; if ($type1 === 'belongsTo' || ($type === 'belongsTo' && $DeepModel->alias === $modelAlias) || ($DeepModel->alias !== $modelAlias) ) { $tmpStack = $stack; $tmpStack[] = $assoc1; $db = $LinkModel->useDbConfig === $DeepModel->useDbConfig ? $this : $DeepModel->getDataSource(); $db->queryAssociation($LinkModel, $DeepModel, $type1, $assoc1, $assocData1, $queryData, true, $assocResultSet, $recursive - 1, $tmpStack); } } } } if ($type === 'hasAndBelongsToMany') { $merge = array(); foreach ($assocResultSet as $data) { if (isset($data[$with]) && $data[$with][$foreignKey] === $row[$modelAlias][$primaryKey]) { if ($habtmFieldsCount <= 2) { unset($data[$with]); } $merge[] = $data; } } if (empty($merge) && !isset($row[$association])) { $row[$association] = $merge; } else { $this->_mergeAssociation($row, $merge, $association, $type); } } else { if (!$prefetched && $LinkModel->useConsistentAfterFind) { if ($queryData['callbacks'] === true || $queryData['callbacks'] === 'after') { $this->_filterResultsInclusive($assocResultSet, $Model, array($association)); } } $this->_mergeAssociation($row, $assocResultSet, $association, $type, $selfJoin); } if ($type !== 'hasAndBelongsToMany' && isset($row[$association]) && !$prefetched && !$LinkModel->useConsistentAfterFind) { $row[$association] = $LinkModel->afterFind($row[$association], false); } } else { $tempArray[0][$association] = false; $this->_mergeAssociation($row, $tempArray, $association, $type, $selfJoin); } } } /** * Fetch 'hasMany' associations. * * This is just a proxy to maintain BC. * * @param Model $Model Primary model object. * @param string $query Association query template. * @param array $ids Array of IDs of associated records. * @return array Association results. * @see DboSource::_fetchHasMany() */ public function fetchAssociated(Model $Model, $query, $ids) { return $this->_fetchHasMany($Model, $query, $ids); } /** * Fetch 'hasMany' associations. * * @param Model $Model Primary model object. * @param string $query Association query template. * @param array $ids Array of IDs of associated records. * @return array Association results. */ protected function _fetchHasMany(Model $Model, $query, $ids) { $ids = array_unique($ids); if (count($ids) > 1) { $query = str_replace('= ({$__cakeID__$}', 'IN ({$__cakeID__$}', $query); } $query = str_replace('{$__cakeID__$}', implode(', ', $ids), $query); return $this->fetchAll($query, $Model->cacheQueries); } /** * Fetch 'hasAndBelongsToMany' associations. * * @param Model $Model Primary model object. * @param string $query Association query. * @param array $ids Array of IDs of associated records. * @param string $association Association name. * @return array Association results. */ protected function _fetchHasAndBelongsToMany(Model $Model, $query, $ids, $association) { $ids = array_unique($ids); if (count($ids) > 1) { $query = str_replace('{$__cakeID__$}', '(' . implode(', ', $ids) . ')', $query); $query = str_replace('= (', 'IN (', $query); } else { $query = str_replace('{$__cakeID__$}', $ids[0], $query); } $query = str_replace(' WHERE 1 = 1', '', $query); return $this->fetchAll($query, $Model->cacheQueries); } /** * Merge the results of 'hasMany' associations. * * Note: this function also deals with the formatting of the data. * * @param array &$resultSet Data to merge into. * @param array $assocResultSet Data to merge. * @param string $association Name of Model being merged. * @param Model $Model Model being merged onto. * @return void */ protected function _mergeHasMany(&$resultSet, $assocResultSet, $association, Model $Model) { $modelAlias = $Model->alias; $primaryKey = $Model->primaryKey; $foreignKey = $Model->hasMany[$association]['foreignKey']; foreach ($resultSet as &$result) { if (!isset($result[$modelAlias])) { continue; } $resultPrimaryKey = $result[$modelAlias][$primaryKey]; $merged = array(); foreach ($assocResultSet as $data) { if ($resultPrimaryKey !== $data[$association][$foreignKey]) { continue; } if (count($data) > 1) { $data = array_merge($data[$association], $data); unset($data[$association]); foreach ($data as $key => $name) { if (is_numeric($key)) { $data[$association][] = $name; unset($data[$key]); } } $merged[] = $data; } else { $merged[] = $data[$association]; } } $result = Hash::mergeDiff($result, array($association => $merged)); } } /** * Merge association of merge into data * * @param array &$data The data to merge. * @param array &$merge The data to merge. * @param string $association The association name to merge. * @param string $type The type of association * @param bool $selfJoin Whether or not this is a self join. * @return void */ protected function _mergeAssociation(&$data, &$merge, $association, $type, $selfJoin = false) { if (isset($merge[0]) && !isset($merge[0][$association])) { $association = Inflector::pluralize($association); } $dataAssociation =& $data[$association]; if ($type === 'belongsTo' || $type === 'hasOne') { if (isset($merge[$association])) { $dataAssociation = $merge[$association][0]; } else { if (!empty($merge[0][$association])) { foreach ($merge[0] as $assoc => $data2) { if ($assoc !== $association) { $merge[0][$association][$assoc] = $data2; } } } if (!isset($dataAssociation)) { $dataAssociation = array(); if ($merge[0][$association]) { $dataAssociation = $merge[0][$association]; } } else { if (is_array($merge[0][$association])) { $mergeAssocTmp = array(); foreach ($dataAssociation as $k => $v) { if (!is_array($v)) { $dataAssocTmp[$k] = $v; } } foreach ($merge[0][$association] as $k => $v) { if (!is_array($v)) { $mergeAssocTmp[$k] = $v; } } $dataKeys = array_keys($data); $mergeKeys = array_keys($merge[0]); if ($mergeKeys[0] === $dataKeys[0] || $mergeKeys === $dataKeys) { $dataAssociation[$association] = $merge[0][$association]; } else { $diff = Hash::diff($dataAssocTmp, $mergeAssocTmp); $dataAssociation = array_merge($merge[0][$association], $diff); } } elseif ($selfJoin && array_key_exists($association, $merge[0])) { $dataAssociation = array_merge($dataAssociation, array($association => array())); } } } } else { if (isset($merge[0][$association]) && $merge[0][$association] === false) { if (!isset($dataAssociation)) { $dataAssociation = array(); } } else { foreach ($merge as $row) { $insert = array(); if (count($row) === 1) { $insert = $row[$association]; } elseif (isset($row[$association])) { $insert = array_merge($row[$association], $row); unset($insert[$association]); } if (empty($dataAssociation) || (isset($dataAssociation) && !in_array($insert, $dataAssociation, true))) { $dataAssociation[] = $insert; } } } } } /** * Prepares fields required by an SQL statement. * * When no fields are set, all the $Model fields are returned. * * @param Model $Model The model to prepare. * @param array $queryData An array of queryData information containing keys similar to Model::find(). * @return array Array containing SQL fields. */ public function prepareFields(Model $Model, $queryData) { if (empty($queryData['fields'])) { $queryData['fields'] = $this->fields($Model); } elseif (!empty($Model->hasMany) && $Model->recursive > -1) { // hasMany relationships need the $Model primary key. $assocFields = $this->fields($Model, null, "{$Model->alias}.{$Model->primaryKey}"); $passedFields = $queryData['fields']; if (count($passedFields) > 1 || (strpos($passedFields[0], $assocFields[0]) === false && !preg_match('/^[a-z]+\(/i', $passedFields[0])) ) { $queryData['fields'] = array_merge($passedFields, $assocFields); } } return array_unique($queryData['fields']); } /** * Builds an SQL statement. * * This is merely a convenient wrapper to DboSource::buildStatement(). * * @param Model $Model The model to build an association query for. * @param array $queryData An array of queryData information containing keys similar to Model::find(). * @return string String containing an SQL statement. * @see DboSource::buildStatement() */ public function buildAssociationQuery(Model $Model, $queryData) { $queryData = $this->_scrubQueryData($queryData); return $this->buildStatement( array( 'fields' => $this->prepareFields($Model, $queryData), 'table' => $this->fullTableName($Model), 'alias' => $Model->alias, 'limit' => $queryData['limit'], 'offset' => $queryData['offset'], 'joins' => $queryData['joins'], 'conditions' => $queryData['conditions'], 'order' => $queryData['order'], 'group' => $queryData['group'] ), $Model ); } /** * Generates a query or part of a query from a single model or two associated models. * * Builds a string containing an SQL statement template. * * @param Model $Model Primary Model object. * @param Model|null $LinkModel Linked model object. * @param string $type Association type, one of the model association types ie. hasMany. * @param string $association Association name. * @param array $assocData Association data. * @param array &$queryData An array of queryData information containing keys similar to Model::find(). * @param bool $external Whether or not the association query is on an external datasource. * @return mixed * String representing a query. * True, when $external is false and association $type is 'hasOne' or 'belongsTo'. */ public function generateAssociationQuery(Model $Model, $LinkModel, $type, $association, $assocData, &$queryData, $external) { $assocData = $this->_scrubQueryData($assocData); $queryData = $this->_scrubQueryData($queryData); if ($LinkModel === null) { return $this->buildStatement( array( 'fields' => array_unique($queryData['fields']), 'table' => $this->fullTableName($Model), 'alias' => $Model->alias, 'limit' => $queryData['limit'], 'offset' => $queryData['offset'], 'joins' => $queryData['joins'], 'conditions' => $queryData['conditions'], 'order' => $queryData['order'], 'group' => $queryData['group'] ), $Model ); } if ($external && !empty($assocData['finderQuery'])) { return $assocData['finderQuery']; } if ($type === 'hasMany' || $type === 'hasAndBelongsToMany') { if (empty($assocData['offset']) && !empty($assocData['page'])) { $assocData['offset'] = ($assocData['page'] - 1) * $assocData['limit']; } } switch ($type) { case 'hasOne': case 'belongsTo': $conditions = $this->_mergeConditions( $assocData['conditions'], $this->getConstraint($type, $Model, $LinkModel, $association, array_merge($assocData, compact('external'))) ); if ($external) { // Not self join if ($Model->name !== $LinkModel->name) { $modelAlias = $Model->alias; foreach ($conditions as $key => $condition) { if (is_numeric($key) && strpos($condition, $modelAlias . '.') !== false) { unset($conditions[$key]); } } } $query = array_merge($assocData, array( 'conditions' => $conditions, 'table' => $this->fullTableName($LinkModel), 'fields' => $this->fields($LinkModel, $association, $assocData['fields']), 'alias' => $association, 'group' => null )); } else { $join = array( 'table' => $LinkModel, 'alias' => $association, 'type' => isset($assocData['type']) ? $assocData['type'] : 'LEFT', 'conditions' => trim($this->conditions($conditions, true, false, $Model)) ); $fields = array(); if ($assocData['fields'] !== false) { $fields = $this->fields($LinkModel, $association, $assocData['fields']); } $queryData['fields'] = array_merge($this->prepareFields($Model, $queryData), $fields); if (!empty($assocData['order'])) { $queryData['order'][] = $assocData['order']; } if (!in_array($join, $queryData['joins'], true)) { $queryData['joins'][] = $join; } return true; } break; case 'hasMany': $assocData['fields'] = $this->fields($LinkModel, $association, $assocData['fields']); if (!empty($assocData['foreignKey'])) { $assocData['fields'] = array_merge($assocData['fields'], $this->fields($LinkModel, $association, array("{$association}.{$assocData['foreignKey']}"))); } $query = array( 'conditions' => $this->_mergeConditions($this->getConstraint('hasMany', $Model, $LinkModel, $association, $assocData), $assocData['conditions']), 'fields' => array_unique($assocData['fields']), 'table' => $this->fullTableName($LinkModel), 'alias' => $association, 'order' => $assocData['order'], 'limit' => $assocData['limit'], 'offset' => $assocData['offset'], 'group' => null ); break; case 'hasAndBelongsToMany': $joinFields = array(); $joinAssoc = null; if (isset($assocData['with']) && !empty($assocData['with'])) { $joinKeys = array($assocData['foreignKey'], $assocData['associationForeignKey']); list($with, $joinFields) = $Model->joinModel($assocData['with'], $joinKeys); $joinTbl = $Model->{$with}; $joinAlias = $joinTbl; if (is_array($joinFields) && !empty($joinFields)) { $joinAssoc = $joinAlias = $joinTbl->alias; $joinFields = $this->fields($joinTbl, $joinAlias, $joinFields); } else { $joinFields = array(); } } else { $joinTbl = $assocData['joinTable']; $joinAlias = $this->fullTableName($assocData['joinTable']); } $query = array( 'conditions' => $assocData['conditions'], 'limit' => $assocData['limit'], 'offset' => $assocData['offset'], 'table' => $this->fullTableName($LinkModel), 'alias' => $association, 'fields' => array_merge($this->fields($LinkModel, $association, $assocData['fields']), $joinFields), 'order' => $assocData['order'], 'group' => null, 'joins' => array(array( 'table' => $joinTbl, 'alias' => $joinAssoc, 'conditions' => $this->getConstraint('hasAndBelongsToMany', $Model, $LinkModel, $joinAlias, $assocData, $association) )) ); break; } if (isset($query)) { return $this->buildStatement($query, $Model); } return null; } /** * Returns a conditions array for the constraint between two models. * * @param string $type Association type. * @param Model $Model Primary Model object. * @param Model $LinkModel Linked model object. * @param string $association Association name. * @param array $assocData Association data. * @param string $association2 HABTM association name. * @return array Conditions array defining the constraint between $Model and $LinkModel. */ public function getConstraint($type, Model $Model, Model $LinkModel, $association, $assocData, $association2 = null) { $assocData += array('external' => false); if (empty($assocData['foreignKey'])) { return array(); } switch ($type) { case 'hasOne': if ($assocData['external']) { return array( "{$association}.{$assocData['foreignKey']}" => '{$__cakeID__$}' ); } else { return array( "{$association}.{$assocData['foreignKey']}" => $this->identifier("{$Model->alias}.{$Model->primaryKey}") ); } case 'belongsTo': if ($assocData['external']) { return array( "{$association}.{$LinkModel->primaryKey}" => '{$__cakeForeignKey__$}' ); } else { return array( "{$Model->alias}.{$assocData['foreignKey']}" => $this->identifier("{$association}.{$LinkModel->primaryKey}") ); } case 'hasMany': return array("{$association}.{$assocData['foreignKey']}" => array('{$__cakeID__$}')); case 'hasAndBelongsToMany': return array( array( "{$association}.{$assocData['foreignKey']}" => '{$__cakeID__$}' ), array( "{$association}.{$assocData['associationForeignKey']}" => $this->identifier("{$association2}.{$LinkModel->primaryKey}") ) ); } return array(); } /** * Builds and generates a JOIN condition from an array. Handles final clean-up before conversion. * * @param array $join An array defining a JOIN condition in a query. * @return string An SQL JOIN condition to be used in a query. * @see DboSource::renderJoinStatement() * @see DboSource::buildStatement() */ public function buildJoinStatement($join) { $data = array_merge(array( 'type' => null, 'alias' => null, 'table' => 'join_table', 'conditions' => '', ), $join); if (!empty($data['alias'])) { $data['alias'] = $this->alias . $this->name($data['alias']); } if (!empty($data['conditions'])) { $data['conditions'] = trim($this->conditions($data['conditions'], true, false)); } if (!empty($data['table']) && (!is_string($data['table']) || strpos($data['table'], '(') !== 0)) { $data['table'] = $this->fullTableName($data['table']); } return $this->renderJoinStatement($data); } /** * Builds and generates an SQL statement from an array. Handles final clean-up before conversion. * * @param array $query An array defining an SQL query. * @param Model $Model The model object which initiated the query. * @return string An executable SQL statement. * @see DboSource::renderStatement() */ public function buildStatement($query, Model $Model) { $query = array_merge($this->_queryDefaults, $query); if (!empty($query['joins'])) { $count = count($query['joins']); for ($i = 0; $i < $count; $i++) { if (is_array($query['joins'][$i])) { $query['joins'][$i] = $this->buildJoinStatement($query['joins'][$i]); } } } return $this->renderStatement('select', array( 'conditions' => $this->conditions($query['conditions'], true, true, $Model), 'fields' => implode(', ', $query['fields']), 'table' => $query['table'], 'alias' => $this->alias . $this->name($query['alias']), 'order' => $this->order($query['order'], 'ASC', $Model), 'limit' => $this->limit($query['limit'], $query['offset']), 'joins' => implode(' ', $query['joins']), 'group' => $this->group($query['group'], $Model) )); } /** * Renders a final SQL JOIN statement * * @param array $data The data to generate a join statement for. * @return string */ public function renderJoinStatement($data) { if (strtoupper($data['type']) === 'CROSS' || empty($data['conditions'])) { return "{$data['type']} JOIN {$data['table']} {$data['alias']}"; } return trim("{$data['type']} JOIN {$data['table']} {$data['alias']} ON ({$data['conditions']})"); } /** * Renders a final SQL statement by putting together the component parts in the correct order * * @param string $type type of query being run. e.g select, create, update, delete, schema, alter. * @param array $data Array of data to insert into the query. * @return string|null Rendered SQL expression to be run, otherwise null. */ public function renderStatement($type, $data) { extract($data); $aliases = null; switch (strtolower($type)) { case 'select': return trim("SELECT {$fields} FROM {$table} {$alias} {$joins} {$conditions} {$group} {$order} {$limit}"); case 'create': return "INSERT INTO {$table} ({$fields}) VALUES ({$values})"; case 'update': if (!empty($alias)) { $aliases = "{$this->alias}{$alias} {$joins} "; } return trim("UPDATE {$table} {$aliases}SET {$fields} {$conditions}"); case 'delete': if (!empty($alias)) { $aliases = "{$this->alias}{$alias} {$joins} "; } return trim("DELETE {$alias} FROM {$table} {$aliases}{$conditions}"); case 'schema': foreach (array('columns', 'indexes', 'tableParameters') as $var) { if (is_array(${$var})) { ${$var} = "\t" . implode(",\n\t", array_filter(${$var})); } else { ${$var} = ''; } } if (trim($indexes) !== '') { $columns .= ','; } return "CREATE TABLE {$table} (\n{$columns}{$indexes}) {$tableParameters};"; case 'alter': return null; } } /** * Merges a mixed set of string/array conditions. * * @param mixed $query The query to merge conditions for. * @param mixed $assoc The association names. * @return array */ protected function _mergeConditions($query, $assoc) { if (empty($assoc)) { return $query; } if (is_array($query)) { return array_merge((array)$assoc, $query); } if (!empty($query)) { $query = array($query); if (is_array($assoc)) { $query = array_merge($query, $assoc); } else { $query[] = $assoc; } return $query; } return $assoc; } /** * Generates and executes an SQL UPDATE statement for given model, fields, and values. * For databases that do not support aliases in UPDATE queries. * * @param Model $Model The model to update. * @param array $fields The fields to update * @param array $values The values fo the fields. * @param mixed $conditions The conditions for the update. When non-empty $values will not be quoted. * @return bool Success */ public function update(Model $Model, $fields = array(), $values = null, $conditions = null) { if (!$values) { $combined = $fields; } else { $combined = array_combine($fields, $values); } $fields = implode(', ', $this->_prepareUpdateFields($Model, $combined, empty($conditions))); $alias = $joins = null; $table = $this->fullTableName($Model); $conditions = $this->_matchRecords($Model, $conditions); if ($conditions === false) { return false; } $query = compact('table', 'alias', 'joins', 'fields', 'conditions'); if (!$this->execute($this->renderStatement('update', $query))) { $Model->onError(); return false; } return true; } /** * Quotes and prepares fields and values for an SQL UPDATE statement * * @param Model $Model The model to prepare fields for. * @param array $fields The fields to update. * @param bool $quoteValues If values should be quoted, or treated as SQL snippets * @param bool $alias Include the model alias in the field name * @return array Fields and values, quoted and prepared */ protected function _prepareUpdateFields(Model $Model, $fields, $quoteValues = true, $alias = false) { $quotedAlias = $this->startQuote . $Model->alias . $this->endQuote; $schema = $Model->schema(); $updates = array(); foreach ($fields as $field => $value) { if ($alias && strpos($field, '.') === false) { $quoted = $Model->escapeField($field); } elseif (!$alias && strpos($field, '.') !== false) { $quoted = $this->name(str_replace($quotedAlias . '.', '', str_replace( $Model->alias . '.', '', $field ))); } else { $quoted = $this->name($field); } if ($value === null) { $updates[] = $quoted . ' = NULL'; continue; } $update = $quoted . ' = '; if ($quoteValues) { $update .= $this->value($value, $Model->getColumnType($field), isset($schema[$field]) ? $schema[$field]['null'] : true); } elseif ($Model->getColumnType($field) === 'boolean' && (is_int($value) || is_bool($value))) { $update .= $this->boolean($value, true); } elseif (!$alias) { $update .= str_replace($quotedAlias . '.', '', str_replace( $Model->alias . '.', '', $value )); } else { $update .= $value; } $updates[] = $update; } return $updates; } /** * Generates and executes an SQL DELETE statement. * For databases that do not support aliases in UPDATE queries. * * @param Model $Model The model to delete from * @param mixed $conditions The conditions to use. If empty the model's primary key will be used. * @return bool Success */ public function delete(Model $Model, $conditions = null) { $alias = $joins = null; $table = $this->fullTableName($Model); $conditions = $this->_matchRecords($Model, $conditions); if ($conditions === false) { return false; } if ($this->execute($this->renderStatement('delete', compact('alias', 'table', 'joins', 'conditions'))) === false) { $Model->onError(); return false; } return true; } /** * Gets a list of record IDs for the given conditions. Used for multi-record updates and deletes * in databases that do not support aliases in UPDATE/DELETE queries. * * @param Model $Model The model to find matching records for. * @param mixed $conditions The conditions to match against. * @return array List of record IDs */ protected function _matchRecords(Model $Model, $conditions = null) { if ($conditions === true) { $conditions = $this->conditions(true); } elseif ($conditions === null) { $conditions = $this->conditions($this->defaultConditions($Model, $conditions, false), true, true, $Model); } else { $noJoin = true; foreach ($conditions as $field => $value) { $originalField = $field; if (strpos($field, '.') !== false) { list(, $field) = explode('.', $field); $field = ltrim($field, $this->startQuote); $field = rtrim($field, $this->endQuote); } if (!$Model->hasField($field)) { $noJoin = false; break; } if ($field !== $originalField) { $conditions[$field] = $value; unset($conditions[$originalField]); } } if ($noJoin === true) { return $this->conditions($conditions); } $idList = $Model->find('all', array( 'fields' => "{$Model->alias}.{$Model->primaryKey}", 'conditions' => $conditions )); if (empty($idList)) { return false; } $conditions = $this->conditions(array( $Model->primaryKey => Hash::extract($idList, "{n}.{$Model->alias}.{$Model->primaryKey}") )); } return $conditions; } /** * Returns an array of SQL JOIN conditions from a model's associations. * * @param Model $Model The model to get joins for.2 * @return array */ protected function _getJoins(Model $Model) { $join = array(); $joins = array_merge($Model->getAssociated('hasOne'), $Model->getAssociated('belongsTo')); foreach ($joins as $assoc) { if (!isset($Model->{$assoc})) { continue; } $LinkModel = $Model->{$assoc}; if ($Model->useDbConfig !== $LinkModel->useDbConfig) { continue; } $assocData = $Model->getAssociated($assoc); $join[] = $this->buildJoinStatement(array( 'table' => $LinkModel, 'alias' => $assoc, 'type' => isset($assocData['type']) ? $assocData['type'] : 'LEFT', 'conditions' => trim($this->conditions( $this->_mergeConditions($assocData['conditions'], $this->getConstraint($assocData['association'], $Model, $LinkModel, $assoc, $assocData)), true, false, $Model )) )); } return $join; } /** * Returns an SQL calculation, i.e. COUNT() or MAX() * * @param Model $Model The model to get a calculated field for. * @param string $func Lowercase name of SQL function, i.e. 'count' or 'max' * @param array $params Function parameters (any values must be quoted manually) * @return string An SQL calculation function */ public function calculate(Model $Model, $func, $params = array()) { $params = (array)$params; switch (strtolower($func)) { case 'count': if (!isset($params[0])) { $params[0] = '*'; } if (!isset($params[1])) { $params[1] = 'count'; } if ($Model->isVirtualField($params[0])) { $arg = $this->_quoteFields($Model->getVirtualField($params[0])); } else { $arg = $this->name($params[0]); } return 'COUNT(' . $arg . ') AS ' . $this->name($params[1]); case 'max': case 'min': if (!isset($params[1])) { $params[1] = $params[0]; } if ($Model->isVirtualField($params[0])) { $arg = $this->_quoteFields($Model->getVirtualField($params[0])); } else { $arg = $this->name($params[0]); } return strtoupper($func) . '(' . $arg . ') AS ' . $this->name($params[1]); } } /** * Deletes all the records in a table and resets the count of the auto-incrementing * primary key, where applicable. * * @param Model|string $table A string or model class representing the table to be truncated * @return bool SQL TRUNCATE TABLE statement, false if not applicable. */ public function truncate($table) { return $this->execute('TRUNCATE TABLE ' . $this->fullTableName($table)); } /** * Check if the server support nested transactions * * @return bool */ public function nestedTransactionSupported() { return false; } /** * Begin a transaction * * @return bool True on success, false on fail * (i.e. if the database/model does not support transactions, * or a transaction has not started). */ public function begin() { if ($this->_transactionStarted) { if ($this->nestedTransactionSupported()) { return $this->_beginNested(); } $this->_transactionNesting++; return $this->_transactionStarted; } $this->_transactionNesting = 0; if ($this->fullDebug) { $this->logQuery('BEGIN'); } return $this->_transactionStarted = $this->_connection->beginTransaction(); } /** * Begin a nested transaction * * @return bool */ protected function _beginNested() { $query = 'SAVEPOINT LEVEL' . ++$this->_transactionNesting; if ($this->fullDebug) { $this->logQuery($query); } $this->_connection->exec($query); return true; } /** * Commit a transaction * * @return bool True on success, false on fail * (i.e. if the database/model does not support transactions, * or a transaction has not started). */ public function commit() { if (!$this->_transactionStarted) { return false; } if ($this->_transactionNesting === 0) { if ($this->fullDebug) { $this->logQuery('COMMIT'); } $this->_transactionStarted = false; return $this->_connection->commit(); } if ($this->nestedTransactionSupported()) { return $this->_commitNested(); } $this->_transactionNesting--; return true; } /** * Commit a nested transaction * * @return bool */ protected function _commitNested() { $query = 'RELEASE SAVEPOINT LEVEL' . $this->_transactionNesting--; if ($this->fullDebug) { $this->logQuery($query); } $this->_connection->exec($query); return true; } /** * Rollback a transaction * * @return bool True on success, false on fail * (i.e. if the database/model does not support transactions, * or a transaction has not started). */ public function rollback() { if (!$this->_transactionStarted) { return false; } if ($this->_transactionNesting === 0) { if ($this->fullDebug) { $this->logQuery('ROLLBACK'); } $this->_transactionStarted = false; return $this->_connection->rollBack(); } if ($this->nestedTransactionSupported()) { return $this->_rollbackNested(); } $this->_transactionNesting--; return true; } /** * Rollback a nested transaction * * @return bool */ protected function _rollbackNested() { $query = 'ROLLBACK TO SAVEPOINT LEVEL' . $this->_transactionNesting--; if ($this->fullDebug) { $this->logQuery($query); } $this->_connection->exec($query); return true; } /** * Returns the ID generated from the previous INSERT operation. * * @param mixed $source The source to get an id for. * @return mixed */ public function lastInsertId($source = null) { return $this->_connection->lastInsertId(); } /** * Creates a default set of conditions from the model if $conditions is null/empty. * If conditions are supplied then they will be returned. If a model doesn't exist and no conditions * were provided either null or false will be returned based on what was input. * * @param Model $Model The model to get conditions for. * @param string|array|bool $conditions Array of conditions, conditions string, null or false. If an array of conditions, * or string conditions those conditions will be returned. With other values the model's existence will be checked. * If the model doesn't exist a null or false will be returned depending on the input value. * @param bool $useAlias Use model aliases rather than table names when generating conditions * @return mixed Either null, false, $conditions or an array of default conditions to use. * @see DboSource::update() * @see DboSource::conditions() */ public function defaultConditions(Model $Model, $conditions, $useAlias = true) { if (!empty($conditions)) { return $conditions; } $exists = $Model->exists(); if (!$exists && ($conditions !== null || !empty($Model->__safeUpdateMode))) { return false; } elseif (!$exists) { return null; } $alias = $Model->alias; if (!$useAlias) { $alias = $this->fullTableName($Model, false); } return array("{$alias}.{$Model->primaryKey}" => $Model->getID()); } /** * Returns a key formatted like a string Model.fieldname(i.e. Post.title, or Country.name) * * @param Model $Model The model to get a key for. * @param string $key The key field. * @param string $assoc The association name. * @return string */ public function resolveKey(Model $Model, $key, $assoc = null) { if (strpos('.', $key) !== false) { return $this->name($Model->alias) . '.' . $this->name($key); } return $key; } /** * Private helper method to remove query metadata in given data array. * * @param array $data The data to scrub. * @return array */ protected function _scrubQueryData($data) { static $base = null; if ($base === null) { $base = array_fill_keys(array('conditions', 'fields', 'joins', 'order', 'limit', 'offset', 'group'), array()); $base['callbacks'] = null; } return (array)$data + $base; } /** * Converts model virtual fields into sql expressions to be fetched later * * @param Model $Model The model to get virtual fields for. * @param string $alias Alias table name * @param array $fields virtual fields to be used on query * @return array */ protected function _constructVirtualFields(Model $Model, $alias, $fields) { $virtual = array(); foreach ($fields as $field) { $virtualField = $this->name($alias . $this->virtualFieldSeparator . $field); $expression = $this->_quoteFields($Model->getVirtualField($field)); $virtual[] = '(' . $expression . ") {$this->alias} {$virtualField}"; } return $virtual; } /** * Generates the fields list of an SQL query. * * @param Model $Model The model to get fields for. * @param string $alias Alias table name * @param mixed $fields The provided list of fields. * @param bool $quote If false, returns fields array unquoted * @return array */ public function fields(Model $Model, $alias = null, $fields = array(), $quote = true) { if (empty($alias)) { $alias = $Model->alias; } $virtualFields = $Model->getVirtualField(); $cacheKey = array( $alias, get_class($Model), $Model->alias, $virtualFields, $fields, $quote, ConnectionManager::getSourceName($this), $Model->schemaName, $Model->table ); $cacheKey = md5(serialize($cacheKey)); if ($return = $this->cacheMethod(__FUNCTION__, $cacheKey)) { return $return; } $allFields = empty($fields); if ($allFields) { $fields = array_keys($Model->schema()); } elseif (!is_array($fields)) { $fields = CakeText::tokenize($fields); } $fields = array_values(array_filter($fields)); $allFields = $allFields || in_array('*', $fields) || in_array($Model->alias . '.*', $fields); $virtual = array(); if (!empty($virtualFields)) { $virtualKeys = array_keys($virtualFields); foreach ($virtualKeys as $field) { $virtualKeys[] = $Model->alias . '.' . $field; } $virtual = ($allFields) ? $virtualKeys : array_intersect($virtualKeys, $fields); foreach ($virtual as $i => $field) { if (strpos($field, '.') !== false) { $virtual[$i] = str_replace($Model->alias . '.', '', $field); } $fields = array_diff($fields, array($field)); } $fields = array_values($fields); } if (!$quote) { if (!empty($virtual)) { $fields = array_merge($fields, $this->_constructVirtualFields($Model, $alias, $virtual)); } return $fields; } $count = count($fields); if ($count >= 1 && !in_array($fields[0], array('*', 'COUNT(*)'))) { for ($i = 0; $i < $count; $i++) { if (is_string($fields[$i]) && in_array($fields[$i], $virtual)) { unset($fields[$i]); continue; } if (is_object($fields[$i]) && isset($fields[$i]->type) && $fields[$i]->type === 'expression') { $fields[$i] = $fields[$i]->value; } elseif (preg_match('/^\(.*\)\s' . $this->alias . '.*/i', $fields[$i])) { continue; } elseif (!preg_match('/^.+\\(.*\\)/', $fields[$i])) { $prepend = ''; if (strpos($fields[$i], 'DISTINCT') !== false) { $prepend = 'DISTINCT '; $fields[$i] = trim(str_replace('DISTINCT', '', $fields[$i])); } $dot = strpos($fields[$i], '.'); if ($dot === false) { $prefix = !( strpos($fields[$i], ' ') !== false || strpos($fields[$i], '(') !== false ); $fields[$i] = $this->name(($prefix ? $alias . '.' : '') . $fields[$i]); } else { if (strpos($fields[$i], ',') === false) { $build = explode('.', $fields[$i]); if (!Hash::numeric($build)) { $fields[$i] = $this->name(implode('.', $build)); } } } $fields[$i] = $prepend . $fields[$i]; } elseif (preg_match('/\(([\.\w]+)\)/', $fields[$i], $field)) { if (isset($field[1])) { if (strpos($field[1], '.') === false) { $field[1] = $this->name($alias . '.' . $field[1]); } else { $field[0] = explode('.', $field[1]); if (!Hash::numeric($field[0])) { $field[0] = implode('.', array_map(array(&$this, 'name'), $field[0])); $fields[$i] = preg_replace('/\(' . $field[1] . '\)/', '(' . $field[0] . ')', $fields[$i], 1); } } } } } } if (!empty($virtual)) { $fields = array_merge($fields, $this->_constructVirtualFields($Model, $alias, $virtual)); } return $this->cacheMethod(__FUNCTION__, $cacheKey, array_unique($fields)); } /** * Creates a WHERE clause by parsing given conditions data. If an array or string * conditions are provided those conditions will be parsed and quoted. If a boolean * is given it will be integer cast as condition. Null will return 1 = 1. * * Results of this method are stored in a memory cache. This improves performance, but * because the method uses a hashing algorithm it can have collisions. * Setting DboSource::$cacheMethods to false will disable the memory cache. * * @param mixed $conditions Array or string of conditions, or any value. * @param bool $quoteValues If true, values should be quoted * @param bool $where If true, "WHERE " will be prepended to the return value * @param Model $Model A reference to the Model instance making the query * @return string SQL fragment */ public function conditions($conditions, $quoteValues = true, $where = true, Model $Model = null) { $clause = $out = ''; if ($where) { $clause = ' WHERE '; } if (is_array($conditions) && !empty($conditions)) { $out = $this->conditionKeysToString($conditions, $quoteValues, $Model); if (empty($out)) { return $clause . ' 1 = 1'; } return $clause . implode(' AND ', $out); } if (is_bool($conditions)) { return $clause . (int)$conditions . ' = 1'; } if (empty($conditions) || trim($conditions) === '') { return $clause . '1 = 1'; } $clauses = '/^WHERE\\x20|^GROUP\\x20BY\\x20|^HAVING\\x20|^ORDER\\x20BY\\x20/i'; if (preg_match($clauses, $conditions)) { $clause = ''; } $conditions = $this->_quoteFields($conditions); return $clause . $conditions; } /** * Creates a WHERE clause by parsing given conditions array. Used by DboSource::conditions(). * * @param array $conditions Array or string of conditions * @param bool $quoteValues If true, values should be quoted * @param Model $Model A reference to the Model instance making the query * @return string SQL fragment */ public function conditionKeysToString($conditions, $quoteValues = true, Model $Model = null) { $out = array(); $data = $columnType = null; $bool = array('and', 'or', 'not', 'and not', 'or not', 'xor', '||', '&&'); foreach ($conditions as $key => $value) { $join = ' AND '; $not = null; if (is_array($value)) { $valueInsert = ( !empty($value) && (substr_count($key, '?') === count($value) || substr_count($key, ':') === count($value)) ); } if (is_numeric($key) && empty($value)) { continue; } elseif (is_numeric($key) && is_string($value)) { $out[] = $this->_quoteFields($value); } elseif ((is_numeric($key) && is_array($value)) || in_array(strtolower(trim($key)), $bool)) { if (in_array(strtolower(trim($key)), $bool)) { $join = ' ' . strtoupper($key) . ' '; } else { $key = $join; } $value = $this->conditionKeysToString($value, $quoteValues, $Model); if (strpos($join, 'NOT') !== false) { if (strtoupper(trim($key)) === 'NOT') { $key = 'AND ' . trim($key); } $not = 'NOT '; } if (empty($value)) { continue; } if (empty($value[1])) { if ($not) { $out[] = $not . '(' . $value[0] . ')'; } else { $out[] = $value[0]; } } else { $out[] = '(' . $not . '(' . implode(') ' . strtoupper($key) . ' (', $value) . '))'; } } else { if (is_object($value) && isset($value->type)) { if ($value->type === 'identifier') { $data .= $this->name($key) . ' = ' . $this->name($value->value); } elseif ($value->type === 'expression') { if (is_numeric($key)) { $data .= $value->value; } else { $data .= $this->name($key) . ' = ' . $value->value; } } } elseif (is_array($value) && !empty($value) && !$valueInsert) { $keys = array_keys($value); if ($keys === array_values($keys)) { if (count($value) === 1 && !preg_match('/\s+(?:NOT|IN|\!=)$/', $key)) { $data = $this->_quoteFields($key) . ' = ('; if ($quoteValues) { if ($Model !== null) { $columnType = $Model->getColumnType($key); } $data .= implode(', ', $this->value($value, $columnType)); } $data .= ')'; } else { $data = $this->_parseKey($key, $value, $Model); } } else { $ret = $this->conditionKeysToString($value, $quoteValues, $Model); if (count($ret) > 1) { $data = '(' . implode(') AND (', $ret) . ')'; } elseif (isset($ret[0])) { $data = $ret[0]; } } } elseif (is_numeric($key) && !empty($value)) { $data = $this->_quoteFields($value); } else { $data = $this->_parseKey(trim($key), $value, $Model); } if ($data) { $out[] = $data; $data = null; } } } return $out; } /** * Extracts a Model.field identifier and an SQL condition operator from a string, formats * and inserts values, and composes them into an SQL snippet. * * @param string $key An SQL key snippet containing a field and optional SQL operator * @param mixed $value The value(s) to be inserted in the string * @param Model $Model Model object initiating the query * @return string */ protected function _parseKey($key, $value, Model $Model = null) { $operatorMatch = '/^(((' . implode(')|(', $this->_sqlOps); $operatorMatch .= ')\\x20?)|<[>=]?(?![^>]+>)\\x20?|[>=!]{1,3}(?!<)\\x20?)/is'; $bound = (strpos($key, '?') !== false || (is_array($value) && strpos($key, ':') !== false)); $key = trim($key); if (strpos($key, ' ') === false) { $operator = '='; } else { list($key, $operator) = explode(' ', $key, 2); if (!preg_match($operatorMatch, trim($operator)) && strpos($operator, ' ') !== false) { $key = $key . ' ' . $operator; $split = strrpos($key, ' '); $operator = substr($key, $split); $key = substr($key, 0, $split); } } $virtual = false; $type = null; if ($Model !== null) { if ($Model->isVirtualField($key)) { $key = $this->_quoteFields($Model->getVirtualField($key)); $virtual = true; } $type = $Model->getColumnType($key); } $null = $value === null || (is_array($value) && empty($value)); if (strtolower($operator) === 'not') { $data = $this->conditionKeysToString( array($operator => array($key => $value)), true, $Model ); return $data[0]; } $value = $this->value($value, $type); if (!$virtual && $key !== '?') { $isKey = ( strpos($key, '(') !== false || strpos($key, ')') !== false || strpos($key, '|') !== false ); $key = $isKey ? $this->_quoteFields($key) : $this->name($key); } if ($bound) { return CakeText::insert($key . ' ' . trim($operator), $value); } if (!preg_match($operatorMatch, trim($operator))) { $operator .= is_array($value) ? ' IN' : ' ='; } $operator = trim($operator); if (is_array($value)) { $value = implode(', ', $value); switch ($operator) { case '=': $operator = 'IN'; break; case '!=': case '<>': $operator = 'NOT IN'; break; } $value = "({$value})"; } elseif ($null || $value === 'NULL') { switch ($operator) { case '=': $operator = 'IS'; break; case '!=': case '<>': $operator = 'IS NOT'; break; } } if ($virtual) { return "({$key}) {$operator} {$value}"; } return "{$key} {$operator} {$value}"; } /** * Quotes Model.fields * * @param string $conditions The conditions to quote. * @return string or false if no match */ protected function _quoteFields($conditions) { $start = $end = null; $original = $conditions; if (!empty($this->startQuote)) { $start = preg_quote($this->startQuote); } if (!empty($this->endQuote)) { $end = preg_quote($this->endQuote); } // Remove quotes and requote all the Model.field names. $conditions = str_replace(array($start, $end), '', $conditions); $conditions = preg_replace_callback( '/(?:[\'\"][^\'\"\\\]*(?:\\\.[^\'\"\\\]*)*[\'\"])|([a-z0-9_][a-z0-9\\-_]*\\.[a-z0-9_][a-z0-9_\\-]*)/i', array(&$this, '_quoteMatchedField'), $conditions ); // Quote `table_name AS Alias` $conditions = preg_replace( '/(\s[a-z0-9\\-_.' . $start . $end . ']*' . $end . ')\s+AS\s+([a-z0-9\\-_]+)/i', '\1 AS ' . $this->startQuote . '\2' . $this->endQuote, $conditions ); if ($conditions !== null) { return $conditions; } return $original; } /** * Auxiliary function to quote matches `Model.fields` from a preg_replace_callback call * * @param string $match matched string * @return string quoted string */ protected function _quoteMatchedField($match) { if (is_numeric($match[0])) { return $match[0]; } return $this->name($match[0]); } /** * Returns a limit statement in the correct format for the particular database. * * @param int $limit Limit of results returned * @param int $offset Offset from which to start results * @return string SQL limit/offset statement */ public function limit($limit, $offset = null) { if ($limit) { $rt = ' LIMIT'; if ($offset) { $rt .= sprintf(' %u,', $offset); } $rt .= sprintf(' %u', $limit); return $rt; } return null; } /** * Returns an ORDER BY clause as a string. * * @param array|string $keys Field reference, as a key (i.e. Post.title) * @param string $direction Direction (ASC or DESC) * @param Model $Model Model reference (used to look for virtual field) * @return string ORDER BY clause */ public function order($keys, $direction = 'ASC', Model $Model = null) { if (!is_array($keys)) { $keys = array($keys); } $keys = array_filter($keys); $result = array(); while (!empty($keys)) { list($key, $dir) = each($keys); array_shift($keys); if (is_numeric($key)) { $key = $dir; $dir = $direction; } if (is_string($key) && strpos($key, ',') !== false && !preg_match('/\(.+\,.+\)/', $key)) { $key = array_map('trim', explode(',', $key)); } if (is_array($key)) { //Flatten the array $key = array_reverse($key, true); foreach ($key as $k => $v) { if (is_numeric($k)) { array_unshift($keys, $v); } else { $keys = array($k => $v) + $keys; } } continue; } elseif (is_object($key) && isset($key->type) && $key->type === 'expression') { $result[] = $key->value; continue; } if (preg_match('/\\x20(ASC|DESC).*/i', $key, $_dir)) { $dir = $_dir[0]; $key = preg_replace('/\\x20(ASC|DESC).*/i', '', $key); } $key = trim($key); if ($Model !== null) { if ($Model->isVirtualField($key)) { $key = '(' . $this->_quoteFields($Model->getVirtualField($key)) . ')'; } list($alias) = pluginSplit($key); if ($alias !== $Model->alias && is_object($Model->{$alias}) && $Model->{$alias}->isVirtualField($key)) { $key = '(' . $this->_quoteFields($Model->{$alias}->getVirtualField($key)) . ')'; } } if (strpos($key, '.')) { $key = preg_replace_callback('/([a-zA-Z0-9_-]{1,})\\.([a-zA-Z0-9_-]{1,})/', array(&$this, '_quoteMatchedField'), $key); } if (!preg_match('/\s/', $key) && strpos($key, '.') === false) { $key = $this->name($key); } $key .= ' ' . trim($dir); $result[] = $key; } if (!empty($result)) { return ' ORDER BY ' . implode(', ', $result); } return ''; } /** * Create a GROUP BY SQL clause. * * @param string|array $fields Group By fields * @param Model $Model The model to get group by fields for. * @return string Group By clause or null. */ public function group($fields, Model $Model = null) { if (empty($fields)) { return null; } if (!is_array($fields)) { $fields = array($fields); } if ($Model !== null) { foreach ($fields as $index => $key) { if ($Model->isVirtualField($key)) { $fields[$index] = '(' . $Model->getVirtualField($key) . ')'; } } } $fields = implode(', ', $fields); return ' GROUP BY ' . $this->_quoteFields($fields); } /** * Disconnects database, kills the connection and says the connection is closed. * * @return void */ public function close() { $this->disconnect(); } /** * Checks if the specified table contains any record matching specified SQL * * @param Model $Model Model to search * @param string $sql SQL WHERE clause (condition only, not the "WHERE" part) * @return bool True if the table has a matching record, else false */ public function hasAny(Model $Model, $sql) { $sql = $this->conditions($sql); $table = $this->fullTableName($Model); $alias = $this->alias . $this->name($Model->alias); $where = $sql ? "{$sql}" : ' WHERE 1 = 1'; $id = $Model->escapeField(); $out = $this->fetchRow("SELECT COUNT({$id}) {$this->alias}count FROM {$table} {$alias}{$where}"); if (is_array($out)) { return $out[0]['count']; } return false; } /** * Gets the length of a database-native column description, or null if no length * * @param string $real Real database-layer column type (i.e. "varchar(255)") * @return mixed An integer or string representing the length of the column, or null for unknown length. */ public function length($real) { if (!preg_match_all('/([\w\s]+)(?:\((\d+)(?:,(\d+))?\))?(\sunsigned)?(\szerofill)?/', $real, $result)) { $col = str_replace(array(')', 'unsigned'), '', $real); $limit = null; if (strpos($col, '(') !== false) { list($col, $limit) = explode('(', $col); } if ($limit !== null) { return (int)$limit; } return null; } $types = array( 'int' => 1, 'tinyint' => 1, 'smallint' => 1, 'mediumint' => 1, 'integer' => 1, 'bigint' => 1 ); list($real, $type, $length, $offset, $sign) = $result; $typeArr = $type; $type = $type[0]; $length = $length[0]; $offset = $offset[0]; $isFloat = in_array($type, array('dec', 'decimal', 'float', 'numeric', 'double')); if ($isFloat && $offset) { return $length . ',' . $offset; } if (($real[0] == $type) && (count($real) === 1)) { return null; } if (isset($types[$type])) { $length += $types[$type]; if (!empty($sign)) { $length--; } } elseif (in_array($type, array('enum', 'set'))) { $length = 0; foreach ($typeArr as $key => $enumValue) { if ($key === 0) { continue; } $tmpLength = strlen($enumValue); if ($tmpLength > $length) { $length = $tmpLength; } } } return (int)$length; } /** * Translates between PHP boolean values and Database (faked) boolean values * * @param mixed $data Value to be translated * @param bool $quote Whether or not the field should be cast to a string. * @return string|bool Converted boolean value */ public function boolean($data, $quote = false) { if ($quote) { return !empty($data) ? '1' : '0'; } return !empty($data); } /** * Inserts multiple values into a table * * @param string $table The table being inserted into. * @param array $fields The array of field/column names being inserted. * @param array $values The array of values to insert. The values should * be an array of rows. Each row should have values keyed by the column name. * Each row must have the values in the same order as $fields. * @return bool */ public function insertMulti($table, $fields, $values) { $table = $this->fullTableName($table); $holder = implode(',', array_fill(0, count($fields), '?')); $fields = implode(', ', array_map(array(&$this, 'name'), $fields)); $pdoMap = array( 'integer' => PDO::PARAM_INT, 'float' => PDO::PARAM_STR, 'boolean' => PDO::PARAM_BOOL, 'string' => PDO::PARAM_STR, 'text' => PDO::PARAM_STR ); $columnMap = array(); $sql = "INSERT INTO {$table} ({$fields}) VALUES ({$holder})"; $statement = $this->_connection->prepare($sql); $this->begin(); foreach ($values[key($values)] as $key => $val) { $type = $this->introspectType($val); $columnMap[$key] = $pdoMap[$type]; } foreach ($values as $value) { $i = 1; foreach ($value as $col => $val) { $statement->bindValue($i, $val, $columnMap[$col]); $i += 1; } $statement->execute(); $statement->closeCursor(); if ($this->fullDebug) { $this->logQuery($sql, $value); } } return $this->commit(); } /** * Reset a sequence based on the MAX() value of $column. Useful * for resetting sequences after using insertMulti(). * * This method should be implemented by datasources that require sequences to be used. * * @param string $table The name of the table to update. * @param string $column The column to use when resetting the sequence value. * @return bool Success. */ public function resetSequence($table, $column) { } /** * Returns an array of the indexes in given datasource name. * * @param string $model Name of model to inspect * @return array Fields in table. Keys are column and unique */ public function index($model) { return array(); } /** * Generate a database-native schema for the given Schema object * * @param CakeSchema $schema An instance of a subclass of CakeSchema * @param string $tableName Optional. If specified only the table name given will be generated. * Otherwise, all tables defined in the schema are generated. * @return string */ public function createSchema($schema, $tableName = null) { if (!$schema instanceof CakeSchema) { trigger_error(__d('cake_dev', 'Invalid schema object'), E_USER_WARNING); return null; } $out = ''; foreach ($schema->tables as $curTable => $columns) { if (!$tableName || $tableName === $curTable) { $cols = $indexes = $tableParameters = array(); $primary = null; $table = $this->fullTableName($curTable); $primaryCount = 0; foreach ($columns as $col) { if (isset($col['key']) && $col['key'] === 'primary') { $primaryCount++; } } foreach ($columns as $name => $col) { if (is_string($col)) { $col = array('type' => $col); } $isPrimary = isset($col['key']) && $col['key'] === 'primary'; // Multi-column primary keys are not supported. if ($isPrimary && $primaryCount > 1) { unset($col['key']); $isPrimary = false; } if ($isPrimary) { $primary = $name; } if ($name !== 'indexes' && $name !== 'tableParameters') { $col['name'] = $name; if (!isset($col['type'])) { $col['type'] = 'string'; } $cols[] = $this->buildColumn($col); } elseif ($name === 'indexes') { $indexes = array_merge($indexes, $this->buildIndex($col, $table)); } elseif ($name === 'tableParameters') { $tableParameters = array_merge($tableParameters, $this->buildTableParameters($col, $table)); } } if (!isset($columns['indexes']['PRIMARY']) && !empty($primary)) { $col = array('PRIMARY' => array('column' => $primary, 'unique' => 1)); $indexes = array_merge($indexes, $this->buildIndex($col, $table)); } $columns = $cols; $out .= $this->renderStatement('schema', compact('table', 'columns', 'indexes', 'tableParameters')) . "\n\n"; } } return $out; } /** * Generate an alter syntax from CakeSchema::compare() * * @param mixed $compare The comparison data. * @param string $table The table name. * @return bool */ public function alterSchema($compare, $table = null) { return false; } /** * Generate a "drop table" statement for the given Schema object * * @param CakeSchema $schema An instance of a subclass of CakeSchema * @param string $table Optional. If specified only the table name given will be generated. * Otherwise, all tables defined in the schema are generated. * @return string */ public function dropSchema(CakeSchema $schema, $table = null) { $out = ''; if ($table && array_key_exists($table, $schema->tables)) { return $this->_dropTable($table) . "\n"; } elseif ($table) { return $out; } foreach (array_keys($schema->tables) as $curTable) { $out .= $this->_dropTable($curTable) . "\n"; } return $out; } /** * Generate a "drop table" statement for a single table * * @param type $table Name of the table to drop * @return string Drop table SQL statement */ protected function _dropTable($table) { return 'DROP TABLE ' . $this->fullTableName($table) . ";"; } /** * Generate a database-native column schema string * * @param array $column An array structured like the following: array('name' => 'value', 'type' => 'value'[, options]), * where options can be 'default', 'length', or 'key'. * @return string */ public function buildColumn($column) { $name = $type = null; extract(array_merge(array('null' => true), $column)); if (empty($name) || empty($type)) { trigger_error(__d('cake_dev', 'Column name or type not defined in schema'), E_USER_WARNING); return null; } if (!isset($this->columns[$type])) { trigger_error(__d('cake_dev', 'Column type %s does not exist', $type), E_USER_WARNING); return null; } $real = $this->columns[$type]; $out = $this->name($name) . ' ' . $real['name']; if (isset($column['length'])) { $length = $column['length']; } elseif (isset($column['limit'])) { $length = $column['limit']; } elseif (isset($real['length'])) { $length = $real['length']; } elseif (isset($real['limit'])) { $length = $real['limit']; } if (isset($length)) { $out .= '(' . $length . ')'; } if (($column['type'] === 'integer' || $column['type'] === 'float') && isset($column['default']) && $column['default'] === '') { $column['default'] = null; } $out = $this->_buildFieldParameters($out, $column, 'beforeDefault'); if (isset($column['key']) && $column['key'] === 'primary' && ($type === 'integer' || $type === 'biginteger')) { $out .= ' ' . $this->columns['primary_key']['name']; } elseif (isset($column['key']) && $column['key'] === 'primary') { $out .= ' NOT NULL'; } elseif (isset($column['default']) && isset($column['null']) && $column['null'] === false) { $out .= ' DEFAULT ' . $this->value($column['default'], $type) . ' NOT NULL'; } elseif (isset($column['default'])) { $out .= ' DEFAULT ' . $this->value($column['default'], $type); } elseif ($type !== 'timestamp' && !empty($column['null'])) { $out .= ' DEFAULT NULL'; } elseif ($type === 'timestamp' && !empty($column['null'])) { $out .= ' NULL'; } elseif (isset($column['null']) && $column['null'] === false) { $out .= ' NOT NULL'; } if ($type === 'timestamp' && isset($column['default']) && strtolower($column['default']) === 'current_timestamp') { $out = str_replace(array("'CURRENT_TIMESTAMP'", "'current_timestamp'"), 'CURRENT_TIMESTAMP', $out); } return $this->_buildFieldParameters($out, $column, 'afterDefault'); } /** * Build the field parameters, in a position * * @param string $columnString The partially built column string * @param array $columnData The array of column data. * @param string $position The position type to use. 'beforeDefault' or 'afterDefault' are common * @return string a built column with the field parameters added. */ protected function _buildFieldParameters($columnString, $columnData, $position) { foreach ($this->fieldParameters as $paramName => $value) { if (isset($columnData[$paramName]) && $value['position'] == $position) { if (isset($value['options']) && !in_array($columnData[$paramName], $value['options'], true)) { continue; } if (isset($value['types']) && !in_array($columnData['type'], $value['types'], true)) { continue; } $val = $columnData[$paramName]; if ($value['quote']) { $val = $this->value($val); } $columnString .= ' ' . $value['value'] . (empty($value['noVal']) ? $value['join'] . $val : ''); } } return $columnString; } /** * Format indexes for create table. * * @param array $indexes The indexes to build * @param string $table The table name. * @return array */ public function buildIndex($indexes, $table = null) { $join = array(); foreach ($indexes as $name => $value) { $out = ''; if ($name === 'PRIMARY') { $out .= 'PRIMARY '; $name = null; } else { if (!empty($value['unique'])) { $out .= 'UNIQUE '; } $name = $this->startQuote . $name . $this->endQuote; } if (is_array($value['column'])) { $out .= 'KEY ' . $name . ' (' . implode(', ', array_map(array(&$this, 'name'), $value['column'])) . ')'; } else { $out .= 'KEY ' . $name . ' (' . $this->name($value['column']) . ')'; } $join[] = $out; } return $join; } /** * Read additional table parameters * * @param string $name The table name to read. * @return array */ public function readTableParameters($name) { $parameters = array(); if (method_exists($this, 'listDetailedSources')) { $currentTableDetails = $this->listDetailedSources($name); foreach ($this->tableParameters as $paramName => $parameter) { if (!empty($parameter['column']) && !empty($currentTableDetails[$parameter['column']])) { $parameters[$paramName] = $currentTableDetails[$parameter['column']]; } } } return $parameters; } /** * Format parameters for create table * * @param array $parameters The parameters to create SQL for. * @param string $table The table name. * @return array */ public function buildTableParameters($parameters, $table = null) { $result = array(); foreach ($parameters as $name => $value) { if (isset($this->tableParameters[$name])) { if ($this->tableParameters[$name]['quote']) { $value = $this->value($value); } $result[] = $this->tableParameters[$name]['value'] . $this->tableParameters[$name]['join'] . $value; } } return $result; } /** * Guesses the data type of an array * * @param string $value The value to introspect for type data. * @return string */ public function introspectType($value) { if (!is_array($value)) { if (is_bool($value)) { return 'boolean'; } if (is_float($value) && (float)$value === $value) { return 'float'; } if (is_int($value) && (int)$value === $value) { return 'integer'; } if (is_string($value) && strlen($value) > 255) { return 'text'; } return 'string'; } $isAllFloat = $isAllInt = true; $containsInt = $containsString = false; foreach ($value as $valElement) { $valElement = trim($valElement); if (!is_float($valElement) && !preg_match('/^[\d]+\.[\d]+$/', $valElement)) { $isAllFloat = false; } else { continue; } if (!is_int($valElement) && !preg_match('/^[\d]+$/', $valElement)) { $isAllInt = false; } else { $containsInt = true; continue; } $containsString = true; } if ($isAllFloat) { return 'float'; } if ($isAllInt) { return 'integer'; } if ($containsInt && !$containsString) { return 'integer'; } return 'string'; } /** * Writes a new key for the in memory sql query cache * * @param string $sql SQL query * @param mixed $data result of $sql query * @param array $params query params bound as values * @return void */ protected function _writeQueryCache($sql, $data, $params = array()) { if (preg_match('/^\s*select/i', $sql)) { $this->_queryCache[$sql][serialize($params)] = $data; } } /** * Returns the result for a sql query if it is already cached * * @param string $sql SQL query * @param array $params query params bound as values * @return mixed results for query if it is cached, false otherwise */ public function getQueryCache($sql, $params = array()) { if (isset($this->_queryCache[$sql]) && preg_match('/^\s*select/i', $sql)) { $serialized = serialize($params); if (isset($this->_queryCache[$sql][$serialized])) { return $this->_queryCache[$sql][$serialized]; } } return false; } /** * Used for storing in cache the results of the in-memory methodCache */ public function __destruct() { if ($this->_methodCacheChange) { Cache::write('method_cache', static::$methodCache, '_cake_core_'); } parent::__destruct(); } } cakephp-2.8.0/lib/Cake/Model/Datasource/Session/000077500000000000000000000000001265552240500213305ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Model/Datasource/Session/CacheSession.php000066400000000000000000000051601265552240500244120ustar00rootroot00000000000000 'Session', 'alias' => 'Session', 'table' => 'cake_sessions', ); } else { $settings = array( 'class' => $modelName, 'alias' => 'Session', ); } $this->_model = ClassRegistry::init($settings); $this->_timeout = Configure::read('Session.timeout') * 60; } /** * Method called on open of a database session. * * @return bool Success */ public function open() { return true; } /** * Method called on close of a database session. * * @return bool Success */ public function close() { return true; } /** * Method used to read from a database session. * * @param int|string $id The key of the value to read * @return mixed The value of the key or false if it does not exist */ public function read($id) { $row = $this->_model->find('first', array( 'conditions' => array($this->_model->alias . '.' . $this->_model->primaryKey => $id) )); if (empty($row[$this->_model->alias])) { return ''; } if (!is_numeric($row[$this->_model->alias]['data']) && empty($row[$this->_model->alias]['data'])) { return ''; } return (string)$row[$this->_model->alias]['data']; } /** * Helper function called on write for database sessions. * * Will retry, once, if the save triggers a PDOException which * can happen if a race condition is encountered * * @param int $id ID that uniquely identifies session in database * @param mixed $data The value of the data to be saved. * @return bool True for successful write, false otherwise. */ public function write($id, $data) { if (!$id) { return false; } $expires = time() + $this->_timeout; $record = compact('id', 'data', 'expires'); $record[$this->_model->primaryKey] = $id; $options = array( 'validate' => false, 'callbacks' => false, 'counterCache' => false ); try { return (bool)$this->_model->save($record, $options); } catch (PDOException $e) { return (bool)$this->_model->save($record, $options); } } /** * Method called on the destruction of a database session. * * @param int $id ID that uniquely identifies session in database * @return bool True for successful delete, false otherwise. */ public function destroy($id) { return (bool)$this->_model->delete($id); } /** * Helper function called on gc for database sessions. * * @param int $expires Timestamp (defaults to current time) * @return bool Success */ public function gc($expires = null) { if (!$expires) { $expires = time(); } else { $expires = time() - $expires; } $this->_model->deleteAll(array($this->_model->alias . ".expires <" => $expires), false, false); return true; } } cakephp-2.8.0/lib/Cake/Model/I18nModel.php000066400000000000000000000020211265552240500200170ustar00rootroot00000000000000 table 'users'; class 'Man' => table 'men') * The table is required to have at least 'id auto_increment' primary key. * * @package Cake.Model * @link http://book.cakephp.org/2.0/en/models.html */ class Model extends Object implements CakeEventListener { /** * The name of the DataSource connection that this Model uses * * The value must be an attribute name that you defined in `app/Config/database.php` * or created using `ConnectionManager::create()`. * * @var string * @link http://book.cakephp.org/2.0/en/models/model-attributes.html#usedbconfig */ public $useDbConfig = 'default'; /** * Custom database table name, or null/false if no table association is desired. * * @var string * @link http://book.cakephp.org/2.0/en/models/model-attributes.html#usetable */ public $useTable = null; /** * Custom display field name. Display fields are used by Scaffold, in SELECT boxes' OPTION elements. * * This field is also used in `find('list')` when called with no extra parameters in the fields list * * @var string * @link http://book.cakephp.org/2.0/en/models/model-attributes.html#displayfield */ public $displayField = null; /** * Value of the primary key ID of the record that this model is currently pointing to. * Automatically set after database insertions. * * @var mixed */ public $id = false; /** * Container for the data that this model gets from persistent storage (usually, a database). * * @var array * @link http://book.cakephp.org/2.0/en/models/model-attributes.html#data */ public $data = array(); /** * Holds physical schema/database name for this model. Automatically set during Model creation. * * @var string */ public $schemaName = null; /** * Table name for this Model. * * @var string */ public $table = false; /** * The name of the primary key field for this model. * * @var string * @link http://book.cakephp.org/2.0/en/models/model-attributes.html#primarykey */ public $primaryKey = null; /** * Field-by-field table metadata. * * @var array */ protected $_schema = null; /** * List of validation rules. It must be an array with the field name as key and using * as value one of the following possibilities * * ### Validating using regular expressions * * ``` * public $validate = array( * 'name' => '/^[a-z].+$/i' * ); * ``` * * ### Validating using methods (no parameters) * * ``` * public $validate = array( * 'name' => 'notBlank' * ); * ``` * * ### Validating using methods (with parameters) * * ``` * public $validate = array( * 'length' => array( * 'rule' => array('lengthBetween', 5, 25) * ) * ); * ``` * * ### Validating using custom method * * ``` * public $validate = array( * 'password' => array( * 'rule' => array('customValidation') * ) * ); * public function customValidation($data) { * // $data will contain array('password' => 'value') * if (isset($this->data[$this->alias]['password2'])) { * return $this->data[$this->alias]['password2'] === current($data); * } * return true; * } * ``` * * ### Validations with messages * * The messages will be used in Model::$validationErrors and can be used in the FormHelper * * ``` * public $validate = array( * 'length' => array( * 'rule' => array('lengthBetween', 5, 15), * 'message' => array('Between %d to %d characters') * ) * ); * ``` * * ### Multiple validations to the same field * * ``` * public $validate = array( * 'login' => array( * array( * 'rule' => 'alphaNumeric', * 'message' => 'Only alphabets and numbers allowed', * 'last' => true * ), * array( * 'rule' => array('minLength', 8), * 'message' => array('Minimum length of %d characters') * ) * ) * ); * ``` * * ### Valid keys in validations * * - `rule`: String with method name, regular expression (started by slash) or array with method and parameters * - `message`: String with the message or array if have multiple parameters. See http://php.net/sprintf * - `last`: Boolean value to indicate if continue validating the others rules if the current fail [Default: true] * - `required`: Boolean value to indicate if the field must be present on save * - `allowEmpty`: Boolean value to indicate if the field can be empty * - `on`: Possible values: `update`, `create`. Indicate to apply this rule only on update or create * * @var array * @link http://book.cakephp.org/2.0/en/models/model-attributes.html#validate * @link http://book.cakephp.org/2.0/en/models/data-validation.html */ public $validate = array(); /** * List of validation errors. * * @var array */ public $validationErrors = array(); /** * Name of the validation string domain to use when translating validation errors. * * @var string */ public $validationDomain = null; /** * Database table prefix for tables in model. * * @var string * @link http://book.cakephp.org/2.0/en/models/model-attributes.html#tableprefix */ public $tablePrefix = null; /** * Plugin model belongs to. * * @var string */ public $plugin = null; /** * Name of the model. * * @var string * @link http://book.cakephp.org/2.0/en/models/model-attributes.html#name */ public $name = null; /** * Alias name for model. * * @var string */ public $alias = null; /** * List of table names included in the model description. Used for associations. * * @var array */ public $tableToModel = array(); /** * Whether or not to cache queries for this model. This enables in-memory * caching only, the results are not stored beyond the current request. * * @var bool * @link http://book.cakephp.org/2.0/en/models/model-attributes.html#cachequeries */ public $cacheQueries = false; /** * Detailed list of belongsTo associations. * * ### Basic usage * * `public $belongsTo = array('Group', 'Department');` * * ### Detailed configuration * * ``` * public $belongsTo = array( * 'Group', * 'Department' => array( * 'className' => 'Department', * 'foreignKey' => 'department_id' * ) * ); * ``` * * ### Possible keys in association * * - `className`: the class name of the model being associated to the current model. * If you're defining a 'Profile belongsTo User' relationship, the className key should equal 'User.' * - `foreignKey`: the name of the foreign key found in the current model. This is * especially handy if you need to define multiple belongsTo relationships. The default * value for this key is the underscored, singular name of the other model, suffixed with '_id'. * - `conditions`: An SQL fragment used to filter related model records. It's good * practice to use model names in SQL fragments: 'User.active = 1' is always * better than just 'active = 1.' * - `type`: the type of the join to use in the SQL query, default is LEFT which * may not fit your needs in all situations, INNER may be helpful when you want * everything from your main and associated models or nothing at all!(effective * when used with some conditions of course). (NB: type value is in lower case - i.e. left, inner) * - `fields`: A list of fields to be retrieved when the associated model data is * fetched. Returns all fields by default. * - `order`: An SQL fragment that defines the sorting order for the returned associated rows. * - `counterCache`: If set to true the associated Model will automatically increase or * decrease the "[singular_model_name]_count" field in the foreign table whenever you do * a save() or delete(). If its a string then its the field name to use. The value in the * counter field represents the number of related rows. * - `counterScope`: Optional conditions array to use for updating counter cache field. * * @var array * @link http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#belongsto */ public $belongsTo = array(); /** * Detailed list of hasOne associations. * * ### Basic usage * * `public $hasOne = array('Profile', 'Address');` * * ### Detailed configuration * * ``` * public $hasOne = array( * 'Profile', * 'Address' => array( * 'className' => 'Address', * 'foreignKey' => 'user_id' * ) * ); * ``` * * ### Possible keys in association * * - `className`: the class name of the model being associated to the current model. * If you're defining a 'User hasOne Profile' relationship, the className key should equal 'Profile.' * - `foreignKey`: the name of the foreign key found in the other model. This is * especially handy if you need to define multiple hasOne relationships. * The default value for this key is the underscored, singular name of the * current model, suffixed with '_id'. In the example above it would default to 'user_id'. * - `conditions`: An SQL fragment used to filter related model records. It's good * practice to use model names in SQL fragments: "Profile.approved = 1" is * always better than just "approved = 1." * - `fields`: A list of fields to be retrieved when the associated model data is * fetched. Returns all fields by default. * - `order`: An SQL fragment that defines the sorting order for the returned associated rows. * - `dependent`: When the dependent key is set to true, and the model's delete() * method is called with the cascade parameter set to true, associated model * records are also deleted. In this case we set it true so that deleting a * User will also delete her associated Profile. * * @var array * @link http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasone */ public $hasOne = array(); /** * Detailed list of hasMany associations. * * ### Basic usage * * `public $hasMany = array('Comment', 'Task');` * * ### Detailed configuration * * ``` * public $hasMany = array( * 'Comment', * 'Task' => array( * 'className' => 'Task', * 'foreignKey' => 'user_id' * ) * ); * ``` * * ### Possible keys in association * * - `className`: the class name of the model being associated to the current model. * If you're defining a 'User hasMany Comment' relationship, the className key should equal 'Comment.' * - `foreignKey`: the name of the foreign key found in the other model. This is * especially handy if you need to define multiple hasMany relationships. The default * value for this key is the underscored, singular name of the actual model, suffixed with '_id'. * - `conditions`: An SQL fragment used to filter related model records. It's good * practice to use model names in SQL fragments: "Comment.status = 1" is always * better than just "status = 1." * - `fields`: A list of fields to be retrieved when the associated model data is * fetched. Returns all fields by default. * - `order`: An SQL fragment that defines the sorting order for the returned associated rows. * - `limit`: The maximum number of associated rows you want returned. * - `offset`: The number of associated rows to skip over (given the current * conditions and order) before fetching and associating. * - `dependent`: When dependent is set to true, recursive model deletion is * possible. In this example, Comment records will be deleted when their * associated User record has been deleted. * - `exclusive`: When exclusive is set to true, recursive model deletion does * the delete with a deleteAll() call, instead of deleting each entity separately. * This greatly improves performance, but may not be ideal for all circumstances. * - `finderQuery`: A complete SQL query CakePHP can use to fetch associated model * records. This should be used in situations that require very custom results. * * @var array * @link http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasmany */ public $hasMany = array(); /** * Detailed list of hasAndBelongsToMany associations. * * ### Basic usage * * `public $hasAndBelongsToMany = array('Role', 'Address');` * * ### Detailed configuration * * ``` * public $hasAndBelongsToMany = array( * 'Role', * 'Address' => array( * 'className' => 'Address', * 'foreignKey' => 'user_id', * 'associationForeignKey' => 'address_id', * 'joinTable' => 'addresses_users' * ) * ); * ``` * * ### Possible keys in association * * - `className`: the class name of the model being associated to the current model. * If you're defining a 'Recipe HABTM Tag' relationship, the className key should equal 'Tag.' * - `joinTable`: The name of the join table used in this association (if the * current table doesn't adhere to the naming convention for HABTM join tables). * - `with`: Defines the name of the model for the join table. By default CakePHP * will auto-create a model for you. Using the example above it would be called * RecipesTag. By using this key you can override this default name. The join * table model can be used just like any "regular" model to access the join table directly. * - `foreignKey`: the name of the foreign key found in the current model. * This is especially handy if you need to define multiple HABTM relationships. * The default value for this key is the underscored, singular name of the * current model, suffixed with '_id'. * - `associationForeignKey`: the name of the foreign key found in the other model. * This is especially handy if you need to define multiple HABTM relationships. * The default value for this key is the underscored, singular name of the other * model, suffixed with '_id'. * - `unique`: If true (default value) cake will first delete existing relationship * records in the foreign keys table before inserting new ones, when updating a * record. So existing associations need to be passed again when updating. * To prevent deletion of existing relationship records, set this key to a string 'keepExisting'. * - `conditions`: An SQL fragment used to filter related model records. It's good * practice to use model names in SQL fragments: "Comment.status = 1" is always * better than just "status = 1." * - `fields`: A list of fields to be retrieved when the associated model data is * fetched. Returns all fields by default. * - `order`: An SQL fragment that defines the sorting order for the returned associated rows. * - `limit`: The maximum number of associated rows you want returned. * - `offset`: The number of associated rows to skip over (given the current * conditions and order) before fetching and associating. * - `finderQuery`, A complete SQL query CakePHP * can use to fetch associated model records. This should * be used in situations that require very custom results. * * @var array * @link http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#hasandbelongstomany-habtm */ public $hasAndBelongsToMany = array(); /** * List of behaviors to load when the model object is initialized. Settings can be * passed to behaviors by using the behavior name as index. Eg: * * public $actsAs = array('Translate', 'MyBehavior' => array('setting1' => 'value1')) * * @var array * @link http://book.cakephp.org/2.0/en/models/behaviors.html#using-behaviors */ public $actsAs = null; /** * Holds the Behavior objects currently bound to this model. * * @var BehaviorCollection */ public $Behaviors = null; /** * Whitelist of fields allowed to be saved. * * @var array */ public $whitelist = array(); /** * Whether or not to cache sources for this model. * * @var bool */ public $cacheSources = true; /** * Type of find query currently executing. * * @var string */ public $findQueryType = null; /** * Number of associations to recurse through during find calls. Fetches only * the first level by default. * * @var int * @link http://book.cakephp.org/2.0/en/models/model-attributes.html#recursive */ public $recursive = 1; /** * The column name(s) and direction(s) to order find results by default. * * public $order = "Post.created DESC"; * public $order = array("Post.view_count DESC", "Post.rating DESC"); * * @var string * @link http://book.cakephp.org/2.0/en/models/model-attributes.html#order */ public $order = null; /** * Array of virtual fields this model has. Virtual fields are aliased * SQL expressions. Fields added to this property will be read as other fields in a model * but will not be saveable. * * `public $virtualFields = array('two' => '1 + 1');` * * Is a simplistic example of how to set virtualFields * * @var array * @link http://book.cakephp.org/2.0/en/models/model-attributes.html#virtualfields */ public $virtualFields = array(); /** * Default list of association keys. * * @var array */ protected $_associationKeys = array( 'belongsTo' => array('className', 'foreignKey', 'conditions', 'fields', 'order', 'counterCache'), 'hasOne' => array('className', 'foreignKey', 'conditions', 'fields', 'order', 'dependent'), 'hasMany' => array('className', 'foreignKey', 'conditions', 'fields', 'order', 'limit', 'offset', 'dependent', 'exclusive', 'finderQuery', 'counterQuery'), 'hasAndBelongsToMany' => array('className', 'joinTable', 'with', 'foreignKey', 'associationForeignKey', 'conditions', 'fields', 'order', 'limit', 'offset', 'unique', 'finderQuery') ); /** * Holds provided/generated association key names and other data for all associations. * * @var array */ protected $_associations = array('belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany'); // @codingStandardsIgnoreStart /** * Holds model associations temporarily to allow for dynamic (un)binding. * * @var array */ public $__backAssociation = array(); /** * Back inner association * * @var array */ public $__backInnerAssociation = array(); /** * Back original association * * @var array */ public $__backOriginalAssociation = array(); /** * Back containable association * * @var array */ public $__backContainableAssociation = array(); /** * Safe update mode * If true, this prevents Model::save() from generating a query with WHERE 1 = 1 on race condition. * * @var bool */ public $__safeUpdateMode = false; // @codingStandardsIgnoreEnd /** * If true, afterFind will be passed consistent formatted $results in case of $primary is false. * The format will be such as the following. * * ``` * $results = array( * 0 => array( * 'ModelName' => array( * 'field1' => 'value1', * 'field2' => 'value2' * ) * ) * ); * ``` * * @var bool */ public $useConsistentAfterFind = true; /** * The ID of the model record that was last inserted. * * @var int */ protected $_insertID = null; /** * Has the datasource been configured. * * @var bool * @see Model::getDataSource */ protected $_sourceConfigured = false; /** * List of valid finder method options, supplied as the first parameter to find(). * * @var array */ public $findMethods = array( 'all' => true, 'first' => true, 'count' => true, 'neighbors' => true, 'list' => true, 'threaded' => true ); /** * Instance of the CakeEventManager this model is using * to dispatch inner events. * * @var CakeEventManager */ protected $_eventManager = null; /** * Instance of the ModelValidator * * @var ModelValidator */ protected $_validator = null; /** * Constructor. Binds the model's database table to the object. * * If `$id` is an array it can be used to pass several options into the model. * * - `id`: The id to start the model on. * - `table`: The table to use for this model. * - `ds`: The connection name this model is connected to. * - `name`: The name of the model eg. Post. * - `alias`: The alias of the model, this is used for registering the instance in the `ClassRegistry`. * eg. `ParentThread` * * ### Overriding Model's __construct method. * * When overriding Model::__construct() be careful to include and pass in all 3 of the * arguments to `parent::__construct($id, $table, $ds);` * * ### Dynamically creating models * * You can dynamically create model instances using the $id array syntax. * * ``` * $Post = new Model(array('table' => 'posts', 'name' => 'Post', 'ds' => 'connection2')); * ``` * * Would create a model attached to the posts table on connection2. Dynamic model creation is useful * when you want a model object that contains no associations or attached behaviors. * * @param bool|int|string|array $id Set this ID for this model on startup, * can also be an array of options, see above. * @param string $table Name of database table to use. * @param string $ds DataSource connection name. */ public function __construct($id = false, $table = null, $ds = null) { parent::__construct(); if (is_array($id)) { extract(array_merge( array( 'id' => $this->id, 'table' => $this->useTable, 'ds' => $this->useDbConfig, 'name' => $this->name, 'alias' => $this->alias, 'plugin' => $this->plugin ), $id )); } if ($this->plugin === null) { $this->plugin = (isset($plugin) ? $plugin : $this->plugin); } if ($this->name === null) { $this->name = (isset($name) ? $name : get_class($this)); } if ($this->alias === null) { $this->alias = (isset($alias) ? $alias : $this->name); } if ($this->primaryKey === null) { $this->primaryKey = 'id'; } ClassRegistry::addObject($this->alias, $this); $this->id = $id; unset($id); if ($table === false) { $this->useTable = false; } elseif ($table) { $this->useTable = $table; } if ($ds !== null) { $this->useDbConfig = $ds; } if (is_subclass_of($this, 'AppModel')) { $merge = array('actsAs', 'findMethods'); $parentClass = get_parent_class($this); if ($parentClass !== 'AppModel') { $this->_mergeVars($merge, $parentClass); } $this->_mergeVars($merge, 'AppModel'); } $this->_mergeVars(array('findMethods'), 'Model'); $this->Behaviors = new BehaviorCollection(); if ($this->useTable !== false) { if ($this->useTable === null) { $this->useTable = Inflector::tableize($this->name); } if (!$this->displayField) { unset($this->displayField); } $this->table = $this->useTable; $this->tableToModel[$this->table] = $this->alias; } elseif ($this->table === false) { $this->table = Inflector::tableize($this->name); } if ($this->tablePrefix === null) { unset($this->tablePrefix); } $this->_createLinks(); $this->Behaviors->init($this->alias, $this->actsAs); } /** * Returns a list of all events that will fire in the model during it's lifecycle. * You can override this function to add your own listener callbacks * * @return array */ public function implementedEvents() { return array( 'Model.beforeFind' => array('callable' => 'beforeFind', 'passParams' => true), 'Model.afterFind' => array('callable' => 'afterFind', 'passParams' => true), 'Model.beforeValidate' => array('callable' => 'beforeValidate', 'passParams' => true), 'Model.afterValidate' => array('callable' => 'afterValidate'), 'Model.beforeSave' => array('callable' => 'beforeSave', 'passParams' => true), 'Model.afterSave' => array('callable' => 'afterSave', 'passParams' => true), 'Model.beforeDelete' => array('callable' => 'beforeDelete', 'passParams' => true), 'Model.afterDelete' => array('callable' => 'afterDelete'), ); } /** * Returns the CakeEventManager manager instance that is handling any callbacks. * You can use this instance to register any new listeners or callbacks to the * model events, or create your own events and trigger them at will. * * @return CakeEventManager */ public function getEventManager() { if (empty($this->_eventManager)) { $this->_eventManager = new CakeEventManager(); $this->_eventManager->attach($this->Behaviors); $this->_eventManager->attach($this); } return $this->_eventManager; } /** * Handles custom method calls, like findBy for DB models, * and custom RPC calls for remote data sources. * * @param string $method Name of method to call. * @param array $params Parameters for the method. * @return mixed Whatever is returned by called method */ public function __call($method, $params) { $result = $this->Behaviors->dispatchMethod($this, $method, $params); if ($result !== array('unhandled')) { return $result; } return $this->getDataSource()->query($method, $params, $this); } /** * Handles the lazy loading of model associations by looking in the association arrays for the requested variable * * @param string $name variable tested for existence in class * @return bool true if the variable exists (if is a not loaded model association it will be created), false otherwise */ public function __isset($name) { $className = false; foreach ($this->_associations as $type) { if (isset($name, $this->{$type}[$name])) { $className = empty($this->{$type}[$name]['className']) ? $name : $this->{$type}[$name]['className']; break; } elseif (isset($name, $this->__backAssociation[$type][$name])) { $className = empty($this->__backAssociation[$type][$name]['className']) ? $name : $this->__backAssociation[$type][$name]['className']; break; } elseif ($type === 'hasAndBelongsToMany') { foreach ($this->{$type} as $k => $relation) { if (empty($relation['with'])) { continue; } if (is_array($relation['with'])) { if (key($relation['with']) === $name) { $className = $name; } } else { list($plugin, $class) = pluginSplit($relation['with']); if ($class === $name) { $className = $relation['with']; } } if ($className) { $assocKey = $k; $dynamic = !empty($relation['dynamicWith']); break(2); } } } } if (!$className) { return false; } list($plugin, $className) = pluginSplit($className); if (!ClassRegistry::isKeySet($className) && !empty($dynamic)) { $this->{$className} = new AppModel(array( 'name' => $className, 'table' => $this->hasAndBelongsToMany[$assocKey]['joinTable'], 'ds' => $this->useDbConfig )); } else { $this->_constructLinkedModel($name, $className, $plugin); } if (!empty($assocKey)) { $this->hasAndBelongsToMany[$assocKey]['joinTable'] = $this->{$name}->table; if (count($this->{$name}->schema()) <= 2 && $this->{$name}->primaryKey !== false) { $this->{$name}->primaryKey = $this->hasAndBelongsToMany[$assocKey]['foreignKey']; } } return true; } /** * Returns the value of the requested variable if it can be set by __isset() * * @param string $name variable requested for it's value or reference * @return mixed value of requested variable if it is set */ public function __get($name) { if ($name === 'displayField') { return $this->displayField = $this->hasField(array('title', 'name', $this->primaryKey)); } if ($name === 'tablePrefix') { $this->setDataSource(); if (property_exists($this, 'tablePrefix') && !empty($this->tablePrefix)) { return $this->tablePrefix; } return $this->tablePrefix = null; } if (isset($this->{$name})) { return $this->{$name}; } } /** * Bind model associations on the fly. * * If `$reset` is false, association will not be reset * to the originals defined in the model * * Example: Add a new hasOne binding to the Profile model not * defined in the model source code: * * `$this->User->bindModel(array('hasOne' => array('Profile')));` * * Bindings that are not made permanent will be reset by the next Model::find() call on this * model. * * @param array $params Set of bindings (indexed by binding type) * @param bool $reset Set to false to make the binding permanent * @return bool Success * @link http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#creating-and-destroying-associations-on-the-fly */ public function bindModel($params, $reset = true) { foreach ($params as $assoc => $model) { if ($reset === true && !isset($this->__backAssociation[$assoc])) { $this->__backAssociation[$assoc] = $this->{$assoc}; } foreach ($model as $key => $value) { $assocName = $key; if (is_numeric($key)) { $assocName = $value; $value = array(); } $this->{$assoc}[$assocName] = $value; if (property_exists($this, $assocName)) { unset($this->{$assocName}); } if ($reset === false && isset($this->__backAssociation[$assoc])) { $this->__backAssociation[$assoc][$assocName] = $value; } } } $this->_createLinks(); return true; } /** * Turn off associations on the fly. * * If $reset is false, association will not be reset * to the originals defined in the model * * Example: Turn off the associated Model Support request, * to temporarily lighten the User model: * * `$this->User->unbindModel(array('hasMany' => array('SupportRequest')));` * Or alternatively: * `$this->User->unbindModel(array('hasMany' => 'SupportRequest'));` * * Unbound models that are not made permanent will reset with the next call to Model::find() * * @param array $params Set of bindings to unbind (indexed by binding type) * @param bool $reset Set to false to make the unbinding permanent * @return bool Success * @link http://book.cakephp.org/2.0/en/models/associations-linking-models-together.html#creating-and-destroying-associations-on-the-fly */ public function unbindModel($params, $reset = true) { foreach ($params as $assoc => $models) { if ($reset === true && !isset($this->__backAssociation[$assoc])) { $this->__backAssociation[$assoc] = $this->{$assoc}; } $models = Hash::normalize((array)$models, false); foreach ($models as $model) { if ($reset === false && isset($this->__backAssociation[$assoc][$model])) { unset($this->__backAssociation[$assoc][$model]); } unset($this->{$assoc}[$model]); } } return true; } /** * Create a set of associations. * * @return void */ protected function _createLinks() { foreach ($this->_associations as $type) { $association =& $this->{$type}; if (!is_array($association)) { $association = explode(',', $association); foreach ($association as $i => $className) { $className = trim($className); unset ($association[$i]); $association[$className] = array(); } } if (!empty($association)) { foreach ($association as $assoc => $value) { $plugin = null; if (is_numeric($assoc)) { unset($association[$assoc]); $assoc = $value; $value = array(); if (strpos($assoc, '.') !== false) { list($plugin, $assoc) = pluginSplit($assoc, true); $association[$assoc] = array('className' => $plugin . $assoc); } else { $association[$assoc] = $value; } } $this->_generateAssociation($type, $assoc); } } } } /** * Protected helper method to create associated models of a given class. * * @param string $assoc Association name * @param string $className Class name * @param string $plugin name of the plugin where $className is located * examples: public $hasMany = array('Assoc' => array('className' => 'ModelName')); * usage: $this->Assoc->modelMethods(); * * public $hasMany = array('ModelName'); * usage: $this->ModelName->modelMethods(); * @return void */ protected function _constructLinkedModel($assoc, $className = null, $plugin = null) { if (empty($className)) { $className = $assoc; } if (!isset($this->{$assoc}) || $this->{$assoc}->name !== $className) { if ($plugin) { $plugin .= '.'; } $model = array('class' => $plugin . $className, 'alias' => $assoc); $this->{$assoc} = ClassRegistry::init($model); if ($plugin) { ClassRegistry::addObject($plugin . $className, $this->{$assoc}); } if ($assoc) { $this->tableToModel[$this->{$assoc}->table] = $assoc; } } } /** * Build an array-based association from string. * * @param string $type 'belongsTo', 'hasOne', 'hasMany', 'hasAndBelongsToMany' * @param string $assocKey Association key. * @return void */ protected function _generateAssociation($type, $assocKey) { $class = $assocKey; $dynamicWith = false; $assoc =& $this->{$type}[$assocKey]; foreach ($this->_associationKeys[$type] as $key) { if (!isset($assoc[$key]) || $assoc[$key] === null) { $data = ''; switch ($key) { case 'fields': $data = ''; break; case 'foreignKey': $data = (($type === 'belongsTo') ? Inflector::underscore($assocKey) : Inflector::singularize($this->table)) . '_id'; break; case 'associationForeignKey': $data = Inflector::singularize($this->{$class}->table) . '_id'; break; case 'with': $data = Inflector::camelize(Inflector::singularize($assoc['joinTable'])); $dynamicWith = true; break; case 'joinTable': $tables = array($this->table, $this->{$class}->table); sort($tables); $data = $tables[0] . '_' . $tables[1]; break; case 'className': $data = $class; break; case 'unique': $data = true; break; } $assoc[$key] = $data; } if ($dynamicWith) { $assoc['dynamicWith'] = true; } } } /** * Sets a custom table for your model class. Used by your controller to select a database table. * * @param string $tableName Name of the custom table * @throws MissingTableException when database table $tableName is not found on data source * @return void */ public function setSource($tableName) { $this->setDataSource($this->useDbConfig); $db = ConnectionManager::getDataSource($this->useDbConfig); if (method_exists($db, 'listSources')) { $restore = $db->cacheSources; $db->cacheSources = ($restore && $this->cacheSources); $sources = $db->listSources(); $db->cacheSources = $restore; if (is_array($sources) && !in_array(strtolower($this->tablePrefix . $tableName), array_map('strtolower', $sources))) { throw new MissingTableException(array( 'table' => $this->tablePrefix . $tableName, 'class' => $this->alias, 'ds' => $this->useDbConfig, )); } if ($sources) { $this->_schema = null; } } $this->table = $this->useTable = $tableName; $this->tableToModel[$this->table] = $this->alias; } /** * This function does two things: * * 1. it scans the array $one for the primary key, * and if that's found, it sets the current id to the value of $one[id]. * For all other keys than 'id' the keys and values of $one are copied to the 'data' property of this object. * 2. Returns an array with all of $one's keys and values. * (Alternative indata: two strings, which are mangled to * a one-item, two-dimensional array using $one for a key and $two as its value.) * * @param string|array|SimpleXmlElement|DomNode $one Array or string of data * @param string $two Value string for the alternative indata method * @return array|null Data with all of $one's keys and values, otherwise null. * @link http://book.cakephp.org/2.0/en/models/saving-your-data.html */ public function set($one, $two = null) { if (!$one) { return null; } if (is_object($one)) { if ($one instanceof SimpleXMLElement || $one instanceof DOMNode) { $one = $this->_normalizeXmlData(Xml::toArray($one)); } else { $one = Set::reverse($one); } } if (is_array($one)) { $data = $one; if (empty($one[$this->alias])) { $data = $this->_setAliasData($one); } } else { $data = array($this->alias => array($one => $two)); } foreach ($data as $modelName => $fieldSet) { if (!is_array($fieldSet)) { continue; } if (!isset($this->data[$modelName])) { $this->data[$modelName] = array(); } foreach ($fieldSet as $fieldName => $fieldValue) { unset($this->validationErrors[$fieldName]); if ($modelName === $this->alias && $fieldName === $this->primaryKey) { $this->id = $fieldValue; } if (is_array($fieldValue) || is_object($fieldValue)) { $fieldValue = $this->deconstruct($fieldName, $fieldValue); } $this->data[$modelName][$fieldName] = $fieldValue; } } return $data; } /** * Move values to alias * * @param array $data Data. * @return array */ protected function _setAliasData($data) { $models = array_keys($this->getAssociated()); $schema = array_keys((array)$this->schema()); foreach ($data as $field => $value) { if (in_array($field, $schema) || !in_array($field, $models)) { $data[$this->alias][$field] = $value; unset($data[$field]); } } return $data; } /** * Normalize `Xml::toArray()` to use in `Model::save()` * * @param array $xml XML as array * @return array */ protected function _normalizeXmlData(array $xml) { $return = array(); foreach ($xml as $key => $value) { if (is_array($value)) { $return[Inflector::camelize($key)] = $this->_normalizeXmlData($value); } elseif ($key[0] === '@') { $return[substr($key, 1)] = $value; } else { $return[$key] = $value; } } return $return; } /** * Deconstructs a complex data type (array or object) into a single field value. * * @param string $field The name of the field to be deconstructed * @param array|object $data An array or object to be deconstructed into a field * @return mixed The resulting data that should be assigned to a field */ public function deconstruct($field, $data) { if (!is_array($data)) { return $data; } $type = $this->getColumnType($field); if (!in_array($type, array('datetime', 'timestamp', 'date', 'time'))) { return $data; } $useNewDate = (isset($data['year']) || isset($data['month']) || isset($data['day']) || isset($data['hour']) || isset($data['minute'])); $dateFields = array('Y' => 'year', 'm' => 'month', 'd' => 'day', 'H' => 'hour', 'i' => 'min', 's' => 'sec'); $timeFields = array('H' => 'hour', 'i' => 'min', 's' => 'sec'); $date = array(); if (isset($data['meridian']) && empty($data['meridian'])) { return null; } if (isset($data['hour']) && isset($data['meridian']) && !empty($data['hour']) && $data['hour'] != 12 && $data['meridian'] === 'pm' ) { $data['hour'] = $data['hour'] + 12; } if (isset($data['hour']) && isset($data['meridian']) && $data['hour'] == 12 && $data['meridian'] === 'am') { $data['hour'] = '00'; } if ($type === 'time') { foreach ($timeFields as $key => $val) { if (!isset($data[$val]) || $data[$val] === '0' || $data[$val] === '00') { $data[$val] = '00'; } elseif ($data[$val] !== '') { $data[$val] = sprintf('%02d', $data[$val]); } if (!empty($data[$val])) { $date[$key] = $data[$val]; } else { return null; } } } if ($type === 'datetime' || $type === 'timestamp' || $type === 'date') { foreach ($dateFields as $key => $val) { if ($val === 'hour' || $val === 'min' || $val === 'sec') { if (!isset($data[$val]) || $data[$val] === '0' || $data[$val] === '00') { $data[$val] = '00'; } else { $data[$val] = sprintf('%02d', $data[$val]); } } if (!isset($data[$val]) || isset($data[$val]) && (empty($data[$val]) || $data[$val][0] === '-')) { return null; } if (isset($data[$val]) && !empty($data[$val])) { $date[$key] = $data[$val]; } } } if ($useNewDate && !empty($date)) { $format = $this->getDataSource()->columns[$type]['format']; foreach (array('m', 'd', 'H', 'i', 's') as $index) { if (isset($date[$index])) { $date[$index] = sprintf('%02d', $date[$index]); } } return str_replace(array_keys($date), array_values($date), $format); } return $data; } /** * Returns an array of table metadata (column names and types) from the database. * $field => keys(type, null, default, key, length, extra) * * @param bool|string $field Set to true to reload schema, or a string to return a specific field * @return array|null Array of table metadata */ public function schema($field = false) { if ($this->useTable !== false && (!is_array($this->_schema) || $field === true)) { $db = $this->getDataSource(); $db->cacheSources = ($this->cacheSources && $db->cacheSources); if (method_exists($db, 'describe')) { $this->_schema = $db->describe($this); } } if (!is_string($field)) { return $this->_schema; } if (isset($this->_schema[$field])) { return $this->_schema[$field]; } return null; } /** * Returns an associative array of field names and column types. * * @return array Field types indexed by field name */ public function getColumnTypes() { $columns = $this->schema(); if (empty($columns)) { trigger_error(__d('cake_dev', '(Model::getColumnTypes) Unable to build model field data. If you are using a model without a database table, try implementing schema()'), E_USER_WARNING); } $cols = array(); foreach ($columns as $field => $values) { $cols[$field] = $values['type']; } return $cols; } /** * Returns the column type of a column in the model. * * @param string $column The name of the model column * @return string Column type */ public function getColumnType($column) { $cols = $this->schema(); if (isset($cols[$column]) && isset($cols[$column]['type'])) { return $cols[$column]['type']; } $db = $this->getDataSource(); $model = null; $startQuote = isset($db->startQuote) ? $db->startQuote : null; $endQuote = isset($db->endQuote) ? $db->endQuote : null; $column = str_replace(array($startQuote, $endQuote), '', $column); if (strpos($column, '.')) { list($model, $column) = explode('.', $column); } if (isset($model) && $model != $this->alias && isset($this->{$model})) { return $this->{$model}->getColumnType($column); } if (isset($cols[$column]) && isset($cols[$column]['type'])) { return $cols[$column]['type']; } return null; } /** * Returns true if the supplied field exists in the model's database table. * * @param string|array $name Name of field to look for, or an array of names * @param bool $checkVirtual checks if the field is declared as virtual * @return mixed If $name is a string, returns a boolean indicating whether the field exists. * If $name is an array of field names, returns the first field that exists, * or false if none exist. */ public function hasField($name, $checkVirtual = false) { if (is_array($name)) { foreach ($name as $n) { if ($this->hasField($n, $checkVirtual)) { return $n; } } return false; } if ($checkVirtual && !empty($this->virtualFields) && $this->isVirtualField($name)) { return true; } if (empty($this->_schema)) { $this->schema(); } if ($this->_schema) { return isset($this->_schema[$name]); } return false; } /** * Check that a method is callable on a model. This will check both the model's own methods, its * inherited methods and methods that could be callable through behaviors. * * @param string $method The method to be called. * @return bool True on method being callable. */ public function hasMethod($method) { if (method_exists($this, $method)) { return true; } return $this->Behaviors->hasMethod($method); } /** * Returns true if the supplied field is a model Virtual Field * * @param string $field Name of field to look for * @return bool indicating whether the field exists as a model virtual field. */ public function isVirtualField($field) { if (empty($this->virtualFields) || !is_string($field)) { return false; } if (isset($this->virtualFields[$field])) { return true; } if (strpos($field, '.') !== false) { list($model, $field) = explode('.', $field); if ($model === $this->alias && isset($this->virtualFields[$field])) { return true; } } return false; } /** * Returns the expression for a model virtual field * * @param string $field Name of field to look for * @return mixed If $field is string expression bound to virtual field $field * If $field is null, returns an array of all model virtual fields * or false if none $field exist. */ public function getVirtualField($field = null) { if (!$field) { return empty($this->virtualFields) ? false : $this->virtualFields; } if ($this->isVirtualField($field)) { if (strpos($field, '.') !== false) { list(, $field) = pluginSplit($field); } return $this->virtualFields[$field]; } return false; } /** * Initializes the model for writing a new record, loading the default values * for those fields that are not defined in $data, and clearing previous validation errors. * Especially helpful for saving data in loops. * * @param bool|array $data Optional data array to assign to the model after it is created. If null or false, * schema data defaults are not merged. * @param bool $filterKey If true, overwrites any primary key input with an empty value * @return array The current Model::data; after merging $data and/or defaults from database * @link http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-create-array-data-array */ public function create($data = array(), $filterKey = false) { $defaults = array(); $this->id = false; $this->data = array(); $this->validationErrors = array(); if ($data !== null && $data !== false) { $schema = (array)$this->schema(); foreach ($schema as $field => $properties) { if ($this->primaryKey !== $field && isset($properties['default']) && $properties['default'] !== '') { $defaults[$field] = $properties['default']; } } $this->set($defaults); $this->set($data); } if ($filterKey) { $this->set($this->primaryKey, false); } return $this->data; } /** * This function is a convenient wrapper class to create(false) and, as the name suggests, clears the id, data, and validation errors. * * @return bool Always true upon success * @see Model::create() */ public function clear() { $this->create(false); return true; } /** * Returns a list of fields from the database, and sets the current model * data (Model::$data) with the record found. * * @param string|array $fields String of single field name, or an array of field names. * @param int|string $id The ID of the record to read * @return array Array of database fields, or false if not found * @link http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#model-read */ public function read($fields = null, $id = null) { $this->validationErrors = array(); if ($id) { $this->id = $id; } $id = $this->id; if (is_array($this->id)) { $id = $this->id[0]; } if ($id !== null && $id !== false) { $this->data = $this->find('first', array( 'conditions' => array($this->alias . '.' . $this->primaryKey => $id), 'fields' => $fields )); return $this->data; } return false; } /** * Returns the content of a single field given the supplied conditions, * of the first record in the supplied order. * * @param string $name The name of the field to get. * @param array $conditions SQL conditions (defaults to NULL). * @param string $order SQL ORDER BY fragment. * @return string|false Field content, or false if not found. * @link http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#model-field */ public function field($name, $conditions = null, $order = null) { if ($conditions === null && $this->id !== false) { $conditions = array($this->alias . '.' . $this->primaryKey => $this->id); } $recursive = $this->recursive; if ($this->recursive >= 1) { $recursive = -1; } $fields = $name; $data = $this->find('first', compact('conditions', 'fields', 'order', 'recursive')); if (!$data) { return false; } if (strpos($name, '.') === false) { if (isset($data[$this->alias][$name])) { return $data[$this->alias][$name]; } } else { $name = explode('.', $name); if (isset($data[$name[0]][$name[1]])) { return $data[$name[0]][$name[1]]; } } if (isset($data[0]) && count($data[0]) > 0) { return array_shift($data[0]); } } /** * Saves the value of a single field to the database, based on the current * model ID. * * @param string $name Name of the table field * @param mixed $value Value of the field * @param bool|array $validate Either a boolean, or an array. * If a boolean, indicates whether or not to validate before saving. * If an array, allows control of 'validate', 'callbacks' and 'counterCache' options. * See Model::save() for details of each options. * @return bool|array See Model::save() False on failure or an array of model data on success. * @see Model::save() * @link http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-savefield-string-fieldname-string-fieldvalue-validate-false */ public function saveField($name, $value, $validate = false) { $id = $this->id; $this->create(false); $options = array('validate' => $validate, 'fieldList' => array($name)); if (is_array($validate)) { $options = $validate + array('validate' => false, 'fieldList' => array($name)); } return $this->save(array($this->alias => array($this->primaryKey => $id, $name => $value)), $options); } /** * Saves model data (based on white-list, if supplied) to the database. By * default, validation occurs before save. Passthrough method to _doSave() with * transaction handling. * * @param array $data Data to save. * @param bool|array $validate Either a boolean, or an array. * If a boolean, indicates whether or not to validate before saving. * If an array, can have following keys: * * - atomic: If true (default), will attempt to save the record in a single transaction. * - validate: Set to true/false to enable or disable validation. * - fieldList: An array of fields you want to allow for saving. * - callbacks: Set to false to disable callbacks. Using 'before' or 'after' * will enable only those callbacks. * - `counterCache`: Boolean to control updating of counter caches (if any) * * @param array $fieldList List of fields to allow to be saved * @return mixed On success Model::$data if its not empty or true, false on failure * @throws Exception * @throws PDOException * @triggers Model.beforeSave $this, array($options) * @triggers Model.afterSave $this, array($created, $options) * @link http://book.cakephp.org/2.0/en/models/saving-your-data.html */ public function save($data = null, $validate = true, $fieldList = array()) { $defaults = array( 'validate' => true, 'fieldList' => array(), 'callbacks' => true, 'counterCache' => true, 'atomic' => true ); if (!is_array($validate)) { $options = compact('validate', 'fieldList') + $defaults; } else { $options = $validate + $defaults; } if (!$options['atomic']) { return $this->_doSave($data, $options); } $db = $this->getDataSource(); $transactionBegun = $db->begin(); try { $success = $this->_doSave($data, $options); if ($transactionBegun) { if ($success) { $db->commit(); } else { $db->rollback(); } } return $success; } catch (Exception $e) { if ($transactionBegun) { $db->rollback(); } throw $e; } } /** * Saves model data (based on white-list, if supplied) to the database. By * default, validation occurs before save. * * @param array $data Data to save. * @param array $options can have following keys: * * - validate: Set to true/false to enable or disable validation. * - fieldList: An array of fields you want to allow for saving. * - callbacks: Set to false to disable callbacks. Using 'before' or 'after' * will enable only those callbacks. * - `counterCache`: Boolean to control updating of counter caches (if any) * * @return mixed On success Model::$data if its not empty or true, false on failure * @throws PDOException * @link http://book.cakephp.org/2.0/en/models/saving-your-data.html */ protected function _doSave($data = null, $options = array()) { $_whitelist = $this->whitelist; $fields = array(); if (!empty($options['fieldList'])) { if (!empty($options['fieldList'][$this->alias]) && is_array($options['fieldList'][$this->alias])) { $this->whitelist = $options['fieldList'][$this->alias]; } elseif (Hash::dimensions($options['fieldList']) < 2) { $this->whitelist = $options['fieldList']; } } elseif ($options['fieldList'] === null) { $this->whitelist = array(); } $this->set($data); if (empty($this->data) && !$this->hasField(array('created', 'updated', 'modified'))) { $this->whitelist = $_whitelist; return false; } foreach (array('created', 'updated', 'modified') as $field) { $keyPresentAndEmpty = ( isset($this->data[$this->alias]) && array_key_exists($field, $this->data[$this->alias]) && $this->data[$this->alias][$field] === null ); if ($keyPresentAndEmpty) { unset($this->data[$this->alias][$field]); } } $exists = $this->exists(); $dateFields = array('modified', 'updated'); if (!$exists) { $dateFields[] = 'created'; } if (isset($this->data[$this->alias])) { $fields = array_keys($this->data[$this->alias]); } if ($options['validate'] && !$this->validates($options)) { $this->whitelist = $_whitelist; return false; } $db = $this->getDataSource(); $now = time(); foreach ($dateFields as $updateCol) { $fieldHasValue = in_array($updateCol, $fields); $fieldInWhitelist = ( count($this->whitelist) === 0 || in_array($updateCol, $this->whitelist) ); if (($fieldHasValue && $fieldInWhitelist) || !$this->hasField($updateCol)) { continue; } $default = array('formatter' => 'date'); $colType = array_merge($default, $db->columns[$this->getColumnType($updateCol)]); $time = $now; if (array_key_exists('format', $colType)) { $time = call_user_func($colType['formatter'], $colType['format']); } if (!empty($this->whitelist)) { $this->whitelist[] = $updateCol; } $this->set($updateCol, $time); } if ($options['callbacks'] === true || $options['callbacks'] === 'before') { $event = new CakeEvent('Model.beforeSave', $this, array($options)); list($event->break, $event->breakOn) = array(true, array(false, null)); $this->getEventManager()->dispatch($event); if (!$event->result) { $this->whitelist = $_whitelist; return false; } } if (empty($this->data[$this->alias][$this->primaryKey])) { unset($this->data[$this->alias][$this->primaryKey]); } $joined = $fields = $values = array(); foreach ($this->data as $n => $v) { if (isset($this->hasAndBelongsToMany[$n])) { if (isset($v[$n])) { $v = $v[$n]; } $joined[$n] = $v; } elseif ($n === $this->alias) { foreach (array('created', 'updated', 'modified') as $field) { if (array_key_exists($field, $v) && empty($v[$field])) { unset($v[$field]); } } foreach ($v as $x => $y) { if ($this->hasField($x) && (empty($this->whitelist) || in_array($x, $this->whitelist))) { list($fields[], $values[]) = array($x, $y); } } } } if (empty($fields) && empty($joined)) { $this->whitelist = $_whitelist; return false; } $count = count($fields); if (!$exists && $count > 0) { $this->id = false; } $success = true; $created = false; if ($count > 0) { $cache = $this->_prepareUpdateFields(array_combine($fields, $values)); if (!empty($this->id)) { $this->__safeUpdateMode = true; try { $success = (bool)$db->update($this, $fields, $values); } catch (Exception $e) { $this->__safeUpdateMode = false; throw $e; } $this->__safeUpdateMode = false; } else { if (empty($this->data[$this->alias][$this->primaryKey]) && $this->_isUUIDField($this->primaryKey)) { if (array_key_exists($this->primaryKey, $this->data[$this->alias])) { $j = array_search($this->primaryKey, $fields); $values[$j] = CakeText::uuid(); } else { list($fields[], $values[]) = array($this->primaryKey, CakeText::uuid()); } } if (!$db->create($this, $fields, $values)) { $success = false; } else { $created = true; } } if ($success && $options['counterCache'] && !empty($this->belongsTo)) { $this->updateCounterCache($cache, $created); } } if ($success && !empty($joined)) { $this->_saveMulti($joined, $this->id, $db); } if (!$success) { $this->whitelist = $_whitelist; return $success; } if ($count > 0) { if ($created) { $this->data[$this->alias][$this->primaryKey] = $this->id; } if ($options['callbacks'] === true || $options['callbacks'] === 'after') { $event = new CakeEvent('Model.afterSave', $this, array($created, $options)); $this->getEventManager()->dispatch($event); } } if (!empty($this->data)) { $success = $this->data; } $this->_clearCache(); $this->validationErrors = array(); $this->whitelist = $_whitelist; $this->data = false; return $success; } /** * Check if the passed in field is a UUID field * * @param string $field the field to check * @return bool */ protected function _isUUIDField($field) { $field = $this->schema($field); return $field['length'] == 36 && in_array($field['type'], array('string', 'binary')); } /** * Saves model hasAndBelongsToMany data to the database. * * @param array $joined Data to save * @param int|string $id ID of record in this model * @param DataSource $db Datasource instance. * @return void */ protected function _saveMulti($joined, $id, $db) { foreach ($joined as $assoc => $data) { if (!isset($this->hasAndBelongsToMany[$assoc])) { continue; } $habtm = $this->hasAndBelongsToMany[$assoc]; list($join) = $this->joinModel($habtm['with']); $Model = $this->{$join}; if (!empty($habtm['with'])) { $withModel = is_array($habtm['with']) ? key($habtm['with']) : $habtm['with']; list(, $withModel) = pluginSplit($withModel); $dbMulti = $this->{$withModel}->getDataSource(); } else { $dbMulti = $db; } $isUUID = !empty($Model->primaryKey) && $Model->_isUUIDField($Model->primaryKey); $newData = $newValues = $newJoins = array(); $primaryAdded = false; $fields = array( $dbMulti->name($habtm['foreignKey']), $dbMulti->name($habtm['associationForeignKey']) ); $idField = $db->name($Model->primaryKey); if ($isUUID && !in_array($idField, $fields)) { $fields[] = $idField; $primaryAdded = true; } foreach ((array)$data as $row) { if ((is_string($row) && (strlen($row) === 36 || strlen($row) === 16)) || is_numeric($row)) { $newJoins[] = $row; $values = array($id, $row); if ($isUUID && $primaryAdded) { $values[] = CakeText::uuid(); } $newValues[$row] = $values; unset($values); } elseif (isset($row[$habtm['associationForeignKey']])) { if (!empty($row[$Model->primaryKey])) { $newJoins[] = $row[$habtm['associationForeignKey']]; } $newData[] = $row; } elseif (isset($row[$join]) && isset($row[$join][$habtm['associationForeignKey']])) { if (!empty($row[$join][$Model->primaryKey])) { $newJoins[] = $row[$join][$habtm['associationForeignKey']]; } $newData[] = $row[$join]; } } $keepExisting = $habtm['unique'] === 'keepExisting'; if ($habtm['unique']) { $conditions = array( $join . '.' . $habtm['foreignKey'] => $id ); if (!empty($habtm['conditions'])) { $conditions = array_merge($conditions, (array)$habtm['conditions']); } $associationForeignKey = $Model->alias . '.' . $habtm['associationForeignKey']; $links = $Model->find('all', array( 'conditions' => $conditions, 'recursive' => empty($habtm['conditions']) ? -1 : 0, 'fields' => $associationForeignKey, )); $oldLinks = Hash::extract($links, "{n}.{$associationForeignKey}"); if (!empty($oldLinks)) { if ($keepExisting && !empty($newJoins)) { $conditions[$associationForeignKey] = array_diff($oldLinks, $newJoins); } else { $conditions[$associationForeignKey] = $oldLinks; } $dbMulti->delete($Model, $conditions); } } if (!empty($newData)) { foreach ($newData as $data) { $data[$habtm['foreignKey']] = $id; if (empty($data[$Model->primaryKey])) { $Model->create(); } $Model->save($data, array('atomic' => false)); } } if (!empty($newValues)) { if ($keepExisting && !empty($links)) { foreach ($links as $link) { $oldJoin = $link[$join][$habtm['associationForeignKey']]; if (!in_array($oldJoin, $newJoins)) { $conditions[$associationForeignKey] = $oldJoin; $db->delete($Model, $conditions); } else { unset($newValues[$oldJoin]); } } $newValues = array_values($newValues); } if (!empty($newValues)) { $dbMulti->insertMulti($Model, $fields, $newValues); } } } } /** * Updates the counter cache of belongsTo associations after a save or delete operation * * @param array $keys Optional foreign key data, defaults to the information $this->data * @param bool $created True if a new record was created, otherwise only associations with * 'counterScope' defined get updated * @return void */ public function updateCounterCache($keys = array(), $created = false) { if (empty($keys) && isset($this->data[$this->alias])) { $keys = $this->data[$this->alias]; } $keys['old'] = isset($keys['old']) ? $keys['old'] : array(); foreach ($this->belongsTo as $parent => $assoc) { if (empty($assoc['counterCache'])) { continue; } $Model = $this->{$parent}; if (!is_array($assoc['counterCache'])) { if (isset($assoc['counterScope'])) { $assoc['counterCache'] = array($assoc['counterCache'] => $assoc['counterScope']); } else { $assoc['counterCache'] = array($assoc['counterCache'] => array()); } } $foreignKey = $assoc['foreignKey']; $fkQuoted = $this->escapeField($assoc['foreignKey']); foreach ($assoc['counterCache'] as $field => $conditions) { if (!is_string($field)) { $field = Inflector::underscore($this->alias) . '_count'; } if (!$Model->hasField($field)) { continue; } if ($conditions === true) { $conditions = array(); } else { $conditions = (array)$conditions; } if (!array_key_exists($foreignKey, $keys)) { $keys[$foreignKey] = $this->field($foreignKey); } $recursive = (empty($conditions) ? -1 : 0); if (isset($keys['old'][$foreignKey]) && $keys['old'][$foreignKey] != $keys[$foreignKey]) { $conditions[$fkQuoted] = $keys['old'][$foreignKey]; $count = (int)$this->find('count', compact('conditions', 'recursive')); $Model->updateAll( array($field => $count), array($Model->escapeField() => $keys['old'][$foreignKey]) ); } $conditions[$fkQuoted] = $keys[$foreignKey]; if ($recursive === 0) { $conditions = array_merge($conditions, (array)$conditions); } $count = (int)$this->find('count', compact('conditions', 'recursive')); $Model->updateAll( array($field => $count), array($Model->escapeField() => $keys[$foreignKey]) ); } } } /** * Helper method for `Model::updateCounterCache()`. Checks the fields to be updated for * * @param array $data The fields of the record that will be updated * @return array Returns updated foreign key values, along with an 'old' key containing the old * values, or empty if no foreign keys are updated. */ protected function _prepareUpdateFields($data) { $foreignKeys = array(); foreach ($this->belongsTo as $assoc => $info) { if (isset($info['counterCache']) && $info['counterCache']) { $foreignKeys[$assoc] = $info['foreignKey']; } } $included = array_intersect($foreignKeys, array_keys($data)); if (empty($included) || empty($this->id)) { return array(); } $old = $this->find('first', array( 'conditions' => array($this->alias . '.' . $this->primaryKey => $this->id), 'fields' => array_values($included), 'recursive' => -1 )); return array_merge($data, array('old' => $old[$this->alias])); } /** * Backwards compatible passthrough method for: * saveMany(), validateMany(), saveAssociated() and validateAssociated() * * Saves multiple individual records for a single model; Also works with a single record, as well as * all its associated records. * * #### Options * * - `validate`: Set to false to disable validation, true to validate each record before saving, * 'first' to validate *all* records before any are saved (default), * 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(). * 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 * - `callbacks`: See Model::save() * - `counterCache`: See Model::save() * * @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. * @param array $options Options to use when saving record data, See $options above. * @return mixed If atomic: True on success, or false on failure. * Otherwise: array similar to the $data array passed, but values are set to true/false * depending on whether each record saved successfully. * @link http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-saveassociated-array-data-null-array-options-array * @link http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-saveall-array-data-null-array-options-array */ public function saveAll($data = array(), $options = array()) { $options += array('validate' => 'first'); if (Hash::numeric(array_keys($data))) { if ($options['validate'] === 'only') { return $this->validateMany($data, $options); } return $this->saveMany($data, $options); } if ($options['validate'] === 'only') { return $this->validateAssociated($data, $options); } return $this->saveAssociated($data, $options); } /** * Saves multiple individual records for a single model * * #### Options * * - `validate`: Set to false to disable validation, true to validate each record before saving, * '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() * - `deep`: If set to true, all associated data will be saved as well. * - `callbacks`: See Model::save() * - `counterCache`: See Model::save() * * @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. * @return mixed If atomic: True on success, or false on failure. * Otherwise: array similar to the $data array passed, but values are set to true/false * depending on whether each record saved successfully. * @throws PDOException * @link http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-savemany-array-data-null-array-options-array */ public function saveMany($data = null, $options = array()) { if (empty($data)) { $data = $this->data; } $options += array('validate' => 'first', 'atomic' => true, 'deep' => false); $this->validationErrors = $validationErrors = array(); if (empty($data) && $options['validate'] !== false) { $result = $this->save($data, $options); if (!$options['atomic']) { return array(!empty($result)); } return !empty($result); } if ($options['validate'] === 'first') { $validates = $this->validateMany($data, $options); if ((!$validates && $options['atomic']) || (!$options['atomic'] && in_array(false, $validates, true))) { return $validates; } $options['validate'] = false; } $transactionBegun = false; if ($options['atomic']) { $db = $this->getDataSource(); $transactionBegun = $db->begin(); } try { $return = array(); foreach ($data as $key => $record) { $validates = $this->create(null) !== null; $saved = false; if ($validates) { if ($options['deep']) { $saved = $this->saveAssociated($record, array('atomic' => false) + $options); } else { $saved = (bool)$this->save($record, array('atomic' => false) + $options); } } $validates = ($validates && ($saved === true || (is_array($saved) && !in_array(false, Hash::flatten($saved), true)))); if (!$validates) { $validationErrors[$key] = $this->validationErrors; } if (!$options['atomic']) { $return[$key] = $validates; } elseif (!$validates) { break; } } $this->validationErrors = $validationErrors; if (!$options['atomic']) { return $return; } if ($validates) { if ($transactionBegun) { return $db->commit() !== false; } return true; } if ($transactionBegun) { $db->rollback(); } return false; } catch (Exception $e) { if ($transactionBegun) { $db->rollback(); } throw $e; } } /** * Validates multiple individual records for a single model * * #### Options * * - `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. * * Warning: This method could potentially change the passed argument `$data`, * If you do not want this to happen, make a copy of `$data` before passing it * to this method * * @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(). * @return bool|array If atomic: True on success, or false on failure. * Otherwise: array similar to the $data array passed, but values are set to true/false * depending on whether each record validated successfully. */ public function validateMany(&$data, $options = array()) { return $this->validator()->validateMany($data, $options); } /** * Saves a single record, as well as all its directly associated records. * * #### Options * * - `validate`: Set to `false` to disable validation, `true` to validate each record before saving, * '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(). * 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. * - `callbacks`: See Model::save() * - `counterCache`: See Model::save() * * @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. * @return mixed If atomic: True on success, or false on failure. * Otherwise: array similar to the $data array passed, but values are set to true/false * depending on whether each record saved successfully. * @throws PDOException * @link http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-saveassociated-array-data-null-array-options-array */ public function saveAssociated($data = null, $options = array()) { if (empty($data)) { $data = $this->data; } $options += array('validate' => 'first', 'atomic' => true, 'deep' => false); $this->validationErrors = $validationErrors = array(); if (empty($data) && $options['validate'] !== false) { $result = $this->save($data, $options); if (!$options['atomic']) { return array(!empty($result)); } return !empty($result); } if ($options['validate'] === 'first') { $validates = $this->validateAssociated($data, $options); if ((!$validates && $options['atomic']) || (!$options['atomic'] && in_array(false, Hash::flatten($validates), true))) { return $validates; } $options['validate'] = false; } $transactionBegun = false; if ($options['atomic']) { $db = $this->getDataSource(); $transactionBegun = $db->begin(); } try { $associations = $this->getAssociated(); $return = array(); $validates = true; foreach ($data as $association => $values) { $isEmpty = empty($values) || (isset($values[$association]) && empty($values[$association])); if ($isEmpty || !isset($associations[$association]) || $associations[$association] !== 'belongsTo') { continue; } $Model = $this->{$association}; $validates = $Model->create(null) !== null; $saved = false; if ($validates) { if ($options['deep']) { $saved = $Model->saveAssociated($values, array('atomic' => false) + $options); } else { $saved = (bool)$Model->save($values, array('atomic' => false) + $options); } $validates = ($saved === true || (is_array($saved) && !in_array(false, Hash::flatten($saved), true))); } if ($validates) { $key = $this->belongsTo[$association]['foreignKey']; if (isset($data[$this->alias])) { $data[$this->alias][$key] = $Model->id; } else { $data = array_merge(array($key => $Model->id), $data, array($key => $Model->id)); } $options = $this->_addToWhiteList($key, $options); } else { $validationErrors[$association] = $Model->validationErrors; } $return[$association] = $validates; } if ($validates && !($this->create(null) !== null && $this->save($data, array('atomic' => false) + $options))) { $validationErrors[$this->alias] = $this->validationErrors; $validates = false; } $return[$this->alias] = $validates; foreach ($data as $association => $values) { if (!$validates) { break; } $isEmpty = empty($values) || (isset($values[$association]) && empty($values[$association])); if ($isEmpty || !isset($associations[$association])) { continue; } $Model = $this->{$association}; $type = $associations[$association]; $key = $this->{$type}[$association]['foreignKey']; switch ($type) { case 'hasOne': if (isset($values[$association])) { $values[$association][$key] = $this->id; } else { $values = array_merge(array($key => $this->id), $values, array($key => $this->id)); } $validates = $Model->create(null) !== null; $saved = false; if ($validates) { $options = $Model->_addToWhiteList($key, $options); if ($options['deep']) { $saved = $Model->saveAssociated($values, array('atomic' => false) + $options); } else { $saved = (bool)$Model->save($values, $options); } } $validates = ($validates && ($saved === true || (is_array($saved) && !in_array(false, Hash::flatten($saved), true)))); if (!$validates) { $validationErrors[$association] = $Model->validationErrors; } $return[$association] = $validates; break; case 'hasMany': foreach ($values as $i => $value) { if (isset($values[$i][$association])) { $values[$i][$association][$key] = $this->id; } else { $values[$i] = array_merge(array($key => $this->id), $value, array($key => $this->id)); } } $options = $Model->_addToWhiteList($key, $options); $_return = $Model->saveMany($values, array('atomic' => false) + $options); if (in_array(false, $_return, true)) { $validationErrors[$association] = $Model->validationErrors; $validates = false; } $return[$association] = $_return; break; } } $this->validationErrors = $validationErrors; if (isset($validationErrors[$this->alias])) { $this->validationErrors = $validationErrors[$this->alias]; unset($validationErrors[$this->alias]); $this->validationErrors = array_merge($this->validationErrors, $validationErrors); } if (!$options['atomic']) { return $return; } if ($validates) { if ($transactionBegun) { return $db->commit() !== false; } return true; } if ($transactionBegun) { $db->rollback(); } return false; } catch (Exception $e) { if ($transactionBegun) { $db->rollback(); } throw $e; } } /** * Helper method for saveAll() and friends, to add foreign key to fieldlist * * @param string $key fieldname to be added to list * @param array $options Options list * @return array options */ protected function _addToWhiteList($key, $options) { if (empty($options['fieldList']) && $this->whitelist && !in_array($key, $this->whitelist)) { $options['fieldList'][$this->alias] = $this->whitelist; $options['fieldList'][$this->alias][] = $key; return $options; } if (!empty($options['fieldList'][$this->alias]) && is_array($options['fieldList'][$this->alias])) { $options['fieldList'][$this->alias][] = $key; return $options; } if (!empty($options['fieldList']) && is_array($options['fieldList']) && Hash::dimensions($options['fieldList']) < 2) { $options['fieldList'][] = $key; } return $options; } /** * Validates a single record, as well as all its directly associated records. * * #### Options * * - `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. * * Warning: This method could potentially change the passed argument `$data`, * If you do not want this to happen, make a copy of `$data` before passing it * to this method * * @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(). * @return array|bool If atomic: True on success, or false on failure. * Otherwise: array similar to the $data array passed, but values are set to true/false * depending on whether each record validated successfully. */ public function validateAssociated(&$data, $options = array()) { return $this->validator()->validateAssociated($data, $options); } /** * Updates multiple model records based on a set of conditions. * * @param array $fields Set of fields and values, indexed by fields. * Fields are treated as SQL snippets, to insert literal values manually escape your data. * @param mixed $conditions Conditions to match, true for all records * @return bool True on success, false on failure * @link http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-updateall-array-fields-mixed-conditions */ public function updateAll($fields, $conditions = true) { return $this->getDataSource()->update($this, $fields, null, $conditions); } /** * Removes record for given ID. If no ID is given, the current ID is used. Returns true on success. * * @param int|string $id ID of record to delete * @param bool $cascade Set to true to delete records that depend on this record * @return bool True on success * @triggers Model.beforeDelete $this, array($cascade) * @triggers Model.afterDelete $this * @link http://book.cakephp.org/2.0/en/models/deleting-data.html */ public function delete($id = null, $cascade = true) { if (!empty($id)) { $this->id = $id; } $id = $this->id; $event = new CakeEvent('Model.beforeDelete', $this, array($cascade)); list($event->break, $event->breakOn) = array(true, array(false, null)); $this->getEventManager()->dispatch($event); if ($event->isStopped()) { return false; } if (!$this->exists()) { return false; } $this->_deleteDependent($id, $cascade); $this->_deleteLinks($id); $this->id = $id; if (!empty($this->belongsTo)) { foreach ($this->belongsTo as $assoc) { if (empty($assoc['counterCache'])) { continue; } $keys = $this->find('first', array( 'fields' => $this->_collectForeignKeys(), 'conditions' => array($this->alias . '.' . $this->primaryKey => $id), 'recursive' => -1, 'callbacks' => false )); break; } } if (!$this->getDataSource()->delete($this, array($this->alias . '.' . $this->primaryKey => $id))) { return false; } if (!empty($keys[$this->alias])) { $this->updateCounterCache($keys[$this->alias]); } $this->getEventManager()->dispatch(new CakeEvent('Model.afterDelete', $this)); $this->_clearCache(); $this->id = false; return true; } /** * Cascades model deletes through associated hasMany and hasOne child records. * * @param string $id ID of record that was deleted * @param bool $cascade Set to true to delete records that depend on this record * @return void */ protected function _deleteDependent($id, $cascade) { if ($cascade !== true) { return; } if (!empty($this->__backAssociation)) { $savedAssociations = $this->__backAssociation; $this->__backAssociation = array(); } foreach (array_merge($this->hasMany, $this->hasOne) as $assoc => $data) { if ($data['dependent'] !== true) { continue; } $Model = $this->{$assoc}; if ($data['foreignKey'] === false && $data['conditions'] && in_array($this->name, $Model->getAssociated('belongsTo'))) { $Model->recursive = 0; $conditions = array($this->escapeField(null, $this->name) => $id); } else { $Model->recursive = -1; $conditions = array($Model->escapeField($data['foreignKey']) => $id); if ($data['conditions']) { $conditions = array_merge((array)$data['conditions'], $conditions); } } if (isset($data['exclusive']) && $data['exclusive']) { $Model->deleteAll($conditions); } else { $records = $Model->find('all', array( 'conditions' => $conditions, 'fields' => $Model->primaryKey )); if (!empty($records)) { foreach ($records as $record) { $Model->delete($record[$Model->alias][$Model->primaryKey]); } } } } if (isset($savedAssociations)) { $this->__backAssociation = $savedAssociations; } } /** * Cascades model deletes through HABTM join keys. * * @param string $id ID of record that was deleted * @return void */ protected function _deleteLinks($id) { foreach ($this->hasAndBelongsToMany as $data) { list(, $joinModel) = pluginSplit($data['with']); $Model = $this->{$joinModel}; $records = $Model->find('all', array( 'conditions' => array($Model->escapeField($data['foreignKey']) => $id), 'fields' => $Model->primaryKey, 'recursive' => -1, 'callbacks' => false )); if (!empty($records)) { foreach ($records as $record) { $Model->delete($record[$Model->alias][$Model->primaryKey]); } } } } /** * Deletes multiple model records based on a set of conditions. * * @param mixed $conditions Conditions to match * @param bool $cascade Set to true to delete records that depend on this record * @param bool $callbacks Run callbacks * @return bool True on success, false on failure * @link http://book.cakephp.org/2.0/en/models/deleting-data.html#deleteall */ public function deleteAll($conditions, $cascade = true, $callbacks = false) { if (empty($conditions)) { return false; } $db = $this->getDataSource(); if (!$cascade && !$callbacks) { return $db->delete($this, $conditions); } $ids = $this->find('all', array_merge(array( 'fields' => "{$this->alias}.{$this->primaryKey}", 'order' => false, 'group' => "{$this->alias}.{$this->primaryKey}", 'recursive' => 0), compact('conditions')) ); if ($ids === false || $ids === null) { return false; } $ids = Hash::extract($ids, "{n}.{$this->alias}.{$this->primaryKey}"); if (empty($ids)) { return true; } if ($callbacks) { $_id = $this->id; $result = true; foreach ($ids as $id) { $result = $result && $this->delete($id, $cascade); } $this->id = $_id; return $result; } foreach ($ids as $id) { $this->_deleteLinks($id); if ($cascade) { $this->_deleteDependent($id, $cascade); } } return $db->delete($this, array($this->alias . '.' . $this->primaryKey => $ids)); } /** * Collects foreign keys from associations. * * @param string $type Association type. * @return array */ protected function _collectForeignKeys($type = 'belongsTo') { $result = array(); foreach ($this->{$type} as $assoc => $data) { if (isset($data['foreignKey']) && is_string($data['foreignKey'])) { $result[$assoc] = $data['foreignKey']; } } return $result; } /** * Returns true if a record with particular ID exists. * * If $id is not passed it calls `Model::getID()` to obtain the current record ID, * and then performs a `Model::find('count')` on the currently configured datasource * to ascertain the existence of the record in persistent storage. * * @param int|string $id ID of record to check for existence * @return bool True if such a record exists */ public function exists($id = null) { if ($id === null) { $id = $this->getID(); } if ($id === false) { return false; } if ($this->useTable === false) { return false; } return (bool)$this->find('count', array( 'conditions' => array( $this->alias . '.' . $this->primaryKey => $id ), 'recursive' => -1, 'callbacks' => false )); } /** * Returns true if a record that meets given conditions exists. * * @param array $conditions SQL conditions array * @return bool True if such a record exists */ public function hasAny($conditions = null) { return (bool)$this->find('count', array('conditions' => $conditions, 'recursive' => -1)); } /** * Queries the datasource and returns a result set array. * * Used to perform find operations, where the first argument is type of find operation to perform * (all / first / count / neighbors / list / threaded), * second parameter options for finding (indexed array, including: 'conditions', 'limit', * 'recursive', 'page', 'fields', 'offset', 'order', 'callbacks') * * Eg: * ``` * $model->find('all', array( * 'conditions' => array('name' => 'Thomas Anderson'), * 'fields' => array('name', 'email'), * 'order' => 'field3 DESC', * 'recursive' => 2, * 'group' => 'type', * 'callbacks' => false, * )); * ``` * * In addition to the standard query keys above, you can provide Datasource, and behavior specific * keys. For example, when using a SQL based datasource you can use the joins key to specify additional * joins that should be part of the query. * * ``` * $model->find('all', array( * 'conditions' => array('name' => 'Thomas Anderson'), * 'joins' => array( * array( * 'alias' => 'Thought', * 'table' => 'thoughts', * 'type' => 'LEFT', * 'conditions' => '`Thought`.`person_id` = `Person`.`id`' * ) * ) * )); * ``` * * ### Disabling callbacks * * The `callbacks` key allows you to disable or specify the callbacks that should be run. To * disable beforeFind & afterFind callbacks set `'callbacks' => false` in your options. You can * also set the callbacks option to 'before' or 'after' to enable only the specified callback. * * ### Adding new find types * * Behaviors and find types can also define custom finder keys which are passed into find(). * See the documentation for custom find types * (http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#creating-custom-find-types) * for how to implement custom find types. * * Specifying 'fields' for notation 'list': * * - If no fields are specified, then 'id' is used for key and 'model->displayField' is used for value. * - If a single field is specified, 'id' is used for key and specified field is used for value. * - If three fields are specified, they are used (in order) for key, value and group. * - Otherwise, first and second fields are used for key and value. * * Note: find(list) + database views have issues with MySQL 5.0. Try upgrading to MySQL 5.1 if you * have issues with database views. * * Note: find(count) has its own return values. * * @param string $type Type of find operation (all / first / count / neighbors / list / threaded) * @param array $query Option fields (conditions / fields / joins / limit / offset / order / page / group / callbacks) * @return array|null Array of records, or Null on failure. * @link http://book.cakephp.org/2.0/en/models/retrieving-your-data.html */ public function find($type = 'first', $query = array()) { $this->findQueryType = $type; $this->id = $this->getID(); $query = $this->buildQuery($type, $query); if ($query === null) { return null; } return $this->_readDataSource($type, $query); } /** * Read from the datasource * * Model::_readDataSource() is used by all find() calls to read from the data source and can be overloaded to allow * caching of datasource calls. * * ``` * protected function _readDataSource($type, $query) { * $cacheName = md5(json_encode($query)); * $cache = Cache::read($cacheName, 'cache-config-name'); * if ($cache !== false) { * return $cache; * } * * $results = parent::_readDataSource($type, $query); * Cache::write($cacheName, $results, 'cache-config-name'); * return $results; * } * ``` * * @param string $type Type of find operation (all / first / count / neighbors / list / threaded) * @param array $query Option fields (conditions / fields / joins / limit / offset / order / page / group / callbacks) * @return array */ protected function _readDataSource($type, $query) { $results = $this->getDataSource()->read($this, $query); $this->resetAssociations(); if ($query['callbacks'] === true || $query['callbacks'] === 'after') { $results = $this->_filterResults($results); } $this->findQueryType = null; if ($this->findMethods[$type] === true) { return $this->{'_find' . ucfirst($type)}('after', $query, $results); } } /** * Builds the query array that is used by the data source to generate the query to fetch the data. * * @param string $type Type of find operation (all / first / count / neighbors / list / threaded) * @param array $query Option fields (conditions / fields / joins / limit / offset / order / page / group / callbacks) * @return array|null Query array or null if it could not be build for some reasons * @triggers Model.beforeFind $this, array($query) * @see Model::find() */ public function buildQuery($type = 'first', $query = array()) { $query = array_merge( array( 'conditions' => null, 'fields' => null, 'joins' => array(), 'limit' => null, 'offset' => null, 'order' => null, 'page' => 1, 'group' => null, 'callbacks' => true, ), (array)$query ); if ($this->findMethods[$type] === true) { $query = $this->{'_find' . ucfirst($type)}('before', $query); } if (!is_numeric($query['page']) || (int)$query['page'] < 1) { $query['page'] = 1; } if ($query['page'] > 1 && !empty($query['limit'])) { $query['offset'] = ($query['page'] - 1) * $query['limit']; } if ($query['order'] === null && $this->order !== null) { $query['order'] = $this->order; } $query['order'] = (array)$query['order']; if ($query['callbacks'] === true || $query['callbacks'] === 'before') { $event = new CakeEvent('Model.beforeFind', $this, array($query)); list($event->break, $event->breakOn, $event->modParams) = array(true, array(false, null), 0); $this->getEventManager()->dispatch($event); if ($event->isStopped()) { return null; } $query = $event->result === true ? $event->data[0] : $event->result; } return $query; } /** * Handles the before/after filter logic for find('all') operations. Only called by Model::find(). * * @param string $state Either "before" or "after" * @param array $query Query. * @param array $results Results. * @return array * @see Model::find() */ protected function _findAll($state, $query, $results = array()) { if ($state === 'before') { return $query; } return $results; } /** * Handles the before/after filter logic for find('first') operations. Only called by Model::find(). * * @param string $state Either "before" or "after" * @param array $query Query. * @param array $results Results. * @return array * @see Model::find() */ protected function _findFirst($state, $query, $results = array()) { if ($state === 'before') { $query['limit'] = 1; return $query; } if (empty($results[0])) { return array(); } return $results[0]; } /** * Handles the before/after filter logic for find('count') operations. Only called by Model::find(). * * @param string $state Either "before" or "after" * @param array $query Query. * @param array $results Results. * @return int The number of records found, or false * @see Model::find() */ protected function _findCount($state, $query, $results = array()) { if ($state === 'before') { if (!empty($query['type']) && isset($this->findMethods[$query['type']]) && $query['type'] !== 'count') { $query['operation'] = 'count'; $query = $this->{'_find' . ucfirst($query['type'])}('before', $query); } $db = $this->getDataSource(); $query['order'] = false; if (!method_exists($db, 'calculate')) { return $query; } if (!empty($query['fields']) && is_array($query['fields'])) { if (!preg_match('/^count/i', current($query['fields']))) { unset($query['fields']); } } if (empty($query['fields'])) { $query['fields'] = $db->calculate($this, 'count'); } elseif (method_exists($db, 'expression') && is_string($query['fields']) && !preg_match('/count/i', $query['fields'])) { $query['fields'] = $db->calculate($this, 'count', array( $db->expression($query['fields']), 'count' )); } return $query; } foreach (array(0, $this->alias) as $key) { if (isset($results[0][$key]['count'])) { if ($query['group']) { return count($results); } return (int)$results[0][$key]['count']; } } return false; } /** * Handles the before/after filter logic for find('list') operations. Only called by Model::find(). * * @param string $state Either "before" or "after" * @param array $query Query. * @param array $results Results. * @return array Key/value pairs of primary keys/display field values of all records found * @see Model::find() */ protected function _findList($state, $query, $results = array()) { if ($state === 'before') { if (empty($query['fields'])) { $query['fields'] = array("{$this->alias}.{$this->primaryKey}", "{$this->alias}.{$this->displayField}"); $list = array("{n}.{$this->alias}.{$this->primaryKey}", "{n}.{$this->alias}.{$this->displayField}", null); } else { if (!is_array($query['fields'])) { $query['fields'] = CakeText::tokenize($query['fields']); } if (count($query['fields']) === 1) { if (strpos($query['fields'][0], '.') === false) { $query['fields'][0] = $this->alias . '.' . $query['fields'][0]; } $list = array("{n}.{$this->alias}.{$this->primaryKey}", '{n}.' . $query['fields'][0], null); $query['fields'] = array("{$this->alias}.{$this->primaryKey}", $query['fields'][0]); } elseif (count($query['fields']) === 3) { for ($i = 0; $i < 3; $i++) { if (strpos($query['fields'][$i], '.') === false) { $query['fields'][$i] = $this->alias . '.' . $query['fields'][$i]; } } $list = array('{n}.' . $query['fields'][0], '{n}.' . $query['fields'][1], '{n}.' . $query['fields'][2]); } else { for ($i = 0; $i < 2; $i++) { if (strpos($query['fields'][$i], '.') === false) { $query['fields'][$i] = $this->alias . '.' . $query['fields'][$i]; } } $list = array('{n}.' . $query['fields'][0], '{n}.' . $query['fields'][1], null); } } if (!isset($query['recursive']) || $query['recursive'] === null) { $query['recursive'] = -1; } list($query['list']['keyPath'], $query['list']['valuePath'], $query['list']['groupPath']) = $list; return $query; } if (empty($results)) { return array(); } return Hash::combine($results, $query['list']['keyPath'], $query['list']['valuePath'], $query['list']['groupPath']); } /** * Detects the previous field's value, then uses logic to find the 'wrapping' * rows and return them. * * @param string $state Either "before" or "after" * @param array $query Query. * @param array $results Results. * @return array */ protected function _findNeighbors($state, $query, $results = array()) { extract($query); if ($state === 'before') { $conditions = (array)$conditions; if (isset($field) && isset($value)) { if (strpos($field, '.') === false) { $field = $this->alias . '.' . $field; } } else { $field = $this->alias . '.' . $this->primaryKey; $value = $this->id; } $query['conditions'] = array_merge($conditions, array($field . ' <' => $value)); $query['order'] = $field . ' DESC'; $query['limit'] = 1; $query['field'] = $field; $query['value'] = $value; return $query; } unset($query['conditions'][$field . ' <']); $return = array(); if (isset($results[0])) { $prevVal = Hash::get($results[0], $field); $query['conditions'][$field . ' >='] = $prevVal; $query['conditions'][$field . ' !='] = $value; $query['limit'] = 2; } else { $return['prev'] = null; $query['conditions'][$field . ' >'] = $value; $query['limit'] = 1; } $query['order'] = $field . ' ASC'; $neighbors = $this->find('all', $query); if (!array_key_exists('prev', $return)) { $return['prev'] = isset($neighbors[0]) ? $neighbors[0] : null; } if (count($neighbors) === 2) { $return['next'] = $neighbors[1]; } elseif (count($neighbors) === 1 && !$return['prev']) { $return['next'] = $neighbors[0]; } else { $return['next'] = null; } return $return; } /** * In the event of ambiguous results returned (multiple top level results, with different parent_ids) * top level results with different parent_ids to the first result will be dropped * * @param string $state Either "before" or "after". * @param array $query Query. * @param array $results Results. * @return array Threaded results */ protected function _findThreaded($state, $query, $results = array()) { if ($state === 'before') { return $query; } $parent = 'parent_id'; if (isset($query['parent'])) { $parent = $query['parent']; } return Hash::nest($results, array( 'idPath' => '{n}.' . $this->alias . '.' . $this->primaryKey, 'parentPath' => '{n}.' . $this->alias . '.' . $parent )); } /** * Passes query results through model and behavior afterFind() methods. * * @param array $results Results to filter * @param bool $primary If this is the primary model results (results from model where the find operation was performed) * @return array Set of filtered results * @triggers Model.afterFind $this, array($results, $primary) */ protected function _filterResults($results, $primary = true) { $event = new CakeEvent('Model.afterFind', $this, array($results, $primary)); $event->modParams = 0; $this->getEventManager()->dispatch($event); return $event->result; } /** * This resets the association arrays for the model back * to those originally defined in the model. Normally called at the end * of each call to Model::find() * * @return bool Success */ public function resetAssociations() { if (!empty($this->__backAssociation)) { foreach ($this->_associations as $type) { if (isset($this->__backAssociation[$type])) { $this->{$type} = $this->__backAssociation[$type]; } } $this->__backAssociation = array(); } foreach ($this->_associations as $type) { foreach ($this->{$type} as $key => $name) { if (property_exists($this, $key) && !empty($this->{$key}->__backAssociation)) { $this->{$key}->resetAssociations(); } } } $this->__backAssociation = array(); return true; } /** * Returns false if any fields passed match any (by default, all if $or = false) of their matching values. * * Can be used as a validation method. When used as a validation method, the `$or` parameter * contains an array of fields to be validated. * * @param array $fields Field/value pairs to search (if no values specified, they are pulled from $this->data) * @param bool|array $or If false, all fields specified must match in order for a false return value * @return bool False if any records matching any fields are found */ public function isUnique($fields, $or = true) { if (is_array($or)) { $isRule = ( array_key_exists('rule', $or) && array_key_exists('required', $or) && array_key_exists('message', $or) ); if (!$isRule) { $args = func_get_args(); $fields = $args[1]; $or = isset($args[2]) ? $args[2] : true; } } if (!is_array($fields)) { $fields = func_get_args(); $fieldCount = count($fields) - 1; if (is_bool($fields[$fieldCount])) { $or = $fields[$fieldCount]; unset($fields[$fieldCount]); } } foreach ($fields as $field => $value) { if (is_numeric($field)) { unset($fields[$field]); $field = $value; $value = null; if (isset($this->data[$this->alias][$field])) { $value = $this->data[$this->alias][$field]; } } if (strpos($field, '.') === false) { unset($fields[$field]); $fields[$this->alias . '.' . $field] = $value; } } if ($or) { $fields = array('or' => $fields); } if (!empty($this->id)) { $fields[$this->alias . '.' . $this->primaryKey . ' !='] = $this->id; } return !$this->find('count', array('conditions' => $fields, 'recursive' => -1)); } /** * Returns a resultset for a given SQL statement. Custom SQL queries should be performed with this method. * * The method can options 2nd and 3rd parameters. * * - 2nd param: Either a boolean to control query caching or an array of parameters * for use with prepared statement placeholders. * - 3rd param: If 2nd argument is provided, a boolean flag for enabling/disabled * query caching. * * @param string $sql SQL statement * @return mixed Resultset array or boolean indicating success / failure depending on the query executed * @link http://book.cakephp.org/2.0/en/models/retrieving-your-data.html#model-query */ public function query($sql) { $params = func_get_args(); $db = $this->getDataSource(); return call_user_func_array(array(&$db, 'query'), $params); } /** * Returns true if all fields pass validation. Will validate hasAndBelongsToMany associations * that use the 'with' key as well. Since _saveMulti is incapable of exiting a save operation. * * Will validate the currently set data. Use Model::set() or Model::create() to set the active data. * * @param array $options An optional array of custom options to be made available in the beforeValidate callback * @return bool True if there are no errors */ public function validates($options = array()) { return $this->validator()->validates($options); } /** * Returns an array of fields that have failed the validation of the current model. * * Additionally it populates the validationErrors property of the model with the same array. * * @param array|string $options An optional array of custom options to be made available in the beforeValidate callback * @return array Array of invalid fields and their error messages * @see Model::validates() */ public function invalidFields($options = array()) { return $this->validator()->errors($options); } /** * Marks a field as invalid, optionally setting the name of validation * rule (in case of multiple validation for field) that was broken. * * @param string $field The name of the field to invalidate * @param mixed $value Name of validation rule that was not failed, or validation message to * be returned. If no validation key is provided, defaults to true. * @return void */ public function invalidate($field, $value = true) { $this->validator()->invalidate($field, $value); } /** * Returns true if given field name is a foreign key in this model. * * @param string $field Returns true if the input string ends in "_id" * @return bool True if the field is a foreign key listed in the belongsTo array. */ public function isForeignKey($field) { $foreignKeys = array(); if (!empty($this->belongsTo)) { foreach ($this->belongsTo as $data) { $foreignKeys[] = $data['foreignKey']; } } return in_array($field, $foreignKeys); } /** * Escapes the field name and prepends the model name. Escaping is done according to the * current database driver's rules. * * @param string $field Field to escape (e.g: id) * @param string $alias Alias for the model (e.g: Post) * @return string The name of the escaped field for this Model (i.e. id becomes `Post`.`id`). */ public function escapeField($field = null, $alias = null) { if (empty($alias)) { $alias = $this->alias; } if (empty($field)) { $field = $this->primaryKey; } $db = $this->getDataSource(); if (strpos($field, $db->name($alias) . '.') === 0) { return $field; } return $db->name($alias . '.' . $field); } /** * Returns the current record's ID * * @param int $list Index on which the composed ID is located * @return mixed The ID of the current record, false if no ID */ public function getID($list = 0) { if (empty($this->id) || (is_array($this->id) && isset($this->id[0]) && empty($this->id[0]))) { return false; } if (!is_array($this->id)) { return $this->id; } if (isset($this->id[$list]) && !empty($this->id[$list])) { return $this->id[$list]; } if (isset($this->id[$list])) { return false; } return current($this->id); } /** * Returns the ID of the last record this model inserted. * * @return mixed Last inserted ID */ public function getLastInsertID() { return $this->getInsertID(); } /** * Returns the ID of the last record this model inserted. * * @return mixed Last inserted ID */ public function getInsertID() { return $this->_insertID; } /** * Sets the ID of the last record this model inserted * * @param int|string $id Last inserted ID * @return void */ public function setInsertID($id) { $this->_insertID = $id; } /** * Returns the number of rows returned from the last query. * * @return int Number of rows */ public function getNumRows() { return $this->getDataSource()->lastNumRows(); } /** * Returns the number of rows affected by the last query. * * @return int Number of rows */ public function getAffectedRows() { return $this->getDataSource()->lastAffected(); } /** * Sets the DataSource to which this model is bound. * * @param string $dataSource The name of the DataSource, as defined in app/Config/database.php * @return void * @throws MissingConnectionException */ public function setDataSource($dataSource = null) { $oldConfig = $this->useDbConfig; if ($dataSource) { $this->useDbConfig = $dataSource; } $db = ConnectionManager::getDataSource($this->useDbConfig); if (!empty($oldConfig) && isset($db->config['prefix'])) { $oldDb = ConnectionManager::getDataSource($oldConfig); if (!isset($this->tablePrefix) || (!isset($oldDb->config['prefix']) || $this->tablePrefix === $oldDb->config['prefix'])) { $this->tablePrefix = $db->config['prefix']; } } elseif (isset($db->config['prefix'])) { $this->tablePrefix = $db->config['prefix']; } $schema = $db->getSchemaName(); $defaultProperties = get_class_vars(get_class($this)); if (isset($defaultProperties['schemaName'])) { $schema = $defaultProperties['schemaName']; } $this->schemaName = $schema; } /** * Gets the DataSource to which this model is bound. * * @return DataSource A DataSource object */ public function getDataSource() { if (!$this->_sourceConfigured && $this->useTable !== false) { $this->_sourceConfigured = true; $this->setSource($this->useTable); } return ConnectionManager::getDataSource($this->useDbConfig); } /** * Get associations * * @return array */ public function associations() { return $this->_associations; } /** * Gets all the models with which this model is associated. * * @param string $type Only result associations of this type * @return array|null Associations */ public function getAssociated($type = null) { if (!$type) { $associated = array(); foreach ($this->_associations as $assoc) { if (!empty($this->{$assoc})) { $models = array_keys($this->{$assoc}); foreach ($models as $m) { $associated[$m] = $assoc; } } } return $associated; } if (in_array($type, $this->_associations)) { if (empty($this->{$type})) { return array(); } return array_keys($this->{$type}); } $assoc = array_merge( $this->hasOne, $this->hasMany, $this->belongsTo, $this->hasAndBelongsToMany ); if (array_key_exists($type, $assoc)) { foreach ($this->_associations as $a) { if (isset($this->{$a}[$type])) { $assoc[$type]['association'] = $a; break; } } return $assoc[$type]; } return null; } /** * Gets the name and fields to be used by a join model. This allows specifying join fields * in the association definition. * * @param string|array $assoc The model to be joined * @param array $keys Any join keys which must be merged with the keys queried * @return array */ public function joinModel($assoc, $keys = array()) { if (is_string($assoc)) { list(, $assoc) = pluginSplit($assoc); return array($assoc, array_keys($this->{$assoc}->schema())); } if (is_array($assoc)) { $with = key($assoc); return array($with, array_unique(array_merge($assoc[$with], $keys))); } trigger_error( __d('cake_dev', 'Invalid join model settings in %s. The association parameter has the wrong type, expecting a string or array, but was passed type: %s', $this->alias, gettype($assoc)), E_USER_WARNING ); } /** * Called before each find operation. Return false if you want to halt the find * call, otherwise return the (modified) query data. * * @param array $query Data used to execute this query, i.e. conditions, order, etc. * @return mixed true if the operation should continue, false if it should abort; or, modified * $query to continue with new $query * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforefind */ public function beforeFind($query) { return true; } /** * Called after each find operation. Can be used to modify any results returned by find(). * Return value should be the (modified) results. * * @param mixed $results The results of the find operation * @param bool $primary Whether this model is being queried directly (vs. being queried as an association) * @return mixed Result of the find operation * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#afterfind */ public function afterFind($results, $primary = false) { return $results; } /** * Called before each save operation, after validation. Return a non-true result * to halt the save. * * @param array $options Options passed from Model::save(). * @return bool True if the operation should continue, false if it should abort * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforesave * @see Model::save() */ public function beforeSave($options = array()) { return true; } /** * Called after each successful save operation. * * @param bool $created True if this save created a new record * @param array $options Options passed from Model::save(). * @return void * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#aftersave * @see Model::save() */ public function afterSave($created, $options = array()) { } /** * Called before every deletion operation. * * @param bool $cascade If true records that depend on this record will also be deleted * @return bool True if the operation should continue, false if it should abort * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforedelete */ public function beforeDelete($cascade = true) { return true; } /** * Called after every deletion operation. * * @return void * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#afterdelete */ public function afterDelete() { } /** * Called during validation operations, before validation. Please note that custom * validation rules can be defined in $validate. * * @param array $options Options passed from Model::save(). * @return bool True if validate operation should continue, false to abort * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#beforevalidate * @see Model::save() */ public function beforeValidate($options = array()) { return true; } /** * Called after data has been checked for errors * * @return void */ public function afterValidate() { } /** * Called when a DataSource-level error occurs. * * @return void * @link http://book.cakephp.org/2.0/en/models/callback-methods.html#onerror */ public function onError() { } /** * Clears cache for this model. * * @param string $type If null this deletes cached views if Cache.check is true * Will be used to allow deleting query cache also * @return mixed True on delete, null otherwise */ protected function _clearCache($type = null) { if ($type !== null || Configure::read('Cache.check') !== true) { return; } $pluralized = Inflector::pluralize($this->alias); $assoc = array( strtolower($pluralized), Inflector::underscore($pluralized) ); foreach ($this->_associations as $association) { foreach ($this->{$association} as $className) { $pluralizedAssociation = Inflector::pluralize($className['className']); if (!in_array(strtolower($pluralizedAssociation), $assoc)) { $assoc = array_merge($assoc, array( strtolower($pluralizedAssociation), Inflector::underscore($pluralizedAssociation) )); } } } clearCache(array_unique($assoc)); return true; } /** * Returns an instance of a model validator for this class * * @param ModelValidator $instance Model validator instance. * If null a new ModelValidator instance will be made using current model object * @return ModelValidator */ public function validator(ModelValidator $instance = null) { if ($instance) { $this->_validator = $instance; } elseif (!$this->_validator) { $this->_validator = new ModelValidator($this); } return $this->_validator; } } cakephp-2.8.0/lib/Cake/Model/ModelBehavior.php000066400000000000000000000177731265552240500210630ustar00rootroot00000000000000Model->doSomething($arg1, $arg2);`. * * ### Mapped methods * * Behaviors can also define mapped methods. Mapped methods use pattern matching for method invocation. This * allows you to create methods similar to Model::findAllByXXX methods on your behaviors. Mapped methods need to * be declared in your behaviors `$mapMethods` array. The method signature for a mapped method is slightly different * than a normal behavior mixin method. * * ``` * public $mapMethods = array('/do(\w+)/' => 'doSomething'); * * function doSomething(Model $model, $method, $arg1, $arg2) { * //do something * } * ``` * * The above will map every doXXX() method call to the behavior. As you can see, the model is * still the first parameter, but the called method name will be the 2nd parameter. This allows * you to munge the method name for additional information, much like Model::findAllByXX. * * @package Cake.Model * @see Model::$actsAs * @see BehaviorCollection::load() */ class ModelBehavior extends Object { /** * Contains configuration settings for use with individual model objects. This * is used because if multiple models use this Behavior, each will use the same * object instance. Individual model settings should be stored as an * associative array, keyed off of the model name. * * @var array * @see Model::$alias */ public $settings = array(); /** * Allows the mapping of preg-compatible regular expressions to public or * private methods in this class, where the array key is a /-delimited regular * expression, and the value is a class method. Similar to the functionality of * the findBy* / findAllBy* magic methods. * * @var array */ public $mapMethods = array(); /** * Setup this behavior with the specified configuration settings. * * @param Model $model Model using this behavior * @param array $config Configuration settings for $model * @return void */ public function setup(Model $model, $config = array()) { } /** * Clean up any initialization this behavior has done on a model. Called when a behavior is dynamically * detached from a model using Model::detach(). * * @param Model $model Model using this behavior * @return void * @see BehaviorCollection::detach() */ public function cleanup(Model $model) { if (isset($this->settings[$model->alias])) { unset($this->settings[$model->alias]); } } /** * beforeFind can be used to cancel find operations, or modify the query that will be executed. * By returning null/false you can abort a find. By returning an array you can modify/replace the query * that is going to be run. * * @param Model $model Model using this behavior * @param array $query Data used to execute this query, i.e. conditions, order, etc. * @return bool|array False or null will abort the operation. You can return an array to replace the * $query that will be eventually run. */ public function beforeFind(Model $model, $query) { return true; } /** * After find callback. Can be used to modify any results returned by find. * * @param Model $model Model using this behavior * @param mixed $results The results of the find operation * @param bool $primary Whether this model is being queried directly (vs. being queried as an association) * @return mixed An array value will replace the value of $results - any other value will be ignored. */ public function afterFind(Model $model, $results, $primary = false) { } /** * beforeValidate is called before a model is validated, you can use this callback to * add behavior validation rules into a models validate array. Returning false * will allow you to make the validation fail. * * @param Model $model Model using this behavior * @param array $options Options passed from Model::save(). * @return mixed False or null will abort the operation. Any other result will continue. * @see Model::save() */ public function beforeValidate(Model $model, $options = array()) { return true; } /** * afterValidate is called just after model data was validated, you can use this callback * to perform any data cleanup or preparation if needed * * @param Model $model Model using this behavior * @return mixed False will stop this event from being passed to other behaviors */ public function afterValidate(Model $model) { return true; } /** * beforeSave is called before a model is saved. Returning false from a beforeSave callback * will abort the save operation. * * @param Model $model Model using this behavior * @param array $options Options passed from Model::save(). * @return mixed False if the operation should abort. Any other result will continue. * @see Model::save() */ public function beforeSave(Model $model, $options = array()) { return true; } /** * afterSave is called after a model is saved. * * @param Model $model Model using this behavior * @param bool $created True if this save created a new record * @param array $options Options passed from Model::save(). * @return bool * @see Model::save() */ public function afterSave(Model $model, $created, $options = array()) { return true; } /** * Before delete is called before any delete occurs on the attached model, but after the model's * beforeDelete is called. Returning false from a beforeDelete will abort the delete. * * @param Model $model Model using this behavior * @param bool $cascade If true records that depend on this record will also be deleted * @return mixed False if the operation should abort. Any other result will continue. */ public function beforeDelete(Model $model, $cascade = true) { return true; } /** * After delete is called after any delete occurs on the attached model. * * @param Model $model Model using this behavior * @return void */ public function afterDelete(Model $model) { } /** * DataSource error callback * * @param Model $model Model using this behavior * @param string $error Error generated in DataSource * @return void */ public function onError(Model $model, $error) { } /** * If $model's whitelist property is non-empty, $field will be added to it. * Note: this method should *only* be used in beforeValidate or beforeSave to ensure * that it only modifies the whitelist for the current save operation. Also make sure * you explicitly set the value of the field which you are allowing. * * @param Model $model Model using this behavior * @param string $field Field to be added to $model's whitelist * @return void */ protected function _addToWhitelist(Model $model, $field) { if (is_array($field)) { foreach ($field as $f) { $this->_addToWhitelist($model, $f); } return; } if (!empty($model->whitelist) && !in_array($field, $model->whitelist)) { $model->whitelist[] = $field; } } } cakephp-2.8.0/lib/Cake/Model/ModelValidator.php000066400000000000000000000443331265552240500212410ustar00rootroot00000000000000_model = $Model; } /** * Returns true if all fields pass validation. Will validate hasAndBelongsToMany associations * that use the 'with' key as well. Since `Model::_saveMulti` is incapable of exiting a save operation. * * Will validate the currently set data. Use `Model::set()` or `Model::create()` to set the active data. * * @param array $options An optional array of custom options to be made available in the beforeValidate callback * @return bool True if there are no errors */ public function validates($options = array()) { $errors = $this->errors($options); if (empty($errors) && $errors !== false) { $errors = $this->_validateWithModels($options); } if (is_array($errors)) { return count($errors) === 0; } return $errors; } /** * Validates a single record, as well as all its directly associated records. * * #### Options * * - 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. * * Warning: This method could potentially change the passed argument `$data`, * If you do not want this to happen, make a copy of `$data` before passing it * to this method * * @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(). * @return array|bool If atomic: True on success, or false on failure. * Otherwise: array similar to the $data array passed, but values are set to true/false * depending on whether each record validated successfully. */ public function validateAssociated(&$data, $options = array()) { $model = $this->getModel(); $options += array('atomic' => true, 'deep' => false); $model->validationErrors = $validationErrors = $return = array(); $model->create(null); $return[$model->alias] = true; if (!($model->set($data) && $model->validates($options))) { $validationErrors[$model->alias] = $model->validationErrors; $return[$model->alias] = false; } $data = $model->data; if (!empty($options['deep']) && isset($data[$model->alias])) { $recordData = $data[$model->alias]; unset($data[$model->alias]); $data += $recordData; } $associations = $model->getAssociated(); foreach ($data as $association => &$values) { $validates = true; if (isset($associations[$association])) { if (in_array($associations[$association], array('belongsTo', 'hasOne'))) { if ($options['deep']) { $validates = $model->{$association}->validateAssociated($values, $options); } else { $model->{$association}->create(null); $validates = $model->{$association}->set($values) && $model->{$association}->validates($options); $data[$association] = $model->{$association}->data[$model->{$association}->alias]; } if (is_array($validates)) { $validates = !in_array(false, Hash::flatten($validates), true); } $return[$association] = $validates; } elseif ($associations[$association] === 'hasMany') { $validates = $model->{$association}->validateMany($values, $options); $return[$association] = $validates; } if (!$validates || (is_array($validates) && in_array(false, $validates, true))) { $validationErrors[$association] = $model->{$association}->validationErrors; } } } $model->validationErrors = $validationErrors; if (isset($validationErrors[$model->alias])) { $model->validationErrors = $validationErrors[$model->alias]; unset($validationErrors[$model->alias]); $model->validationErrors = array_merge($model->validationErrors, $validationErrors); } if (!$options['atomic']) { return $return; } if ($return[$model->alias] === false || !empty($model->validationErrors)) { return false; } return true; } /** * Validates multiple individual records for a single model * * #### Options * * - 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. * * Warning: This method could potentially change the passed argument `$data`, * If you do not want this to happen, make a copy of `$data` before passing it * to this method * * @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(). * @return mixed If atomic: True on success, or false on failure. * Otherwise: array similar to the $data array passed, but values are set to true/false * depending on whether each record validated successfully. */ public function validateMany(&$data, $options = array()) { $model = $this->getModel(); $options += array('atomic' => true, 'deep' => false); $model->validationErrors = $validationErrors = $return = array(); foreach ($data as $key => &$record) { if ($options['deep']) { $validates = $model->validateAssociated($record, $options); } else { $model->create(null); $validates = $model->set($record) && $model->validates($options); $data[$key] = $model->data; } if ($validates === false || (is_array($validates) && in_array(false, Hash::flatten($validates), true))) { $validationErrors[$key] = $model->validationErrors; $validates = false; } else { $validates = true; } $return[$key] = $validates; } $model->validationErrors = $validationErrors; if (!$options['atomic']) { return $return; } return empty($model->validationErrors); } /** * Returns an array of fields that have failed validation. On the current model. This method will * actually run validation rules over data, not just return the messages. * * @param string $options An optional array of custom options to be made available in the beforeValidate callback * @return array Array of invalid fields * @triggers Model.afterValidate $model * @see ModelValidator::validates() */ public function errors($options = array()) { if (!$this->_triggerBeforeValidate($options)) { return false; } $model = $this->getModel(); if (!$this->_parseRules()) { return $model->validationErrors; } $fieldList = $model->whitelist; if (empty($fieldList) && !empty($options['fieldList'])) { if (!empty($options['fieldList'][$model->alias]) && is_array($options['fieldList'][$model->alias])) { $fieldList = $options['fieldList'][$model->alias]; } else { $fieldList = $options['fieldList']; } } $exists = $model->exists(); $methods = $this->getMethods(); $fields = $this->_validationList($fieldList); foreach ($fields as $field) { $field->setMethods($methods); $field->setValidationDomain($model->validationDomain); $data = isset($model->data[$model->alias]) ? $model->data[$model->alias] : array(); $errors = $field->validate($data, $exists); foreach ($errors as $error) { $this->invalidate($field->field, $error); } } $model->getEventManager()->dispatch(new CakeEvent('Model.afterValidate', $model)); return $model->validationErrors; } /** * Marks a field as invalid, optionally setting a message explaining * why the rule failed * * @param string $field The name of the field to invalidate * @param string $message Validation message explaining why the rule failed, defaults to true. * @return void */ public function invalidate($field, $message = true) { $this->getModel()->validationErrors[$field][] = $message; } /** * Gets all possible custom methods from the Model and attached Behaviors * to be used as validators * * @return array List of callables to be used as validation methods */ public function getMethods() { $behaviors = $this->_model->Behaviors->enabled(); if (!empty($this->_methods) && $behaviors === $this->_behaviors) { return $this->_methods; } $this->_behaviors = $behaviors; if (empty($this->_modelMethods)) { foreach (get_class_methods($this->_model) as $method) { $this->_modelMethods[strtolower($method)] = array($this->_model, $method); } } $methods = $this->_modelMethods; foreach (array_keys($this->_model->Behaviors->methods()) as $method) { $methods += array(strtolower($method) => array($this->_model, $method)); } return $this->_methods = $methods; } /** * Returns a CakeValidationSet object containing all validation rules for a field, if no * params are passed then it returns an array with all CakeValidationSet objects for each field * * @param string $name [optional] The fieldname to fetch. Defaults to null. * @return CakeValidationSet|array|null */ public function getField($name = null) { $this->_parseRules(); if ($name !== null) { if (!empty($this->_fields[$name])) { return $this->_fields[$name]; } return null; } return $this->_fields; } /** * Sets the CakeValidationSet objects from the `Model::$validate` property * If `Model::$validate` is not set or empty, this method returns false. True otherwise. * * @return bool true if `Model::$validate` was processed, false otherwise */ protected function _parseRules() { if ($this->_validate === $this->_model->validate) { return true; } if (empty($this->_model->validate)) { $this->_validate = array(); $this->_fields = array(); return false; } $this->_validate = $this->_model->validate; $this->_fields = array(); $methods = $this->getMethods(); foreach ($this->_validate as $fieldName => $ruleSet) { $this->_fields[$fieldName] = new CakeValidationSet($fieldName, $ruleSet); $this->_fields[$fieldName]->setMethods($methods); } return true; } /** * Sets the I18n domain for validation messages. This method is chainable. * * @param string $validationDomain [optional] The validation domain to be used. * @return self */ public function setValidationDomain($validationDomain = null) { if (empty($validationDomain)) { $validationDomain = 'default'; } $this->getModel()->validationDomain = $validationDomain; return $this; } /** * Gets the model related to this validator * * @return Model */ public function getModel() { return $this->_model; } /** * Processes the passed fieldList and returns the list of fields to be validated * * @param array $fieldList list of fields to be used for validation * @return CakeValidationSet[] List of validation rules to be applied */ protected function _validationList($fieldList = array()) { if (empty($fieldList) || Hash::dimensions($fieldList) > 1) { return $this->_fields; } $validateList = array(); $this->validationErrors = array(); foreach ((array)$fieldList as $f) { if (!empty($this->_fields[$f])) { $validateList[$f] = $this->_fields[$f]; } } return $validateList; } /** * Runs validation for hasAndBelongsToMany associations that have 'with' keys * set and data in the data set. * * @param array $options Array of options to use on Validation of with models * @return bool Failure of validation on with models. * @see Model::validates() */ protected function _validateWithModels($options) { $valid = true; $model = $this->getModel(); foreach ($model->hasAndBelongsToMany as $assoc => $association) { if (empty($association['with']) || !isset($model->data[$assoc])) { continue; } list($join) = $model->joinModel($model->hasAndBelongsToMany[$assoc]['with']); $data = $model->data[$assoc]; $newData = array(); foreach ((array)$data as $row) { if (isset($row[$model->hasAndBelongsToMany[$assoc]['associationForeignKey']])) { $newData[] = $row; } elseif (isset($row[$join]) && isset($row[$join][$model->hasAndBelongsToMany[$assoc]['associationForeignKey']])) { $newData[] = $row[$join]; } } foreach ($newData as $data) { $data[$model->hasAndBelongsToMany[$assoc]['foreignKey']] = $model->id; $model->{$join}->create($data); $valid = ($valid && $model->{$join}->validator()->validates($options)); } } return $valid; } /** * Propagates beforeValidate event * * @param array $options Options to pass to callback. * @return bool * @triggers Model.beforeValidate $model, array($options) */ protected function _triggerBeforeValidate($options = array()) { $model = $this->getModel(); $event = new CakeEvent('Model.beforeValidate', $model, array($options)); list($event->break, $event->breakOn) = array(true, false); $model->getEventManager()->dispatch($event); if ($event->isStopped()) { return false; } return true; } /** * Returns whether a rule set is defined for a field or not * * @param string $field name of the field to check * @return bool */ public function offsetExists($field) { $this->_parseRules(); return isset($this->_fields[$field]); } /** * Returns the rule set for a field * * @param string $field name of the field to check * @return CakeValidationSet */ public function offsetGet($field) { $this->_parseRules(); return $this->_fields[$field]; } /** * Sets the rule set for a field * * @param string $field name of the field to set * @param array|CakeValidationSet $rules set of rules to apply to field * @return void */ public function offsetSet($field, $rules) { $this->_parseRules(); if (!$rules instanceof CakeValidationSet) { $rules = new CakeValidationSet($field, $rules); $methods = $this->getMethods(); $rules->setMethods($methods); } $this->_fields[$field] = $rules; } /** * Unsets the rule set for a field * * @param string $field name of the field to unset * @return void */ public function offsetUnset($field) { $this->_parseRules(); unset($this->_fields[$field]); } /** * Returns an iterator for each of the fields to be validated * * @return ArrayIterator */ public function getIterator() { $this->_parseRules(); return new ArrayIterator($this->_fields); } /** * Returns the number of fields having validation rules * * @return int */ public function count() { $this->_parseRules(); return count($this->_fields); } /** * Adds a new rule to a field's rule set. If second argument is an array or instance of * CakeValidationSet then rules list for the field will be replaced with second argument and * third argument will be ignored. * * ## Example: * * ``` * $validator * ->add('title', 'required', array('rule' => 'notBlank', 'required' => true)) * ->add('user_id', 'valid', array('rule' => 'numeric', 'message' => 'Invalid User')) * * $validator->add('password', array( * 'size' => array('rule' => array('lengthBetween', 8, 20)), * 'hasSpecialCharacter' => array('rule' => 'validateSpecialchar', 'message' => 'not valid') * )); * ``` * * @param string $field The name of the field where the rule is to be added * @param string|array|CakeValidationSet $name name of the rule to be added or list of rules for the field * @param array|CakeValidationRule $rule or list of rules to be added to the field's rule set * @return self */ public function add($field, $name, $rule = null) { $this->_parseRules(); if ($name instanceof CakeValidationSet) { $this->_fields[$field] = $name; return $this; } if (!isset($this->_fields[$field])) { $rule = (is_string($name)) ? array($name => $rule) : $name; $this->_fields[$field] = new CakeValidationSet($field, $rule); } else { if (is_string($name)) { $this->_fields[$field]->setRule($name, $rule); } else { $this->_fields[$field]->setRules($name); } } $methods = $this->getMethods(); $this->_fields[$field]->setMethods($methods); return $this; } /** * Removes a rule from the set by its name * * ## Example: * * ``` * $validator * ->remove('title', 'required') * ->remove('user_id') * ``` * * @param string $field The name of the field from which the rule will be removed * @param string $rule the name of the rule to be removed * @return self */ public function remove($field, $rule = null) { $this->_parseRules(); if ($rule === null) { unset($this->_fields[$field]); } else { $this->_fields[$field]->removeRule($rule); } return $this; } } cakephp-2.8.0/lib/Cake/Model/Permission.php000066400000000000000000000147031265552240500204610ustar00rootroot00000000000000useDbConfig = $config; } parent::__construct(); } /** * Checks if the given $aro has access to action $action in $aco * * @param string $aro ARO The requesting object identifier. * @param string $aco ACO The controlled object identifier. * @param string $action Action (defaults to *) * @return bool Success (true if ARO has access to action in ACO, false otherwise) */ public function check($aro, $aco, $action = '*') { if (!$aro || !$aco) { return false; } $permKeys = $this->getAcoKeys($this->schema()); $aroPath = $this->Aro->node($aro); $acoPath = $this->Aco->node($aco); if (!$aroPath) { $this->log(__d('cake_dev', "%s - Failed ARO node lookup in permissions check. Node references:\nAro: %s\nAco: %s", 'DbAcl::check()', print_r($aro, true), print_r($aco, true)), E_USER_WARNING ); return false; } if (!$acoPath) { $this->log(__d('cake_dev', "%s - Failed ACO node lookup in permissions check. Node references:\nAro: %s\nAco: %s", 'DbAcl::check()', print_r($aro, true), print_r($aco, true)), E_USER_WARNING ); return false; } if ($action !== '*' && !in_array('_' . $action, $permKeys)) { $this->log(__d('cake_dev', "ACO permissions key %s does not exist in %s", $action, 'DbAcl::check()'), E_USER_NOTICE); return false; } $inherited = array(); $acoIDs = Hash::extract($acoPath, '{n}.' . $this->Aco->alias . '.id'); $count = count($aroPath); for ($i = 0; $i < $count; $i++) { $permAlias = $this->alias; $perms = $this->find('all', array( 'conditions' => array( "{$permAlias}.aro_id" => $aroPath[$i][$this->Aro->alias]['id'], "{$permAlias}.aco_id" => $acoIDs ), 'order' => array($this->Aco->alias . '.lft' => 'desc'), 'recursive' => 0 )); if (empty($perms)) { continue; } $perms = Hash::extract($perms, '{n}.' . $this->alias); foreach ($perms as $perm) { if ($action === '*') { foreach ($permKeys as $key) { if (!empty($perm)) { if ($perm[$key] == -1) { return false; } elseif ($perm[$key] == 1) { $inherited[$key] = 1; } } } if (count($inherited) === count($permKeys)) { return true; } } else { switch ($perm['_' . $action]) { case -1: return false; case 0: continue; case 1: return true; } } } } return false; } /** * Allow $aro to have access to action $actions in $aco * * @param string $aro ARO The requesting object identifier. * @param string $aco ACO The controlled object identifier. * @param string $actions Action (defaults to *) Invalid permissions will result in an exception * @param int $value Value to indicate access type (1 to give access, -1 to deny, 0 to inherit) * @return bool Success * @throws AclException on Invalid permission key. */ public function allow($aro, $aco, $actions = '*', $value = 1) { $perms = $this->getAclLink($aro, $aco); $permKeys = $this->getAcoKeys($this->schema()); $save = array(); if (!$perms) { $this->log(__d('cake_dev', '%s - Invalid node', 'DbAcl::allow()'), E_USER_WARNING); return false; } if (isset($perms[0])) { $save = $perms[0][$this->alias]; } if ($actions === '*') { $save = array_combine($permKeys, array_pad(array(), count($permKeys), $value)); } else { if (!is_array($actions)) { $actions = array('_' . $actions); } foreach ($actions as $action) { if ($action{0} !== '_') { $action = '_' . $action; } if (!in_array($action, $permKeys, true)) { throw new AclException(__d('cake_dev', 'Invalid permission key "%s"', $action)); } $save[$action] = $value; } } list($save['aro_id'], $save['aco_id']) = array($perms['aro'], $perms['aco']); if ($perms['link'] && !empty($perms['link'])) { $save['id'] = $perms['link'][0][$this->alias]['id']; } else { unset($save['id']); $this->id = null; } return ($this->save($save) !== false); } /** * Get an array of access-control links between the given Aro and Aco * * @param string $aro ARO The requesting object identifier. * @param string $aco ACO The controlled object identifier. * @return array Indexed array with: 'aro', 'aco' and 'link' */ public function getAclLink($aro, $aco) { $obj = array(); $obj['Aro'] = $this->Aro->node($aro); $obj['Aco'] = $this->Aco->node($aco); if (empty($obj['Aro']) || empty($obj['Aco'])) { return false; } $aro = Hash::extract($obj, 'Aro.0.' . $this->Aro->alias . '.id'); $aco = Hash::extract($obj, 'Aco.0.' . $this->Aco->alias . '.id'); $aro = current($aro); $aco = current($aco); return array( 'aro' => $aro, 'aco' => $aco, 'link' => $this->find('all', array('conditions' => array( $this->alias . '.aro_id' => $aro, $this->alias . '.aco_id' => $aco ))) ); } /** * Get the crud type keys * * @param array $keys Permission schema * @return array permission keys */ public function getAcoKeys($keys) { $newKeys = array(); $keys = array_keys($keys); foreach ($keys as $key) { if (!in_array($key, array('id', 'aro_id', 'aco_id'))) { $newKeys[] = $key; } } return $newKeys; } } cakephp-2.8.0/lib/Cake/Model/Validator/000077500000000000000000000000001265552240500175405ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Model/Validator/CakeValidationRule.php000066400000000000000000000173671265552240500237750ustar00rootroot00000000000000_addValidatorProps($validator); } /** * Checks if the rule is valid * * @return bool */ public function isValid() { if (!$this->_valid || (is_string($this->_valid) && !empty($this->_valid))) { return false; } return true; } /** * Returns whether the field can be left blank according to this rule * * @return bool */ public function isEmptyAllowed() { return $this->skip() || $this->allowEmpty === true; } /** * Checks if the field is required according to the `required` property * * @return bool */ public function isRequired() { if (in_array($this->required, array('create', 'update'), true)) { if ($this->required === 'create' && !$this->isUpdate() || $this->required === 'update' && $this->isUpdate()) { return true; } return false; } return $this->required; } /** * Checks whether the field failed the `field should be present` validation * * @param string $field Field name * @param array &$data Data to check rule against * @return bool */ public function checkRequired($field, &$data) { return ( (!array_key_exists($field, $data) && $this->isRequired() === true) || ( array_key_exists($field, $data) && (empty($data[$field]) && !is_numeric($data[$field])) && $this->allowEmpty === false ) ); } /** * Checks if the allowEmpty key applies * * @param string $field Field name * @param array &$data data to check rule against * @return bool */ public function checkEmpty($field, &$data) { if (empty($data[$field]) && $data[$field] != '0' && $this->allowEmpty === true) { return true; } return false; } /** * Checks if the validation rule should be skipped * * @return bool True if the ValidationRule can be skipped */ public function skip() { if (!empty($this->on)) { if ($this->on === 'create' && $this->isUpdate() || $this->on === 'update' && !$this->isUpdate()) { return true; } } return false; } /** * Returns whether this rule should break validation process for associated field * after it fails * * @return bool */ public function isLast() { return (bool)$this->last; } /** * Gets the validation error message * * @return string */ public function getValidationResult() { return $this->_valid; } /** * Gets an array with the rule properties * * @return array */ protected function _getPropertiesArray() { $rule = $this->rule; if (!is_string($rule)) { unset($rule[0]); } return array( 'rule' => $rule, 'required' => $this->required, 'allowEmpty' => $this->allowEmpty, 'on' => $this->on, 'last' => $this->last, 'message' => $this->message ); } /** * Sets the recordExists configuration value for this rule, * ir refers to whether the model record it is validating exists * exists in the collection or not (create or update operation) * * If called with no parameters it will return whether this rule * is configured for update operations or not. * * @param bool $exists Boolean to indicate if records exists * @return bool */ public function isUpdate($exists = null) { if ($exists === null) { return $this->_recordExists; } return $this->_recordExists = $exists; } /** * Dispatches the validation rule to the given validator method * * @param string $field Field name * @param array &$data Data array * @param array &$methods Methods list * @return bool True if the rule could be dispatched, false otherwise */ public function process($field, &$data, &$methods) { $this->_valid = true; $this->_parseRule($field, $data); $validator = $this->_getPropertiesArray(); $rule = strtolower($this->_rule); if (isset($methods[$rule])) { $this->_ruleParams[] = array_merge($validator, $this->_passedOptions); $this->_ruleParams[0] = array($field => $this->_ruleParams[0]); $this->_valid = call_user_func_array($methods[$rule], $this->_ruleParams); } elseif (class_exists('Validation') && method_exists('Validation', $this->_rule)) { $this->_valid = call_user_func_array(array('Validation', $this->_rule), $this->_ruleParams); } elseif (is_string($validator['rule'])) { $this->_valid = preg_match($this->_rule, $data[$field]); } else { trigger_error(__d('cake_dev', 'Could not find validation handler %s for %s', $this->_rule, $field), E_USER_WARNING); return false; } return true; } /** * Resets internal state for this rule, by default it will become valid * and it will set isUpdate() to false * * @return void */ public function reset() { $this->_valid = true; $this->_recordExists = false; } /** * Returns passed options for this rule * * @param string|int $key Array index * @return array|null */ public function getOptions($key) { if (!isset($this->_passedOptions[$key])) { return null; } return $this->_passedOptions[$key]; } /** * Sets the rule properties from the rule entry in validate * * @param array $validator [optional] * @return void */ protected function _addValidatorProps($validator = array()) { if (!is_array($validator)) { $validator = array('rule' => $validator); } foreach ($validator as $key => $value) { if (isset($value) || !empty($value)) { if (in_array($key, array('rule', 'required', 'allowEmpty', 'on', 'message', 'last'))) { $this->{$key} = $validator[$key]; } else { $this->_passedOptions[$key] = $value; } } } } /** * Parses the rule and sets the rule and ruleParams * * @param string $field Field name * @param array &$data Data array * @return void */ protected function _parseRule($field, &$data) { if (is_array($this->rule)) { $this->_rule = $this->rule[0]; $this->_ruleParams = array_merge(array($data[$field]), array_values(array_slice($this->rule, 1))); } else { $this->_rule = $this->rule; $this->_ruleParams = array($data[$field]); } } } cakephp-2.8.0/lib/Cake/Model/Validator/CakeValidationSet.php000066400000000000000000000202711265552240500236050ustar00rootroot00000000000000field = $fieldName; if (!is_array($ruleSet) || (is_array($ruleSet) && isset($ruleSet['rule']))) { $ruleSet = array($ruleSet); } foreach ($ruleSet as $index => $validateProp) { $this->_rules[$index] = new CakeValidationRule($validateProp); } $this->ruleSet = $ruleSet; } /** * Sets the list of methods to use for validation * * @param array &$methods Methods list * @return void */ public function setMethods(&$methods) { $this->_methods =& $methods; } /** * Sets the I18n domain for validation messages. * * @param string $validationDomain The validation domain to be used. * @return void */ public function setValidationDomain($validationDomain) { $this->_validationDomain = $validationDomain; } /** * Runs all validation rules in this set and returns a list of * validation errors * * @param array $data Data array * @param bool $isUpdate Is record being updated or created * @return array list of validation errors for this field */ public function validate($data, $isUpdate = false) { $this->reset(); $errors = array(); foreach ($this->getRules() as $name => $rule) { $rule->isUpdate($isUpdate); if ($rule->skip()) { continue; } $checkRequired = $rule->checkRequired($this->field, $data); if (!$checkRequired && array_key_exists($this->field, $data)) { if ($rule->checkEmpty($this->field, $data)) { break; } $rule->process($this->field, $data, $this->_methods); } if ($checkRequired || !$rule->isValid()) { $errors[] = $this->_processValidationResponse($name, $rule); if ($rule->isLast()) { break; } } } return $errors; } /** * Resets internal state for all validation rules in this set * * @return void */ public function reset() { foreach ($this->getRules() as $rule) { $rule->reset(); } } /** * Gets a rule for a given name if exists * * @param string $name Field name. * @return CakeValidationRule */ public function getRule($name) { if (!empty($this->_rules[$name])) { return $this->_rules[$name]; } } /** * Returns all rules for this validation set * * @return CakeValidationRule[] */ public function getRules() { return $this->_rules; } /** * Sets a CakeValidationRule $rule with a $name * * ## Example: * * ``` * $set * ->setRule('required', array('rule' => 'notBlank', 'required' => true)) * ->setRule('between', array('rule' => array('lengthBetween', 4, 10)) * ``` * * @param string $name The name under which the rule should be set * @param CakeValidationRule|array $rule The validation rule to be set * @return self */ public function setRule($name, $rule) { if (!($rule instanceof CakeValidationRule)) { $rule = new CakeValidationRule($rule); } $this->_rules[$name] = $rule; return $this; } /** * Removes a validation rule from the set * * ## Example: * * ``` * $set * ->removeRule('required') * ->removeRule('inRange') * ``` * * @param string $name The name under which the rule should be unset * @return self */ public function removeRule($name) { unset($this->_rules[$name]); return $this; } /** * Sets the rules for a given field * * ## Example: * * ``` * $set->setRules(array( * 'required' => array('rule' => 'notBlank', 'required' => true), * 'inRange' => array('rule' => array('between', 4, 10) * )); * ``` * * @param array $rules The rules to be set * @param bool $mergeVars [optional] If true, merges vars instead of replace. Defaults to true. * @return self */ public function setRules($rules = array(), $mergeVars = true) { if ($mergeVars === false) { $this->_rules = array(); } foreach ($rules as $name => $rule) { $this->setRule($name, $rule); } return $this; } /** * Fetches the correct error message for a failed validation * * @param string $name the name of the rule as it was configured * @param CakeValidationRule $rule the object containing validation information * @return string */ protected function _processValidationResponse($name, $rule) { $message = $rule->getValidationResult(); if (is_string($message)) { return $message; } $message = $rule->message; if ($message !== null) { $args = null; if (is_array($message)) { $result = $message[0]; $args = array_slice($message, 1); } else { $result = $message; } if (is_array($rule->rule) && $args === null) { $args = array_slice($rule->rule, 1); } $args = $this->_translateArgs($args); $message = __d($this->_validationDomain, $result, $args); } elseif (is_string($name)) { if (is_array($rule->rule)) { $args = array_slice($rule->rule, 1); $args = $this->_translateArgs($args); $message = __d($this->_validationDomain, $name, $args); } else { $message = __d($this->_validationDomain, $name); } } else { $message = __d('cake', 'This field cannot be left blank'); } return $message; } /** * Applies translations to validator arguments. * * @param array $args The args to translate * @return array Translated args. */ protected function _translateArgs($args) { foreach ((array)$args as $k => $arg) { if (is_string($arg)) { $args[$k] = __d($this->_validationDomain, $arg); } } return $args; } /** * Returns whether an index exists in the rule set * * @param string $index name of the rule * @return bool */ public function offsetExists($index) { return isset($this->_rules[$index]); } /** * Returns a rule object by its index * * @param string $index name of the rule * @return CakeValidationRule */ public function offsetGet($index) { return $this->_rules[$index]; } /** * Sets or replace a validation rule. * * This is a wrapper for ArrayAccess. Use setRule() directly for * chainable access. * * @param string $index Name of the rule. * @param CakeValidationRule|array $rule Rule to add to $index. * @return void * @see http://www.php.net/manual/en/arrayobject.offsetset.php */ public function offsetSet($index, $rule) { $this->setRule($index, $rule); } /** * Unsets a validation rule * * @param string $index name of the rule * @return void */ public function offsetUnset($index) { unset($this->_rules[$index]); } /** * Returns an iterator for each of the rules to be applied * * @return ArrayIterator */ public function getIterator() { return new ArrayIterator($this->_rules); } /** * Returns the number of rules in this set * * @return int */ public function count() { return count($this->_rules); } } cakephp-2.8.0/lib/Cake/Network/000077500000000000000000000000001265552240500162045ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Network/CakeRequest.php000066400000000000000000001000061265552240500211260ustar00rootroot00000000000000controller`. * * @package Cake.Network */ class CakeRequest implements ArrayAccess { /** * Array of parameters parsed from the URL. * * @var array */ public $params = array( 'plugin' => null, 'controller' => null, 'action' => null, 'named' => array(), 'pass' => array(), ); /** * Array of POST data. Will contain form data as well as uploaded files. * Inputs prefixed with 'data' will have the data prefix removed. If there is * overlap between an input prefixed with data and one without, the 'data' prefixed * value will take precedence. * * @var array */ public $data = array(); /** * Array of querystring arguments * * @var array */ public $query = array(); /** * The URL string used for the request. * * @var string */ public $url; /** * Base URL path. * * @var string */ public $base = false; /** * webroot path segment for the request. * * @var string */ public $webroot = '/'; /** * The full address to the current request * * @var string */ public $here = null; /** * The built in detectors used with `is()` can be modified with `addDetector()`. * * There are several ways to specify a detector, see CakeRequest::addDetector() for the * various formats and ways to define detectors. * * @var array */ protected $_detectors = array( 'get' => array('env' => 'REQUEST_METHOD', 'value' => 'GET'), 'post' => array('env' => 'REQUEST_METHOD', 'value' => 'POST'), 'put' => array('env' => 'REQUEST_METHOD', 'value' => 'PUT'), 'delete' => array('env' => 'REQUEST_METHOD', 'value' => 'DELETE'), 'head' => array('env' => 'REQUEST_METHOD', 'value' => 'HEAD'), 'options' => array('env' => 'REQUEST_METHOD', 'value' => 'OPTIONS'), 'ssl' => array('env' => 'HTTPS', 'value' => 1), 'ajax' => array('env' => 'HTTP_X_REQUESTED_WITH', 'value' => 'XMLHttpRequest'), 'flash' => array('env' => 'HTTP_USER_AGENT', 'pattern' => '/^(Shockwave|Adobe) Flash/'), 'mobile' => array('env' => 'HTTP_USER_AGENT', 'options' => array( 'Android', 'AvantGo', 'BB10', 'BlackBerry', 'DoCoMo', 'Fennec', 'iPod', 'iPhone', 'iPad', 'J2ME', 'MIDP', 'NetFront', 'Nokia', 'Opera Mini', 'Opera Mobi', 'PalmOS', 'PalmSource', 'portalmmm', 'Plucker', 'ReqwirelessWeb', 'SonyEricsson', 'Symbian', 'UP\\.Browser', 'webOS', 'Windows CE', 'Windows Phone OS', 'Xiino' )), 'requested' => array('param' => 'requested', 'value' => 1), 'json' => array('accept' => array('application/json'), 'param' => 'ext', 'value' => 'json'), 'xml' => array('accept' => array('application/xml', 'text/xml'), 'param' => 'ext', 'value' => 'xml'), ); /** * Copy of php://input. Since this stream can only be read once in most SAPI's * keep a copy of it so users don't need to know about that detail. * * @var string */ protected $_input = ''; /** * Constructor * * @param string $url Trimmed URL string to use. Should not contain the application base path. * @param bool $parseEnvironment Set to false to not auto parse the environment. ie. GET, POST and FILES. */ public function __construct($url = null, $parseEnvironment = true) { $this->_base(); if (empty($url)) { $url = $this->_url(); } if ($url[0] === '/') { $url = substr($url, 1); } $this->url = $url; if ($parseEnvironment) { $this->_processPost(); $this->_processGet(); $this->_processFiles(); } $this->here = $this->base . '/' . $this->url; } /** * process the post data and set what is there into the object. * processed data is available at `$this->data` * * Will merge POST vars prefixed with `data`, and ones without * into a single array. Variables prefixed with `data` will overwrite those without. * * If you have mixed POST values be careful not to make any top level keys numeric * containing arrays. Hash::merge() is used to merge data, and it has possibly * unexpected behavior in this situation. * * @return void */ protected function _processPost() { if ($_POST) { $this->data = $_POST; } elseif (($this->is('put') || $this->is('delete')) && strpos(env('CONTENT_TYPE'), 'application/x-www-form-urlencoded') === 0 ) { $data = $this->_readInput(); parse_str($data, $this->data); } if (ini_get('magic_quotes_gpc') === '1') { $this->data = stripslashes_deep($this->data); } $override = null; if (env('HTTP_X_HTTP_METHOD_OVERRIDE')) { $this->data['_method'] = env('HTTP_X_HTTP_METHOD_OVERRIDE'); $override = $this->data['_method']; } $isArray = is_array($this->data); if ($isArray && isset($this->data['_method'])) { if (!empty($_SERVER)) { $_SERVER['REQUEST_METHOD'] = $this->data['_method']; } else { $_ENV['REQUEST_METHOD'] = $this->data['_method']; } $override = $this->data['_method']; unset($this->data['_method']); } if ($override && !in_array($override, array('POST', 'PUT', 'PATCH', 'DELETE'))) { $this->data = array(); } if ($isArray && isset($this->data['data'])) { $data = $this->data['data']; if (count($this->data) <= 1) { $this->data = $data; } else { unset($this->data['data']); $this->data = Hash::merge($this->data, $data); } } } /** * Process the GET parameters and move things into the object. * * @return void */ protected function _processGet() { if (ini_get('magic_quotes_gpc') === '1') { $query = stripslashes_deep($_GET); } else { $query = $_GET; } $unsetUrl = '/' . str_replace(array('.', ' '), '_', urldecode($this->url)); unset($query[$unsetUrl]); unset($query[$this->base . $unsetUrl]); if (strpos($this->url, '?') !== false) { list(, $querystr) = explode('?', $this->url); parse_str($querystr, $queryArgs); $query += $queryArgs; } if (isset($this->params['url'])) { $query = array_merge($this->params['url'], $query); } $this->query = $query; } /** * Get the request uri. Looks in PATH_INFO first, as this is the exact value we need prepared * by PHP. Following that, REQUEST_URI, PHP_SELF, HTTP_X_REWRITE_URL and argv are checked in that order. * Each of these server variables have the base path, and query strings stripped off * * @return string URI The CakePHP request path that is being accessed. */ protected function _url() { if (!empty($_SERVER['PATH_INFO'])) { return $_SERVER['PATH_INFO']; } elseif (isset($_SERVER['REQUEST_URI']) && strpos($_SERVER['REQUEST_URI'], '://') === false) { $uri = $_SERVER['REQUEST_URI']; } elseif (isset($_SERVER['REQUEST_URI'])) { $qPosition = strpos($_SERVER['REQUEST_URI'], '?'); if ($qPosition !== false && strpos($_SERVER['REQUEST_URI'], '://') > $qPosition) { $uri = $_SERVER['REQUEST_URI']; } else { $uri = substr($_SERVER['REQUEST_URI'], strlen(Configure::read('App.fullBaseUrl'))); } } elseif (isset($_SERVER['PHP_SELF']) && isset($_SERVER['SCRIPT_NAME'])) { $uri = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['PHP_SELF']); } elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) { $uri = $_SERVER['HTTP_X_REWRITE_URL']; } elseif ($var = env('argv')) { $uri = $var[0]; } $base = $this->base; if (strlen($base) > 0 && strpos($uri, $base) === 0) { $uri = substr($uri, strlen($base)); } if (strpos($uri, '?') !== false) { list($uri) = explode('?', $uri, 2); } if (empty($uri) || $uri === '/' || $uri === '//' || $uri === '/index.php') { $uri = '/'; } $endsWithIndex = '/webroot/index.php'; $endsWithLength = strlen($endsWithIndex); if (strlen($uri) >= $endsWithLength && substr($uri, -$endsWithLength) === $endsWithIndex ) { $uri = '/'; } return $uri; } /** * Returns a base URL and sets the proper webroot * * If CakePHP is called with index.php in the URL even though * URL Rewriting is activated (and thus not needed) it swallows * the unnecessary part from $base to prevent issue #3318. * * @return string Base URL * @link https://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/3318 */ protected function _base() { $dir = $webroot = null; $config = Configure::read('App'); extract($config); if (!isset($base)) { $base = $this->base; } if ($base !== false) { $this->webroot = $base . '/'; return $this->base = $base; } if (!$baseUrl) { $base = dirname(env('PHP_SELF')); // Clean up additional / which cause following code to fail.. $base = preg_replace('#/+#', '/', $base); $indexPos = strpos($base, '/webroot/index.php'); if ($indexPos !== false) { $base = substr($base, 0, $indexPos) . '/webroot'; } if ($webroot === 'webroot' && $webroot === basename($base)) { $base = dirname($base); } if ($dir === 'app' && $dir === basename($base)) { $base = dirname($base); } if ($base === DS || $base === '.') { $base = ''; } $base = implode('/', array_map('rawurlencode', explode('/', $base))); $this->webroot = $base . '/'; return $this->base = $base; } $file = '/' . basename($baseUrl); $base = dirname($baseUrl); if ($base === DS || $base === '.') { $base = ''; } $this->webroot = $base . '/'; $docRoot = env('DOCUMENT_ROOT'); $docRootContainsWebroot = strpos($docRoot, $dir . DS . $webroot); if (!empty($base) || !$docRootContainsWebroot) { if (strpos($this->webroot, '/' . $dir . '/') === false) { $this->webroot .= $dir . '/'; } if (strpos($this->webroot, '/' . $webroot . '/') === false) { $this->webroot .= $webroot . '/'; } } return $this->base = $base . $file; } /** * Process $_FILES and move things into the object. * * @return void */ protected function _processFiles() { if (isset($_FILES) && is_array($_FILES)) { foreach ($_FILES as $name => $data) { if ($name !== 'data') { $this->params['form'][$name] = $data; } } } if (isset($_FILES['data'])) { foreach ($_FILES['data'] as $key => $data) { $this->_processFileData('', $data, $key); } } } /** * Recursively walks the FILES array restructuring the data * into something sane and useable. * * @param string $path The dot separated path to insert $data into. * @param array $data The data to traverse/insert. * @param string $field The terminal field name, which is the top level key in $_FILES. * @return void */ protected function _processFileData($path, $data, $field) { foreach ($data as $key => $fields) { $newPath = $key; if (strlen($path) > 0) { $newPath = $path . '.' . $key; } if (is_array($fields)) { $this->_processFileData($newPath, $fields, $field); } else { $newPath .= '.' . $field; $this->data = Hash::insert($this->data, $newPath, $fields); } } } /** * Get the IP the client is using, or says they are using. * * @param bool $safe Use safe = false when you think the user might manipulate their HTTP_CLIENT_IP * header. Setting $safe = false will also look at HTTP_X_FORWARDED_FOR * @return string The client IP. */ public function clientIp($safe = true) { if (!$safe && env('HTTP_X_FORWARDED_FOR')) { $ipaddr = preg_replace('/(?:,.*)/', '', env('HTTP_X_FORWARDED_FOR')); } else { if (env('HTTP_CLIENT_IP')) { $ipaddr = env('HTTP_CLIENT_IP'); } else { $ipaddr = env('REMOTE_ADDR'); } } if (env('HTTP_CLIENTADDRESS')) { $tmpipaddr = env('HTTP_CLIENTADDRESS'); if (!empty($tmpipaddr)) { $ipaddr = preg_replace('/(?:,.*)/', '', $tmpipaddr); } } return trim($ipaddr); } /** * Returns the referer that referred this request. * * @param bool $local Attempt to return a local address. Local addresses do not contain hostnames. * @return string The referring address for this request. */ public function referer($local = false) { $ref = env('HTTP_REFERER'); $base = Configure::read('App.fullBaseUrl') . $this->webroot; if (!empty($ref) && !empty($base)) { if ($local && strpos($ref, $base) === 0) { $ref = substr($ref, strlen($base)); if ($ref[0] !== '/') { $ref = '/' . $ref; } return $ref; } elseif (!$local) { return $ref; } } return '/'; } /** * Missing method handler, handles wrapping older style isAjax() type methods * * @param string $name The method called * @param array $params Array of parameters for the method call * @return mixed * @throws CakeException when an invalid method is called. */ public function __call($name, $params) { if (strpos($name, 'is') === 0) { $type = strtolower(substr($name, 2)); return $this->is($type); } throw new CakeException(__d('cake_dev', 'Method %s does not exist', $name)); } /** * Magic get method allows access to parsed routing parameters directly on the object. * * Allows access to `$this->params['controller']` via `$this->controller` * * @param string $name The property being accessed. * @return mixed Either the value of the parameter or null. */ public function __get($name) { if (isset($this->params[$name])) { return $this->params[$name]; } return null; } /** * Magic isset method allows isset/empty checks * on routing parameters. * * @param string $name The property being accessed. * @return bool Existence */ public function __isset($name) { return isset($this->params[$name]); } /** * Check whether or not a Request is a certain type. * * Uses the built in detection rules as well as additional rules * defined with CakeRequest::addDetector(). Any detector can be called * as `is($type)` or `is$Type()`. * * @param string|array $type The type of request you want to check. If an array * this method will return true if the request matches any type. * @return bool Whether or not the request is the type you are checking. */ public function is($type) { if (is_array($type)) { $result = array_map(array($this, 'is'), $type); return count(array_filter($result)) > 0; } $type = strtolower($type); if (!isset($this->_detectors[$type])) { return false; } $detect = $this->_detectors[$type]; if (isset($detect['env']) && $this->_environmentDetector($detect)) { return true; } if (isset($detect['header']) && $this->_headerDetector($detect)) { return true; } if (isset($detect['accept']) && $this->_acceptHeaderDetector($detect)) { return true; } if (isset($detect['param']) && $this->_paramDetector($detect)) { return true; } if (isset($detect['callback']) && is_callable($detect['callback'])) { return call_user_func($detect['callback'], $this); } return false; } /** * Detects if a URL extension is present. * * @param array $detect Detector options array. * @return bool Whether or not the request is the type you are checking. */ protected function _extensionDetector($detect) { if (is_string($detect['extension'])) { $detect['extension'] = array($detect['extension']); } if (in_array($this->params['ext'], $detect['extension'])) { return true; } return false; } /** * Detects if a specific accept header is present. * * @param array $detect Detector options array. * @return bool Whether or not the request is the type you are checking. */ protected function _acceptHeaderDetector($detect) { $acceptHeaders = explode(',', (string)env('HTTP_ACCEPT')); foreach ($detect['accept'] as $header) { if (in_array($header, $acceptHeaders)) { return true; } } return false; } /** * Detects if a specific header is present. * * @param array $detect Detector options array. * @return bool Whether or not the request is the type you are checking. */ protected function _headerDetector($detect) { foreach ($detect['header'] as $header => $value) { $header = env('HTTP_' . strtoupper($header)); if (!is_null($header)) { if (!is_string($value) && !is_bool($value) && is_callable($value)) { return call_user_func($value, $header); } return ($header === $value); } } return false; } /** * Detects if a specific request parameter is present. * * @param array $detect Detector options array. * @return bool Whether or not the request is the type you are checking. */ protected function _paramDetector($detect) { $key = $detect['param']; if (isset($detect['value'])) { $value = $detect['value']; return isset($this->params[$key]) ? $this->params[$key] == $value : false; } if (isset($detect['options'])) { return isset($this->params[$key]) ? in_array($this->params[$key], $detect['options']) : false; } return false; } /** * Detects if a specific environment variable is present. * * @param array $detect Detector options array. * @return bool Whether or not the request is the type you are checking. */ protected function _environmentDetector($detect) { if (isset($detect['env'])) { if (isset($detect['value'])) { return env($detect['env']) == $detect['value']; } if (isset($detect['pattern'])) { return (bool)preg_match($detect['pattern'], env($detect['env'])); } if (isset($detect['options'])) { $pattern = '/' . implode('|', $detect['options']) . '/i'; return (bool)preg_match($pattern, env($detect['env'])); } } return false; } /** * Check that a request matches all the given types. * * Allows you to test multiple types and union the results. * See CakeRequest::is() for how to add additional types and the * built-in types. * * @param array $types The types to check. * @return bool Success. * @see CakeRequest::is() */ public function isAll(array $types) { $result = array_filter(array_map(array($this, 'is'), $types)); return count($result) === count($types); } /** * Add a new detector to the list of detectors that a request can use. * There are several different formats and types of detectors that can be set. * * ### Environment value comparison * * An environment value comparison, compares a value fetched from `env()` to a known value * the environment value is equality checked against the provided value. * * e.g `addDetector('post', array('env' => 'REQUEST_METHOD', 'value' => 'POST'))` * * ### Pattern value comparison * * Pattern value comparison allows you to compare a value fetched from `env()` to a regular expression. * * e.g `addDetector('iphone', array('env' => 'HTTP_USER_AGENT', 'pattern' => '/iPhone/i'));` * * ### Option based comparison * * Option based comparisons use a list of options to create a regular expression. Subsequent calls * to add an already defined options detector will merge the options. * * e.g `addDetector('mobile', array('env' => 'HTTP_USER_AGENT', 'options' => array('Fennec')));` * * ### Callback detectors * * Callback detectors allow you to provide a 'callback' type to handle the check. The callback will * receive the request object as its only parameter. * * e.g `addDetector('custom', array('callback' => array('SomeClass', 'somemethod')));` * * ### Request parameter detectors * * Allows for custom detectors on the request parameters. * * e.g `addDetector('requested', array('param' => 'requested', 'value' => 1)` * * You can also make parameter detectors that accept multiple values * using the `options` key. This is useful when you want to check * if a request parameter is in a list of options. * * `addDetector('extension', array('param' => 'ext', 'options' => array('pdf', 'csv'))` * * @param string $name The name of the detector. * @param array $options The options for the detector definition. See above. * @return void */ public function addDetector($name, $options) { $name = strtolower($name); if (isset($this->_detectors[$name]) && isset($options['options'])) { $options = Hash::merge($this->_detectors[$name], $options); } $this->_detectors[$name] = $options; } /** * Add parameters to the request's parsed parameter set. This will overwrite any existing parameters. * This modifies the parameters available through `$request->params`. * * @param array $params Array of parameters to merge in * @return self */ public function addParams($params) { $this->params = array_merge($this->params, (array)$params); return $this; } /** * Add paths to the requests' paths vars. This will overwrite any existing paths. * Provides an easy way to modify, here, webroot and base. * * @param array $paths Array of paths to merge in * @return self */ public function addPaths($paths) { foreach (array('webroot', 'here', 'base') as $element) { if (isset($paths[$element])) { $this->{$element} = $paths[$element]; } } return $this; } /** * Get the value of the current requests URL. Will include named parameters and querystring arguments. * * @param bool $base Include the base path, set to false to trim the base path off. * @return string the current request URL including query string args. */ public function here($base = true) { $url = $this->here; if (!empty($this->query)) { $url .= '?' . http_build_query($this->query, null, '&'); } if (!$base) { $url = preg_replace('/^' . preg_quote($this->base, '/') . '/', '', $url, 1); } return $url; } /** * Read an HTTP header from the Request information. * * @param string $name Name of the header you want. * @return mixed Either false on no header being set or the value of the header. */ public static function header($name) { $name = 'HTTP_' . strtoupper(str_replace('-', '_', $name)); if (isset($_SERVER[$name])) { return $_SERVER[$name]; } return false; } /** * Get the HTTP method used for this request. * There are a few ways to specify a method. * * - If your client supports it you can use native HTTP methods. * - You can set the HTTP-X-Method-Override header. * - You can submit an input with the name `_method` * * Any of these 3 approaches can be used to set the HTTP method used * by CakePHP internally, and will effect the result of this method. * * @return string The name of the HTTP method used. */ public function method() { return env('REQUEST_METHOD'); } /** * Get the host that the request was handled on. * * @param bool $trustProxy Whether or not to trust the proxy host. * @return string */ public function host($trustProxy = false) { if ($trustProxy) { return env('HTTP_X_FORWARDED_HOST'); } return env('HTTP_HOST'); } /** * Get the domain name and include $tldLength segments of the tld. * * @param int $tldLength Number of segments your tld contains. For example: `example.com` contains 1 tld. * While `example.co.uk` contains 2. * @return string Domain name without subdomains. */ public function domain($tldLength = 1) { $segments = explode('.', $this->host()); $domain = array_slice($segments, -1 * ($tldLength + 1)); return implode('.', $domain); } /** * Get the subdomains for a host. * * @param int $tldLength Number of segments your tld contains. For example: `example.com` contains 1 tld. * While `example.co.uk` contains 2. * @return array An array of subdomains. */ public function subdomains($tldLength = 1) { $segments = explode('.', $this->host()); return array_slice($segments, 0, -1 * ($tldLength + 1)); } /** * Find out which content types the client accepts or check if they accept a * particular type of content. * * #### Get all types: * * `$this->request->accepts();` * * #### Check for a single type: * * `$this->request->accepts('application/json');` * * This method will order the returned content types by the preference values indicated * by the client. * * @param string $type The content type to check for. Leave null to get all types a client accepts. * @return mixed Either an array of all the types the client accepts or a boolean if they accept the * provided type. */ public function accepts($type = null) { $raw = $this->parseAccept(); $accept = array(); foreach ($raw as $types) { $accept = array_merge($accept, $types); } if ($type === null) { return $accept; } return in_array($type, $accept); } /** * Parse the HTTP_ACCEPT header and return a sorted array with content types * as the keys, and pref values as the values. * * Generally you want to use CakeRequest::accept() to get a simple list * of the accepted content types. * * @return array An array of prefValue => array(content/types) */ public function parseAccept() { return $this->_parseAcceptWithQualifier($this->header('accept')); } /** * Get the languages accepted by the client, or check if a specific language is accepted. * * Get the list of accepted languages: * * ``` CakeRequest::acceptLanguage(); ``` * * Check if a specific language is accepted: * * ``` CakeRequest::acceptLanguage('es-es'); ``` * * @param string $language The language to test. * @return mixed If a $language is provided, a boolean. Otherwise the array of accepted languages. */ public static function acceptLanguage($language = null) { $raw = static::_parseAcceptWithQualifier(static::header('Accept-Language')); $accept = array(); foreach ($raw as $languages) { foreach ($languages as &$lang) { if (strpos($lang, '_')) { $lang = str_replace('_', '-', $lang); } $lang = strtolower($lang); } $accept = array_merge($accept, $languages); } if ($language === null) { return $accept; } return in_array(strtolower($language), $accept); } /** * Parse Accept* headers with qualifier options. * * Only qualifiers will be extracted, any other accept extensions will be * discarded as they are not frequently used. * * @param string $header Header to parse. * @return array */ protected static function _parseAcceptWithQualifier($header) { $accept = array(); $header = explode(',', $header); foreach (array_filter($header) as $value) { $prefValue = '1.0'; $value = trim($value); $semiPos = strpos($value, ';'); if ($semiPos !== false) { $params = explode(';', $value); $value = trim($params[0]); foreach ($params as $param) { $qPos = strpos($param, 'q='); if ($qPos !== false) { $prefValue = substr($param, $qPos + 2); } } } if (!isset($accept[$prefValue])) { $accept[$prefValue] = array(); } if ($prefValue) { $accept[$prefValue][] = $value; } } krsort($accept); return $accept; } /** * Provides a read accessor for `$this->query`. Allows you * to use a syntax similar to `CakeSession` for reading URL query data. * * @param string $name Query string variable name * @return mixed The value being read */ public function query($name) { return Hash::get($this->query, $name); } /** * Provides a read/write accessor for `$this->data`. Allows you * to use a syntax similar to `CakeSession` for reading post data. * * ## Reading values. * * `$request->data('Post.title');` * * When reading values you will get `null` for keys/values that do not exist. * * ## Writing values * * `$request->data('Post.title', 'New post!');` * * You can write to any value, even paths/keys that do not exist, and the arrays * will be created for you. * * @param string $name Dot separated name of the value to read/write, one or more args. * @return mixed|self Either the value being read, or $this so you can chain consecutive writes. */ public function data($name) { $args = func_get_args(); if (count($args) === 2) { $this->data = Hash::insert($this->data, $name, $args[1]); return $this; } return Hash::get($this->data, $name); } /** * Safely access the values in $this->params. * * @param string $name The name of the parameter to get. * @return mixed The value of the provided parameter. Will * return false if the parameter doesn't exist or is falsey. */ public function param($name) { $args = func_get_args(); if (count($args) === 2) { $this->params = Hash::insert($this->params, $name, $args[1]); return $this; } if (!isset($this->params[$name])) { return Hash::get($this->params, $name, false); } return $this->params[$name]; } /** * Read data from `php://input`. Useful when interacting with XML or JSON * request body content. * * Getting input with a decoding function: * * `$this->request->input('json_decode');` * * Getting input using a decoding function, and additional params: * * `$this->request->input('Xml::build', array('return' => 'DOMDocument'));` * * Any additional parameters are applied to the callback in the order they are given. * * @param string $callback A decoding callback that will convert the string data to another * representation. Leave empty to access the raw input data. You can also * supply additional parameters for the decoding callback using var args, see above. * @return The decoded/processed request data. */ public function input($callback = null) { $input = $this->_readInput(); $args = func_get_args(); if (!empty($args)) { $callback = array_shift($args); array_unshift($args, $input); return call_user_func_array($callback, $args); } return $input; } /** * Modify data originally from `php://input`. Useful for altering json/xml data * in middleware or DispatcherFilters before it gets to RequestHandlerComponent * * @param string $input A string to replace original parsed data from input() * @return void */ public function setInput($input) { $this->_input = $input; } /** * Allow only certain HTTP request methods. If the request method does not match * a 405 error will be shown and the required "Allow" response header will be set. * * Example: * * $this->request->allowMethod('post', 'delete'); * or * $this->request->allowMethod(array('post', 'delete')); * * If the request would be GET, response header "Allow: POST, DELETE" will be set * and a 405 error will be returned. * * @param string|array $methods Allowed HTTP request methods. * @return bool true * @throws MethodNotAllowedException */ public function allowMethod($methods) { if (!is_array($methods)) { $methods = func_get_args(); } foreach ($methods as $method) { if ($this->is($method)) { return true; } } $allowed = strtoupper(implode(', ', $methods)); $e = new MethodNotAllowedException(); $e->responseHeader('Allow', $allowed); throw $e; } /** * Alias of CakeRequest::allowMethod() for backwards compatibility. * * @param string|array $methods Allowed HTTP request methods. * @return bool true * @throws MethodNotAllowedException * @see CakeRequest::allowMethod() * @deprecated 3.0.0 Since 2.5, use CakeRequest::allowMethod() instead. */ public function onlyAllow($methods) { if (!is_array($methods)) { $methods = func_get_args(); } return $this->allowMethod($methods); } /** * Read data from php://input, mocked in tests. * * @return string contents of php://input */ protected function _readInput() { if (empty($this->_input)) { $fh = fopen('php://input', 'r'); $content = stream_get_contents($fh); fclose($fh); $this->_input = $content; } return $this->_input; } /** * Array access read implementation * * @param string $name Name of the key being accessed. * @return mixed */ public function offsetGet($name) { if (isset($this->params[$name])) { return $this->params[$name]; } if ($name === 'url') { return $this->query; } if ($name === 'data') { return $this->data; } return null; } /** * Array access write implementation * * @param string $name Name of the key being written * @param mixed $value The value being written. * @return void */ public function offsetSet($name, $value) { $this->params[$name] = $value; } /** * Array access isset() implementation * * @param string $name thing to check. * @return bool */ public function offsetExists($name) { return isset($this->params[$name]); } /** * Array access unset() implementation * * @param string $name Name to unset. * @return void */ public function offsetUnset($name) { unset($this->params[$name]); } } cakephp-2.8.0/lib/Cake/Network/CakeResponse.php000066400000000000000000001271451265552240500213110ustar00rootroot00000000000000 'Continue', 101 => 'Switching Protocols', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', 429 => 'Too Many Requests', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'Unsupported Version' ); /** * Holds known mime type mappings * * @var array */ protected $_mimeTypes = array( 'html' => array('text/html', '*/*'), 'json' => 'application/json', 'xml' => array('application/xml', 'text/xml'), 'rss' => 'application/rss+xml', 'ai' => 'application/postscript', 'bcpio' => 'application/x-bcpio', 'bin' => 'application/octet-stream', 'ccad' => 'application/clariscad', 'cdf' => 'application/x-netcdf', 'class' => 'application/octet-stream', 'cpio' => 'application/x-cpio', 'cpt' => 'application/mac-compactpro', 'csh' => 'application/x-csh', 'csv' => array('text/csv', 'application/vnd.ms-excel'), 'dcr' => 'application/x-director', 'dir' => 'application/x-director', 'dms' => 'application/octet-stream', 'doc' => 'application/msword', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'drw' => 'application/drafting', 'dvi' => 'application/x-dvi', 'dwg' => 'application/acad', 'dxf' => 'application/dxf', 'dxr' => 'application/x-director', 'eot' => 'application/vnd.ms-fontobject', 'eps' => 'application/postscript', 'exe' => 'application/octet-stream', 'ez' => 'application/andrew-inset', 'flv' => 'video/x-flv', 'gtar' => 'application/x-gtar', 'gz' => 'application/x-gzip', 'bz2' => 'application/x-bzip', '7z' => 'application/x-7z-compressed', 'hdf' => 'application/x-hdf', 'hqx' => 'application/mac-binhex40', 'ico' => 'image/x-icon', 'ips' => 'application/x-ipscript', 'ipx' => 'application/x-ipix', 'js' => 'application/javascript', 'latex' => 'application/x-latex', 'lha' => 'application/octet-stream', 'lsp' => 'application/x-lisp', 'lzh' => 'application/octet-stream', 'man' => 'application/x-troff-man', 'me' => 'application/x-troff-me', 'mif' => 'application/vnd.mif', 'ms' => 'application/x-troff-ms', 'nc' => 'application/x-netcdf', 'oda' => 'application/oda', 'otf' => 'font/otf', 'pdf' => 'application/pdf', 'pgn' => 'application/x-chess-pgn', 'pot' => 'application/vnd.ms-powerpoint', 'pps' => 'application/vnd.ms-powerpoint', 'ppt' => 'application/vnd.ms-powerpoint', 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'ppz' => 'application/vnd.ms-powerpoint', 'pre' => 'application/x-freelance', 'prt' => 'application/pro_eng', 'ps' => 'application/postscript', 'roff' => 'application/x-troff', 'scm' => 'application/x-lotusscreencam', 'set' => 'application/set', 'sh' => 'application/x-sh', 'shar' => 'application/x-shar', 'sit' => 'application/x-stuffit', 'skd' => 'application/x-koan', 'skm' => 'application/x-koan', 'skp' => 'application/x-koan', 'skt' => 'application/x-koan', 'smi' => 'application/smil', 'smil' => 'application/smil', 'sol' => 'application/solids', 'spl' => 'application/x-futuresplash', 'src' => 'application/x-wais-source', 'step' => 'application/STEP', 'stl' => 'application/SLA', 'stp' => 'application/STEP', 'sv4cpio' => 'application/x-sv4cpio', 'sv4crc' => 'application/x-sv4crc', 'svg' => 'image/svg+xml', 'svgz' => 'image/svg+xml', 'swf' => 'application/x-shockwave-flash', 't' => 'application/x-troff', 'tar' => 'application/x-tar', 'tcl' => 'application/x-tcl', 'tex' => 'application/x-tex', 'texi' => 'application/x-texinfo', 'texinfo' => 'application/x-texinfo', 'tr' => 'application/x-troff', 'tsp' => 'application/dsptype', 'ttc' => 'font/ttf', 'ttf' => 'font/ttf', 'unv' => 'application/i-deas', 'ustar' => 'application/x-ustar', 'vcd' => 'application/x-cdlink', 'vda' => 'application/vda', 'xlc' => 'application/vnd.ms-excel', 'xll' => 'application/vnd.ms-excel', 'xlm' => 'application/vnd.ms-excel', 'xls' => 'application/vnd.ms-excel', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xlw' => 'application/vnd.ms-excel', 'zip' => 'application/zip', 'aif' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff', 'aiff' => 'audio/x-aiff', 'au' => 'audio/basic', 'kar' => 'audio/midi', 'mid' => 'audio/midi', 'midi' => 'audio/midi', 'mp2' => 'audio/mpeg', 'mp3' => 'audio/mpeg', 'mpga' => 'audio/mpeg', 'ogg' => 'audio/ogg', 'oga' => 'audio/ogg', 'spx' => 'audio/ogg', 'ra' => 'audio/x-realaudio', 'ram' => 'audio/x-pn-realaudio', 'rm' => 'audio/x-pn-realaudio', 'rpm' => 'audio/x-pn-realaudio-plugin', 'snd' => 'audio/basic', 'tsi' => 'audio/TSP-audio', 'wav' => 'audio/x-wav', 'aac' => 'audio/aac', 'asc' => 'text/plain', 'c' => 'text/plain', 'cc' => 'text/plain', 'css' => 'text/css', 'etx' => 'text/x-setext', 'f' => 'text/plain', 'f90' => 'text/plain', 'h' => 'text/plain', 'hh' => 'text/plain', 'htm' => array('text/html', '*/*'), 'ics' => 'text/calendar', 'm' => 'text/plain', 'rtf' => 'text/rtf', 'rtx' => 'text/richtext', 'sgm' => 'text/sgml', 'sgml' => 'text/sgml', 'tsv' => 'text/tab-separated-values', 'tpl' => 'text/template', 'txt' => 'text/plain', 'text' => 'text/plain', 'avi' => 'video/x-msvideo', 'fli' => 'video/x-fli', 'mov' => 'video/quicktime', 'movie' => 'video/x-sgi-movie', 'mpe' => 'video/mpeg', 'mpeg' => 'video/mpeg', 'mpg' => 'video/mpeg', 'qt' => 'video/quicktime', 'viv' => 'video/vnd.vivo', 'vivo' => 'video/vnd.vivo', 'ogv' => 'video/ogg', 'webm' => 'video/webm', 'mp4' => 'video/mp4', 'm4v' => 'video/mp4', 'f4v' => 'video/mp4', 'f4p' => 'video/mp4', 'm4a' => 'audio/mp4', 'f4a' => 'audio/mp4', 'f4b' => 'audio/mp4', 'gif' => 'image/gif', 'ief' => 'image/ief', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg', 'jpe' => 'image/jpeg', 'pbm' => 'image/x-portable-bitmap', 'pgm' => 'image/x-portable-graymap', 'png' => 'image/png', 'pnm' => 'image/x-portable-anymap', 'ppm' => 'image/x-portable-pixmap', 'ras' => 'image/cmu-raster', 'rgb' => 'image/x-rgb', 'tif' => 'image/tiff', 'tiff' => 'image/tiff', 'xbm' => 'image/x-xbitmap', 'xpm' => 'image/x-xpixmap', 'xwd' => 'image/x-xwindowdump', 'ice' => 'x-conference/x-cooltalk', 'iges' => 'model/iges', 'igs' => 'model/iges', 'mesh' => 'model/mesh', 'msh' => 'model/mesh', 'silo' => 'model/mesh', 'vrml' => 'model/vrml', 'wrl' => 'model/vrml', 'mime' => 'www/mime', 'pdb' => 'chemical/x-pdb', 'xyz' => 'chemical/x-pdb', 'javascript' => 'application/javascript', 'form' => 'application/x-www-form-urlencoded', 'file' => 'multipart/form-data', 'xhtml' => array('application/xhtml+xml', 'application/xhtml', 'text/xhtml'), 'xhtml-mobile' => 'application/vnd.wap.xhtml+xml', 'atom' => 'application/atom+xml', 'amf' => 'application/x-amf', 'wap' => array('text/vnd.wap.wml', 'text/vnd.wap.wmlscript', 'image/vnd.wap.wbmp'), 'wml' => 'text/vnd.wap.wml', 'wmlscript' => 'text/vnd.wap.wmlscript', 'wbmp' => 'image/vnd.wap.wbmp', 'woff' => 'application/x-font-woff', 'webp' => 'image/webp', 'appcache' => 'text/cache-manifest', 'manifest' => 'text/cache-manifest', 'htc' => 'text/x-component', 'rdf' => 'application/xml', 'crx' => 'application/x-chrome-extension', 'oex' => 'application/x-opera-extension', 'xpi' => 'application/x-xpinstall', 'safariextz' => 'application/octet-stream', 'webapp' => 'application/x-web-app-manifest+json', 'vcf' => 'text/x-vcard', 'vtt' => 'text/vtt', 'mkv' => 'video/x-matroska', 'pkpass' => 'application/vnd.apple.pkpass' ); /** * Protocol header to send to the client * * @var string */ protected $_protocol = 'HTTP/1.1'; /** * Status code to send to the client * * @var int */ protected $_status = 200; /** * Content type to send. This can be an 'extension' that will be transformed using the $_mimetypes array * or a complete mime-type * * @var int */ protected $_contentType = 'text/html'; /** * Buffer list of headers * * @var array */ protected $_headers = array(); /** * Buffer string for response message * * @var string */ protected $_body = null; /** * File object for file to be read out as response * * @var File */ protected $_file = null; /** * File range. Used for requesting ranges of files. * * @var array */ protected $_fileRange = null; /** * The charset the response body is encoded with * * @var string */ protected $_charset = 'UTF-8'; /** * Holds all the cache directives that will be converted * into headers when sending the request * * @var string */ protected $_cacheDirectives = array(); /** * Holds cookies to be sent to the client * * @var array */ protected $_cookies = array(); /** * Constructor * * @param array $options list of parameters to setup the response. Possible values are: * - body: the response text that should be sent to the client * - statusCodes: additional allowable response codes * - status: the HTTP status code to respond with * - type: a complete mime-type string or an extension mapped in this class * - charset: the charset for the response body */ public function __construct(array $options = array()) { if (isset($options['body'])) { $this->body($options['body']); } if (isset($options['statusCodes'])) { $this->httpCodes($options['statusCodes']); } if (isset($options['status'])) { $this->statusCode($options['status']); } if (isset($options['type'])) { $this->type($options['type']); } if (!isset($options['charset'])) { $options['charset'] = Configure::read('App.encoding'); } $this->charset($options['charset']); } /** * Sends the complete response to the client including headers and message body. * Will echo out the content in the response body. * * @return void */ public function send() { if (isset($this->_headers['Location']) && $this->_status === 200) { $this->statusCode(302); } $codeMessage = $this->_statusCodes[$this->_status]; $this->_setCookies(); $this->_sendHeader("{$this->_protocol} {$this->_status} {$codeMessage}"); $this->_setContent(); $this->_setContentLength(); $this->_setContentType(); foreach ($this->_headers as $header => $values) { foreach ((array)$values as $value) { $this->_sendHeader($header, $value); } } if ($this->_file) { $this->_sendFile($this->_file, $this->_fileRange); $this->_file = $this->_fileRange = null; } else { $this->_sendContent($this->_body); } } /** * Sets the cookies that have been added via CakeResponse::cookie() before any * other output is sent to the client. Will set the cookies in the order they * have been set. * * @return void */ protected function _setCookies() { foreach ($this->_cookies as $name => $c) { setcookie( $name, $c['value'], $c['expire'], $c['path'], $c['domain'], $c['secure'], $c['httpOnly'] ); } } /** * Formats the Content-Type header based on the configured contentType and charset * the charset will only be set in the header if the response is of type text * * @return void */ protected function _setContentType() { if (in_array($this->_status, array(304, 204))) { return; } $whitelist = array( 'application/javascript', 'application/json', 'application/xml', 'application/rss+xml' ); $charset = false; if ($this->_charset && (strpos($this->_contentType, 'text/') === 0 || in_array($this->_contentType, $whitelist)) ) { $charset = true; } if ($charset) { $this->header('Content-Type', "{$this->_contentType}; charset={$this->_charset}"); } else { $this->header('Content-Type', "{$this->_contentType}"); } } /** * Sets the response body to an empty text if the status code is 204 or 304 * * @return void */ protected function _setContent() { if (in_array($this->_status, array(304, 204))) { $this->body(''); } } /** * Calculates the correct Content-Length and sets it as a header in the response * Will not set the value if already set or if the output is compressed. * * @return void */ protected function _setContentLength() { $shouldSetLength = !isset($this->_headers['Content-Length']) && !in_array($this->_status, range(301, 307)); if (isset($this->_headers['Content-Length']) && $this->_headers['Content-Length'] === false) { unset($this->_headers['Content-Length']); return; } if ($shouldSetLength && !$this->outputCompressed()) { $offset = ob_get_level() ? ob_get_length() : 0; if (ini_get('mbstring.func_overload') & 2 && function_exists('mb_strlen')) { $this->length($offset + mb_strlen($this->_body, '8bit')); } else { $this->length($this->_headers['Content-Length'] = $offset + strlen($this->_body)); } } } /** * Sends a header to the client. * * Will skip sending headers if headers have already been sent. * * @param string $name the header name * @param string $value the header value * @return void */ protected function _sendHeader($name, $value = null) { if (headers_sent($filename, $linenum)) { return; } if ($value === null) { header($name); } else { header("{$name}: {$value}"); } } /** * Sends a content string to the client. * * @param string $content string to send as response body * @return void */ protected function _sendContent($content) { echo $content; } /** * Buffers a header string to be sent * Returns the complete list of buffered headers * * ### Single header * e.g `header('Location', 'http://example.com');` * * ### Multiple headers * e.g `header(array('Location' => 'http://example.com', 'X-Extra' => 'My header'));` * * ### String header * e.g `header('WWW-Authenticate: Negotiate');` * * ### Array of string headers * e.g `header(array('WWW-Authenticate: Negotiate', 'Content-type: application/pdf'));` * * Multiple calls for setting the same header name will have the same effect as setting the header once * with the last value sent for it * e.g `header('WWW-Authenticate: Negotiate'); header('WWW-Authenticate: Not-Negotiate');` * will have the same effect as only doing `header('WWW-Authenticate: Not-Negotiate');` * * @param string|array $header An array of header strings or a single header string * - an associative array of "header name" => "header value" is also accepted * - an array of string headers is also accepted * @param string|array $value The header value(s) * @return array list of headers to be sent */ public function header($header = null, $value = null) { if ($header === null) { return $this->_headers; } $headers = is_array($header) ? $header : array($header => $value); foreach ($headers as $header => $value) { if (is_numeric($header)) { list($header, $value) = array($value, null); } if ($value === null) { list($header, $value) = explode(':', $header, 2); } $this->_headers[$header] = is_array($value) ? array_map('trim', $value) : trim($value); } return $this->_headers; } /** * Accessor for the location header. * * Get/Set the Location header value. * * @param null|string $url Either null to get the current location, or a string to set one. * @return string|null When setting the location null will be returned. When reading the location * a string of the current location header value (if any) will be returned. */ public function location($url = null) { if ($url === null) { $headers = $this->header(); return isset($headers['Location']) ? $headers['Location'] : null; } $this->header('Location', $url); return null; } /** * Buffers the response message to be sent * if $content is null the current buffer is returned * * @param string $content the string message to be sent * @return string current message buffer if $content param is passed as null */ public function body($content = null) { if ($content === null) { return $this->_body; } return $this->_body = $content; } /** * Sets the HTTP status code to be sent * if $code is null the current code is returned * * @param int $code the HTTP status code * @return int current status code * @throws CakeException When an unknown status code is reached. */ public function statusCode($code = null) { if ($code === null) { return $this->_status; } if (!isset($this->_statusCodes[$code])) { throw new CakeException(__d('cake_dev', 'Unknown status code')); } return $this->_status = $code; } /** * Queries & sets valid HTTP response codes & messages. * * @param int|array $code If $code is an integer, then the corresponding code/message is * returned if it exists, null if it does not exist. If $code is an array, then the * keys are used as codes and the values as messages to add to the default HTTP * codes. The codes must be integers greater than 99 and less than 1000. Keep in * mind that the HTTP specification outlines that status codes begin with a digit * between 1 and 5, which defines the class of response the client is to expect. * Example: * * httpCodes(404); // returns array(404 => 'Not Found') * * httpCodes(array( * 381 => 'Unicorn Moved', * 555 => 'Unexpected Minotaur' * )); // sets these new values, and returns true * * httpCodes(array( * 0 => 'Nothing Here', * -1 => 'Reverse Infinity', * 12345 => 'Universal Password', * 'Hello' => 'World' * )); // throws an exception due to invalid codes * * For more on HTTP status codes see: http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1 * * @return mixed associative array of the HTTP codes as keys, and the message * strings as values, or null of the given $code does not exist. * @throws CakeException If an attempt is made to add an invalid status code */ public function httpCodes($code = null) { if (empty($code)) { return $this->_statusCodes; } if (is_array($code)) { $codes = array_keys($code); $min = min($codes); if (!is_int($min) || $min < 100 || max($codes) > 999) { throw new CakeException(__d('cake_dev', 'Invalid status code')); } $this->_statusCodes = $code + $this->_statusCodes; return true; } if (!isset($this->_statusCodes[$code])) { return null; } return array($code => $this->_statusCodes[$code]); } /** * Sets the response content type. It can be either a file extension * which will be mapped internally to a mime-type or a string representing a mime-type * if $contentType is null the current content type is returned * if $contentType is an associative array, content type definitions will be stored/replaced * * ### Setting the content type * * e.g `type('jpg');` * * ### Returning the current content type * * e.g `type();` * * ### Storing content type definitions * * e.g `type(array('keynote' => 'application/keynote', 'bat' => 'application/bat'));` * * ### Replacing a content type definition * * e.g `type(array('jpg' => 'text/plain'));` * * @param string $contentType Content type key. * @return mixed current content type or false if supplied an invalid content type */ public function type($contentType = null) { if ($contentType === null) { return $this->_contentType; } if (is_array($contentType)) { foreach ($contentType as $type => $definition) { $this->_mimeTypes[$type] = $definition; } return $this->_contentType; } if (isset($this->_mimeTypes[$contentType])) { $contentType = $this->_mimeTypes[$contentType]; $contentType = is_array($contentType) ? current($contentType) : $contentType; } if (strpos($contentType, '/') === false) { return false; } return $this->_contentType = $contentType; } /** * Returns the mime type definition for an alias * * e.g `getMimeType('pdf'); // returns 'application/pdf'` * * @param string $alias the content type alias to map * @return mixed string mapped mime type or false if $alias is not mapped */ public function getMimeType($alias) { if (isset($this->_mimeTypes[$alias])) { return $this->_mimeTypes[$alias]; } return false; } /** * Maps a content-type back to an alias * * e.g `mapType('application/pdf'); // returns 'pdf'` * * @param string|array $ctype Either a string content type to map, or an array of types. * @return mixed Aliases for the types provided. */ public function mapType($ctype) { if (is_array($ctype)) { return array_map(array($this, 'mapType'), $ctype); } foreach ($this->_mimeTypes as $alias => $types) { if (in_array($ctype, (array)$types)) { return $alias; } } return null; } /** * Sets the response charset * if $charset is null the current charset is returned * * @param string $charset Character set string. * @return string current charset */ public function charset($charset = null) { if ($charset === null) { return $this->_charset; } return $this->_charset = $charset; } /** * Sets the correct headers to instruct the client to not cache the response * * @return void */ public function disableCache() { $this->header(array( 'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT', 'Last-Modified' => gmdate("D, d M Y H:i:s") . " GMT", 'Cache-Control' => 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0' )); } /** * Sets the correct headers to instruct the client to cache the response. * * @param string $since a valid time since the response text has not been modified * @param string $time a valid time for cache expiry * @return void */ public function cache($since, $time = '+1 day') { if (!is_int($time)) { $time = strtotime($time); } $this->header(array( 'Date' => gmdate("D, j M Y G:i:s ", time()) . 'GMT' )); $this->modified($since); $this->expires($time); $this->sharable(true); $this->maxAge($time - time()); } /** * Sets whether a response is eligible to be cached by intermediate proxies * This method controls the `public` or `private` directive in the Cache-Control * header * * @param bool $public If set to true, the Cache-Control header will be set as public * if set to false, the response will be set to private * if no value is provided, it will return whether the response is sharable or not * @param int $time time in seconds after which the response should no longer be considered fresh * @return bool */ public function sharable($public = null, $time = null) { if ($public === null) { $public = array_key_exists('public', $this->_cacheDirectives); $private = array_key_exists('private', $this->_cacheDirectives); $noCache = array_key_exists('no-cache', $this->_cacheDirectives); if (!$public && !$private && !$noCache) { return null; } $sharable = $public || !($private || $noCache); return $sharable; } if ($public) { $this->_cacheDirectives['public'] = true; unset($this->_cacheDirectives['private']); } else { $this->_cacheDirectives['private'] = true; unset($this->_cacheDirectives['public']); } $this->maxAge($time); if (!$time) { $this->_setCacheControl(); } return (bool)$public; } /** * Sets the Cache-Control s-maxage directive. * The max-age is the number of seconds after which the response should no longer be considered * a good candidate to be fetched from a shared cache (like in a proxy server). * If called with no parameters, this function will return the current max-age value if any * * @param int $seconds if null, the method will return the current s-maxage value * @return int */ public function sharedMaxAge($seconds = null) { if ($seconds !== null) { $this->_cacheDirectives['s-maxage'] = $seconds; $this->_setCacheControl(); } if (isset($this->_cacheDirectives['s-maxage'])) { return $this->_cacheDirectives['s-maxage']; } return null; } /** * Sets the Cache-Control max-age directive. * The max-age is the number of seconds after which the response should no longer be considered * a good candidate to be fetched from the local (client) cache. * If called with no parameters, this function will return the current max-age value if any * * @param int $seconds if null, the method will return the current max-age value * @return int */ public function maxAge($seconds = null) { if ($seconds !== null) { $this->_cacheDirectives['max-age'] = $seconds; $this->_setCacheControl(); } if (isset($this->_cacheDirectives['max-age'])) { return $this->_cacheDirectives['max-age']; } return null; } /** * Sets the Cache-Control must-revalidate directive. * must-revalidate indicates that the response should not be served * stale by a cache under any circumstance without first revalidating * with the origin. * If called with no parameters, this function will return whether must-revalidate is present. * * @param bool $enable If null returns whether directive is set, if boolean * sets or unsets directive. * @return bool */ public function mustRevalidate($enable = null) { if ($enable !== null) { if ($enable) { $this->_cacheDirectives['must-revalidate'] = true; } else { unset($this->_cacheDirectives['must-revalidate']); } $this->_setCacheControl(); } return array_key_exists('must-revalidate', $this->_cacheDirectives); } /** * Helper method to generate a valid Cache-Control header from the options set * in other methods * * @return void */ protected function _setCacheControl() { $control = ''; foreach ($this->_cacheDirectives as $key => $val) { $control .= $val === true ? $key : sprintf('%s=%s', $key, $val); $control .= ', '; } $control = rtrim($control, ', '); $this->header('Cache-Control', $control); } /** * Sets the Expires header for the response by taking an expiration time * If called with no parameters it will return the current Expires value * * ## Examples: * * `$response->expires('now')` Will Expire the response cache now * `$response->expires(new DateTime('+1 day'))` Will set the expiration in next 24 hours * `$response->expires()` Will return the current expiration header value * * @param string|DateTime $time Valid time string or DateTime object. * @return string */ public function expires($time = null) { if ($time !== null) { $date = $this->_getUTCDate($time); $this->_headers['Expires'] = $date->format('D, j M Y H:i:s') . ' GMT'; } if (isset($this->_headers['Expires'])) { return $this->_headers['Expires']; } return null; } /** * Sets the Last-Modified header for the response by taking a modification time * If called with no parameters it will return the current Last-Modified value * * ## Examples: * * `$response->modified('now')` Will set the Last-Modified to the current time * `$response->modified(new DateTime('+1 day'))` Will set the modification date in the past 24 hours * `$response->modified()` Will return the current Last-Modified header value * * @param string|DateTime $time Valid time string or DateTime object. * @return string */ public function modified($time = null) { if ($time !== null) { $date = $this->_getUTCDate($time); $this->_headers['Last-Modified'] = $date->format('D, j M Y H:i:s') . ' GMT'; } if (isset($this->_headers['Last-Modified'])) { return $this->_headers['Last-Modified']; } return null; } /** * Sets the response as Not Modified by removing any body contents * setting the status code to "304 Not Modified" and removing all * conflicting headers * * @return void */ public function notModified() { $this->statusCode(304); $this->body(''); $remove = array( 'Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified' ); foreach ($remove as $header) { unset($this->_headers[$header]); } } /** * Sets the Vary header for the response, if an array is passed, * values will be imploded into a comma separated string. If no * parameters are passed, then an array with the current Vary header * value is returned * * @param string|array $cacheVariances a single Vary string or an array * containing the list for variances. * @return array */ public function vary($cacheVariances = null) { if ($cacheVariances !== null) { $cacheVariances = (array)$cacheVariances; $this->_headers['Vary'] = implode(', ', $cacheVariances); } if (isset($this->_headers['Vary'])) { return explode(', ', $this->_headers['Vary']); } return null; } /** * Sets the response Etag, Etags are a strong indicative that a response * can be cached by a HTTP client. A bad way of generating Etags is * creating a hash of the response output, instead generate a unique * hash of the unique components that identifies a request, such as a * modification time, a resource Id, and anything else you consider it * makes it unique. * * Second parameter is used to instruct clients that the content has * changed, but sematicallly, it can be used as the same thing. Think * for instance of a page with a hit counter, two different page views * are equivalent, but they differ by a few bytes. This leaves off to * the Client the decision of using or not the cached page. * * If no parameters are passed, current Etag header is returned. * * @param string $tag Tag to set. * @param bool $weak whether the response is semantically the same as * other with the same hash or not * @return string */ public function etag($tag = null, $weak = false) { if ($tag !== null) { $this->_headers['Etag'] = sprintf('%s"%s"', ($weak) ? 'W/' : null, $tag); } if (isset($this->_headers['Etag'])) { return $this->_headers['Etag']; } return null; } /** * Returns a DateTime object initialized at the $time param and using UTC * as timezone * * @param string|DateTime $time Valid time string or unix timestamp or DateTime object. * @return DateTime */ protected function _getUTCDate($time = null) { if ($time instanceof DateTime) { $result = clone $time; } elseif (is_int($time)) { $result = new DateTime(date('Y-m-d H:i:s', $time)); } else { $result = new DateTime($time); } $result->setTimeZone(new DateTimeZone('UTC')); return $result; } /** * Sets the correct output buffering handler to send a compressed response. Responses will * be compressed with zlib, if the extension is available. * * @return bool false if client does not accept compressed responses or no handler is available, true otherwise */ public function compress() { $compressionEnabled = ini_get("zlib.output_compression") !== '1' && extension_loaded("zlib") && (strpos(env('HTTP_ACCEPT_ENCODING'), 'gzip') !== false); return $compressionEnabled && ob_start('ob_gzhandler'); } /** * Returns whether the resulting output will be compressed by PHP * * @return bool */ public function outputCompressed() { return strpos(env('HTTP_ACCEPT_ENCODING'), 'gzip') !== false && (ini_get("zlib.output_compression") === '1' || in_array('ob_gzhandler', ob_list_handlers())); } /** * Sets the correct headers to instruct the browser to download the response as a file. * * @param string $filename the name of the file as the browser will download the response * @return void */ public function download($filename) { $this->header('Content-Disposition', 'attachment; filename="' . $filename . '"'); } /** * Sets the protocol to be used when sending the response. Defaults to HTTP/1.1 * If called with no arguments, it will return the current configured protocol * * @param string $protocol Protocol to be used for sending response. * @return string protocol currently set */ public function protocol($protocol = null) { if ($protocol !== null) { $this->_protocol = $protocol; } return $this->_protocol; } /** * Sets the Content-Length header for the response * If called with no arguments returns the last Content-Length set * * @param int $bytes Number of bytes * @return int|null */ public function length($bytes = null) { if ($bytes !== null) { $this->_headers['Content-Length'] = $bytes; } if (isset($this->_headers['Content-Length'])) { return $this->_headers['Content-Length']; } return null; } /** * Checks whether a response has not been modified according to the 'If-None-Match' * (Etags) and 'If-Modified-Since' (last modification date) request * headers. If the response is detected to be not modified, it * is marked as so accordingly so the client can be informed of that. * * In order to mark a response as not modified, you need to set at least * the Last-Modified etag response header before calling this method. Otherwise * a comparison will not be possible. * * @param CakeRequest $request Request object * @return bool whether the response was marked as not modified or not. */ public function checkNotModified(CakeRequest $request) { $etags = preg_split('/\s*,\s*/', $request->header('If-None-Match'), null, PREG_SPLIT_NO_EMPTY); $modifiedSince = $request->header('If-Modified-Since'); if ($responseTag = $this->etag()) { $etagMatches = in_array('*', $etags) || in_array($responseTag, $etags); } if ($modifiedSince) { $timeMatches = strtotime($this->modified()) === strtotime($modifiedSince); } $checks = compact('etagMatches', 'timeMatches'); if (empty($checks)) { return false; } $notModified = !in_array(false, $checks, true); if ($notModified) { $this->notModified(); } return $notModified; } /** * String conversion. Fetches the response body as a string. * Does *not* send headers. * * @return string */ public function __toString() { return (string)$this->_body; } /** * Getter/Setter for cookie configs * * This method acts as a setter/getter depending on the type of the argument. * If the method is called with no arguments, it returns all configurations. * * If the method is called with a string as argument, it returns either the * given configuration if it is set, or null, if it's not set. * * If the method is called with an array as argument, it will set the cookie * configuration to the cookie container. * * @param array $options Either null to get all cookies, string for a specific cookie * or array to set cookie. * * ### Options (when setting a configuration) * - name: The Cookie name * - value: Value of the cookie * - expire: Time the cookie expires in * - path: Path the cookie applies to * - domain: Domain the cookie is for. * - secure: Is the cookie https? * - httpOnly: Is the cookie available in the client? * * ## Examples * * ### Getting all cookies * * `$this->cookie()` * * ### Getting a certain cookie configuration * * `$this->cookie('MyCookie')` * * ### Setting a cookie configuration * * `$this->cookie((array) $options)` * * @return mixed */ public function cookie($options = null) { if ($options === null) { return $this->_cookies; } if (is_string($options)) { if (!isset($this->_cookies[$options])) { return null; } return $this->_cookies[$options]; } $defaults = array( 'name' => 'CakeCookie[default]', 'value' => '', 'expire' => 0, 'path' => '/', 'domain' => '', 'secure' => false, 'httpOnly' => false ); $options += $defaults; $this->_cookies[$options['name']] = $options; } /** * Setup access for origin and methods on cross origin requests * * This method allow multiple ways to setup the domains, see the examples * * ### Full URI * e.g `cors($request, 'http://www.cakephp.org');` * * ### URI with wildcard * e.g `cors($request, 'http://*.cakephp.org');` * * ### Ignoring the requested protocol * e.g `cors($request, 'www.cakephp.org');` * * ### Any URI * e.g `cors($request, '*');` * * ### Whitelist of URIs * e.g `cors($request, array('http://www.cakephp.org', '*.google.com', 'https://myproject.github.io'));` * * @param CakeRequest $request Request object * @param string|array $allowedDomains List of allowed domains, see method description for more details * @param string|array $allowedMethods List of HTTP verbs allowed * @param string|array $allowedHeaders List of HTTP headers allowed * @return void */ public function cors(CakeRequest $request, $allowedDomains, $allowedMethods = array(), $allowedHeaders = array()) { $origin = $request->header('Origin'); if (!$origin) { return; } $allowedDomains = $this->_normalizeCorsDomains((array)$allowedDomains, $request->is('ssl')); foreach ($allowedDomains as $domain) { if (!preg_match($domain['preg'], $origin)) { continue; } $this->header('Access-Control-Allow-Origin', $domain['original'] === '*' ? '*' : $origin); $allowedMethods && $this->header('Access-Control-Allow-Methods', implode(', ', (array)$allowedMethods)); $allowedHeaders && $this->header('Access-Control-Allow-Headers', implode(', ', (array)$allowedHeaders)); break; } } /** * Normalize the origin to regular expressions and put in an array format * * @param array $domains Domains to normalize * @param bool $requestIsSSL Whether it's a SSL request. * @return array */ protected function _normalizeCorsDomains($domains, $requestIsSSL = false) { $result = array(); foreach ($domains as $domain) { if ($domain === '*') { $result[] = array('preg' => '@.@', 'original' => '*'); continue; } $original = $preg = $domain; if (strpos($domain, '://') === false) { $preg = ($requestIsSSL ? 'https://' : 'http://') . $domain; } $preg = '@' . str_replace('*', '.*', $domain) . '@'; $result[] = compact('original', 'preg'); } return $result; } /** * Setup for display or download the given file. * * If $_SERVER['HTTP_RANGE'] is set a slice of the file will be * returned instead of the entire file. * * ### Options keys * * - name: Alternate download name * - download: If `true` sets download header and forces file to be downloaded rather than displayed in browser * * @param string $path Path to file. If the path is not an absolute path that resolves * to a file, `APP` will be prepended to the path. * @param array $options Options See above. * @return void * @throws NotFoundException */ public function file($path, $options = array()) { $options += array( 'name' => null, 'download' => null ); if (strpos($path, '../') !== false || strpos($path, '..\\') !== false) { throw new NotFoundException(__d( 'cake_dev', 'The requested file contains `..` and will not be read.' )); } if (!is_file($path)) { $path = APP . $path; } $file = new File($path); if (!$file->exists() || !$file->readable()) { if (Configure::read('debug')) { throw new NotFoundException(__d('cake_dev', 'The requested file %s was not found or not readable', $path)); } throw new NotFoundException(__d('cake', 'The requested file was not found')); } $extension = strtolower($file->ext()); $download = $options['download']; if ((!$extension || $this->type($extension) === false) && $download === null) { $download = true; } $fileSize = $file->size(); if ($download) { $agent = env('HTTP_USER_AGENT'); if (preg_match('%Opera(/| )([0-9].[0-9]{1,2})%', $agent)) { $contentType = 'application/octet-stream'; } elseif (preg_match('/MSIE ([0-9].[0-9]{1,2})/', $agent)) { $contentType = 'application/force-download'; } if (!empty($contentType)) { $this->type($contentType); } if ($options['name'] === null) { $name = $file->name; } else { $name = $options['name']; } $this->download($name); $this->header('Content-Transfer-Encoding', 'binary'); } $this->header('Accept-Ranges', 'bytes'); $httpRange = env('HTTP_RANGE'); if (isset($httpRange)) { $this->_fileRange($file, $httpRange); } else { $this->header('Content-Length', $fileSize); } $this->_clearBuffer(); $this->_file = $file; } /** * Apply a file range to a file and set the end offset. * * If an invalid range is requested a 416 Status code will be used * in the response. * * @param File $file The file to set a range on. * @param string $httpRange The range to use. * @return void */ protected function _fileRange($file, $httpRange) { list(, $range) = explode('=', $httpRange); list($start, $end) = explode('-', $range); $fileSize = $file->size(); $lastByte = $fileSize - 1; if ($start === '') { $start = $fileSize - $end; $end = $lastByte; } if ($end === '') { $end = $lastByte; } if ($start > $end || $end > $lastByte || $start > $lastByte) { $this->statusCode(416); $this->header(array( 'Content-Range' => 'bytes 0-' . $lastByte . '/' . $fileSize )); return; } $this->header(array( 'Content-Length' => $end - $start + 1, 'Content-Range' => 'bytes ' . $start . '-' . $end . '/' . $fileSize )); $this->statusCode(206); $this->_fileRange = array($start, $end); } /** * Reads out a file, and echos the content to the client. * * @param File $file File object * @param array $range The range to read out of the file. * @return bool True is whole file is echoed successfully or false if client connection is lost in between */ protected function _sendFile($file, $range) { $compress = $this->outputCompressed(); $file->open('rb'); $end = $start = false; if ($range) { list($start, $end) = $range; } if ($start !== false) { $file->offset($start); } $bufferSize = 8192; set_time_limit(0); session_write_close(); while (!feof($file->handle)) { if (!$this->_isActive()) { $file->close(); return false; } $offset = $file->offset(); if ($end && $offset >= $end) { break; } if ($end && $offset + $bufferSize >= $end) { $bufferSize = $end - $offset + 1; } echo fread($file->handle, $bufferSize); if (!$compress) { $this->_flushBuffer(); } } $file->close(); return true; } /** * Returns true if connection is still active * * @return bool */ protected function _isActive() { return connection_status() === CONNECTION_NORMAL && !connection_aborted(); } /** * Clears the contents of the topmost output buffer and discards them * * @return bool */ protected function _clearBuffer() { if (ob_get_length()) { return ob_end_clean(); } return true; } /** * Flushes the contents of the output buffer * * @return void */ protected function _flushBuffer() { //@codingStandardsIgnoreStart @flush(); if (ob_get_level()) { @ob_flush(); } //@codingStandardsIgnoreEnd } } cakephp-2.8.0/lib/Cake/Network/CakeSocket.php000066400000000000000000000277001265552240500207370ustar00rootroot00000000000000 false, 'host' => 'localhost', 'protocol' => 'tcp', 'port' => 80, 'timeout' => 30 ); /** * Configuration settings for the socket connection * * @var array */ public $config = array(); /** * Reference to socket connection resource * * @var resource */ public $connection = null; /** * This boolean contains the current state of the CakeSocket class * * @var bool */ public $connected = false; /** * This variable contains an array with the last error number (num) and string (str) * * @var array */ public $lastError = array(); /** * True if the socket stream is encrypted after a CakeSocket::enableCrypto() call * * @var bool */ public $encrypted = false; /** * Contains all the encryption methods available * * @var array */ protected $_encryptMethods = array( // @codingStandardsIgnoreStart 'sslv2_client' => STREAM_CRYPTO_METHOD_SSLv2_CLIENT, 'sslv3_client' => STREAM_CRYPTO_METHOD_SSLv3_CLIENT, 'sslv23_client' => STREAM_CRYPTO_METHOD_SSLv23_CLIENT, 'tls_client' => STREAM_CRYPTO_METHOD_TLS_CLIENT, 'sslv2_server' => STREAM_CRYPTO_METHOD_SSLv2_SERVER, 'sslv3_server' => STREAM_CRYPTO_METHOD_SSLv3_SERVER, 'sslv23_server' => STREAM_CRYPTO_METHOD_SSLv23_SERVER, 'tls_server' => STREAM_CRYPTO_METHOD_TLS_SERVER // @codingStandardsIgnoreEnd ); /** * Used to capture connection warnings which can happen when there are * SSL errors for example. * * @var array */ protected $_connectionErrors = array(); /** * Constructor. * * @param array $config Socket configuration, which will be merged with the base configuration * @see CakeSocket::$_baseConfig */ public function __construct($config = array()) { $this->config = array_merge($this->_baseConfig, $config); } /** * Connects the socket to the given host and port. * * @return bool Success * @throws SocketException */ public function connect() { if ($this->connection) { $this->disconnect(); } $hasProtocol = strpos($this->config['host'], '://') !== false; if ($hasProtocol) { list($this->config['protocol'], $this->config['host']) = explode('://', $this->config['host']); } $scheme = null; if (!empty($this->config['protocol'])) { $scheme = $this->config['protocol'] . '://'; } if (!empty($this->config['proxy'])) { $scheme = 'tcp://'; } $host = $this->config['host']; if (isset($this->config['request']['uri']['host'])) { $host = $this->config['request']['uri']['host']; } $this->_setSslContext($host); if (!empty($this->config['context'])) { $context = stream_context_create($this->config['context']); } else { $context = stream_context_create(); } $connectAs = STREAM_CLIENT_CONNECT; if ($this->config['persistent']) { $connectAs |= STREAM_CLIENT_PERSISTENT; } set_error_handler(array($this, '_connectionErrorHandler')); $this->connection = stream_socket_client( $scheme . $this->config['host'] . ':' . $this->config['port'], $errNum, $errStr, $this->config['timeout'], $connectAs, $context ); restore_error_handler(); if (!empty($errNum) || !empty($errStr)) { $this->setLastError($errNum, $errStr); throw new SocketException($errStr, $errNum); } if (!$this->connection && $this->_connectionErrors) { $message = implode("\n", $this->_connectionErrors); throw new SocketException($message, E_WARNING); } $this->connected = is_resource($this->connection); if ($this->connected) { stream_set_timeout($this->connection, $this->config['timeout']); if (!empty($this->config['request']) && $this->config['request']['uri']['scheme'] === 'https' && !empty($this->config['proxy']) ) { $req = array(); $req[] = 'CONNECT ' . $this->config['request']['uri']['host'] . ':' . $this->config['request']['uri']['port'] . ' HTTP/1.1'; $req[] = 'Host: ' . $this->config['host']; $req[] = 'User-Agent: php proxy'; if (!empty($this->config['proxyauth'])) { $req[] = 'Proxy-Authorization: ' . $this->config['proxyauth']; } fwrite($this->connection, implode("\r\n", $req) . "\r\n\r\n"); while (!feof($this->connection)) { $s = rtrim(fgets($this->connection, 4096)); if (preg_match('/^$/', $s)) { break; } } $this->enableCrypto('tls', 'client'); } } return $this->connected; } /** * Configure the SSL context options. * * @param string $host The host name being connected to. * @return void */ protected function _setSslContext($host) { foreach ($this->config as $key => $value) { if (substr($key, 0, 4) !== 'ssl_') { continue; } $contextKey = substr($key, 4); if (empty($this->config['context']['ssl'][$contextKey])) { $this->config['context']['ssl'][$contextKey] = $value; } unset($this->config[$key]); } if (version_compare(PHP_VERSION, '5.3.2', '>=')) { if (!isset($this->config['context']['ssl']['SNI_enabled'])) { $this->config['context']['ssl']['SNI_enabled'] = true; } if (version_compare(PHP_VERSION, '5.6.0', '>=')) { if (empty($this->config['context']['ssl']['peer_name'])) { $this->config['context']['ssl']['peer_name'] = $host; } } else { if (empty($this->config['context']['ssl']['SNI_server_name'])) { $this->config['context']['ssl']['SNI_server_name'] = $host; } } } if (empty($this->config['context']['ssl']['cafile'])) { $this->config['context']['ssl']['cafile'] = CAKE . 'Config' . DS . 'cacert.pem'; } if (!empty($this->config['context']['ssl']['verify_host'])) { $this->config['context']['ssl']['CN_match'] = $host; } unset($this->config['context']['ssl']['verify_host']); } /** * socket_stream_client() does not populate errNum, or $errStr when there are * connection errors, as in the case of SSL verification failure. * * Instead we need to handle those errors manually. * * @param int $code Code. * @param string $message Message. * @return void */ protected function _connectionErrorHandler($code, $message) { $this->_connectionErrors[] = $message; } /** * Gets the connection context. * * @return null|array Null when there is no connection, an array when there is. */ public function context() { if (!$this->connection) { return null; } return stream_context_get_options($this->connection); } /** * Gets the host name of the current connection. * * @return string Host name */ public function host() { if (Validation::ip($this->config['host'])) { return gethostbyaddr($this->config['host']); } return gethostbyaddr($this->address()); } /** * Gets the IP address of the current connection. * * @return string IP address */ public function address() { if (Validation::ip($this->config['host'])) { return $this->config['host']; } return gethostbyname($this->config['host']); } /** * Gets all IP addresses associated with the current connection. * * @return array IP addresses */ public function addresses() { if (Validation::ip($this->config['host'])) { return array($this->config['host']); } return gethostbynamel($this->config['host']); } /** * Gets the last error as a string. * * @return string|null Last error */ public function lastError() { if (!empty($this->lastError)) { return $this->lastError['num'] . ': ' . $this->lastError['str']; } return null; } /** * Sets the last error. * * @param int $errNum Error code * @param string $errStr Error string * @return void */ public function setLastError($errNum, $errStr) { $this->lastError = array('num' => $errNum, 'str' => $errStr); } /** * Writes data to the socket. * * @param string $data The data to write to the socket * @return bool Success */ public function write($data) { if (!$this->connected) { if (!$this->connect()) { return false; } } $totalBytes = strlen($data); for ($written = 0, $rv = 0; $written < $totalBytes; $written += $rv) { $rv = fwrite($this->connection, substr($data, $written)); if ($rv === false || $rv === 0) { return $written; } } return $written; } /** * Reads data from the socket. Returns false if no data is available or no connection could be * established. * * @param int $length Optional buffer length to read; defaults to 1024 * @return mixed Socket data */ public function read($length = 1024) { if (!$this->connected) { if (!$this->connect()) { return false; } } if (!feof($this->connection)) { $buffer = fread($this->connection, $length); $info = stream_get_meta_data($this->connection); if ($info['timed_out']) { $this->setLastError(E_WARNING, __d('cake_dev', 'Connection timed out')); return false; } return $buffer; } return false; } /** * Disconnects the socket from the current connection. * * @return bool Success */ public function disconnect() { if (!is_resource($this->connection)) { $this->connected = false; return true; } $this->connected = !fclose($this->connection); if (!$this->connected) { $this->connection = null; } return !$this->connected; } /** * Destructor, used to disconnect from current connection. */ public function __destruct() { $this->disconnect(); } /** * Resets the state of this Socket instance to it's initial state (before Object::__construct got executed) * * @param array $state Array with key and values to reset * @return bool True on success */ public function reset($state = null) { if (empty($state)) { static $initalState = array(); if (empty($initalState)) { $initalState = get_class_vars(__CLASS__); } $state = $initalState; } foreach ($state as $property => $value) { $this->{$property} = $value; } return true; } /** * Encrypts current stream socket, using one of the defined encryption methods. * * @param string $type Type which can be one of 'sslv2', 'sslv3', 'sslv23' or 'tls'. * @param string $clientOrServer Can be one of 'client', 'server'. Default is 'client'. * @param bool $enable Enable or disable encryption. Default is true (enable) * @return bool True on success * @throws InvalidArgumentException When an invalid encryption scheme is chosen. * @throws SocketException When attempting to enable SSL/TLS fails. * @see stream_socket_enable_crypto */ public function enableCrypto($type, $clientOrServer = 'client', $enable = true) { if (!array_key_exists($type . '_' . $clientOrServer, $this->_encryptMethods)) { throw new InvalidArgumentException(__d('cake_dev', 'Invalid encryption scheme chosen')); } $enableCryptoResult = false; try { $enableCryptoResult = stream_socket_enable_crypto($this->connection, $enable, $this->_encryptMethods[$type . '_' . $clientOrServer]); } catch (Exception $e) { $this->setLastError(null, $e->getMessage()); throw new SocketException($e->getMessage()); } if ($enableCryptoResult === true) { $this->encrypted = $enable; return true; } $errorMessage = __d('cake_dev', 'Unable to perform enableCrypto operation on CakeSocket'); $this->setLastError(null, $errorMessage); throw new SocketException($errorMessage); } } cakephp-2.8.0/lib/Cake/Network/Email/000077500000000000000000000000001265552240500172335ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Network/Email/AbstractTransport.php000066400000000000000000000033451265552240500234310ustar00rootroot00000000000000_config = $config + $this->_config; } return $this->_config; } /** * Help to convert headers in string * * @param array $headers Headers in format key => value * @param string $eol End of line string. * @return string */ protected function _headersToString($headers, $eol = "\r\n") { $out = ''; foreach ($headers as $key => $value) { if ($value === false || $value === null || $value === '') { continue; } $out .= $key . ': ' . $value . $eol; } if (!empty($out)) { $out = substr($out, 0, -1 * strlen($eol)); } return $out; } } cakephp-2.8.0/lib/Cake/Network/Email/CakeEmail.php000066400000000000000000001254541265552240500215720ustar00rootroot00000000000000 'ISO-2022-JP' ); /** * Regex for email validation * * If null, filter_var() will be used. Use the emailPattern() method * to set a custom pattern.' * * @var string */ protected $_emailPattern = self::EMAIL_PATTERN; /** * The class name used for email configuration. * * @var string */ protected $_configClass = 'EmailConfig'; /** * An instance of the EmailConfig class can be set here * * @var EmailConfig */ protected $_configInstance; /** * Constructor * * @param array|string $config Array of configs, or string to load configs from email.php */ public function __construct($config = null) { $this->_appCharset = Configure::read('App.encoding'); if ($this->_appCharset !== null) { $this->charset = $this->_appCharset; } $this->_domain = preg_replace('/\:\d+$/', '', env('HTTP_HOST')); if (empty($this->_domain)) { $this->_domain = php_uname('n'); } if ($config) { $this->config($config); } elseif (config('email') && class_exists($this->_configClass)) { $this->_configInstance = new $this->_configClass(); if (isset($this->_configInstance->default)) { $this->config('default'); } } if (empty($this->headerCharset)) { $this->headerCharset = $this->charset; } } /** * From * * @param string|array $email Null to get, String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @return array|CakeEmail * @throws SocketException */ public function from($email = null, $name = null) { if ($email === null) { return $this->_from; } return $this->_setEmailSingle('_from', $email, $name, __d('cake_dev', 'From requires only 1 email address.')); } /** * Sender * * @param string|array $email Null to get, String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @return array|CakeEmail * @throws SocketException */ public function sender($email = null, $name = null) { if ($email === null) { return $this->_sender; } return $this->_setEmailSingle('_sender', $email, $name, __d('cake_dev', 'Sender requires only 1 email address.')); } /** * Reply-To * * @param string|array $email Null to get, String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @return array|CakeEmail * @throws SocketException */ public function replyTo($email = null, $name = null) { if ($email === null) { return $this->_replyTo; } return $this->_setEmailSingle('_replyTo', $email, $name, __d('cake_dev', 'Reply-To requires only 1 email address.')); } /** * Read Receipt (Disposition-Notification-To header) * * @param string|array $email Null to get, String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @return array|CakeEmail * @throws SocketException */ public function readReceipt($email = null, $name = null) { if ($email === null) { return $this->_readReceipt; } return $this->_setEmailSingle('_readReceipt', $email, $name, __d('cake_dev', 'Disposition-Notification-To requires only 1 email address.')); } /** * Return Path * * @param string|array $email Null to get, String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @return array|CakeEmail * @throws SocketException */ public function returnPath($email = null, $name = null) { if ($email === null) { return $this->_returnPath; } return $this->_setEmailSingle('_returnPath', $email, $name, __d('cake_dev', 'Return-Path requires only 1 email address.')); } /** * To * * @param string|array $email Null to get, String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @return array|self */ public function to($email = null, $name = null) { if ($email === null) { return $this->_to; } return $this->_setEmail('_to', $email, $name); } /** * Add To * * @param string|array $email Null to get, String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @return self */ public function addTo($email, $name = null) { return $this->_addEmail('_to', $email, $name); } /** * Cc * * @param string|array $email Null to get, String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @return array|self */ public function cc($email = null, $name = null) { if ($email === null) { return $this->_cc; } return $this->_setEmail('_cc', $email, $name); } /** * Add Cc * * @param string|array $email Null to get, String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @return self */ public function addCc($email, $name = null) { return $this->_addEmail('_cc', $email, $name); } /** * Bcc * * @param string|array $email Null to get, String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @return array|self */ public function bcc($email = null, $name = null) { if ($email === null) { return $this->_bcc; } return $this->_setEmail('_bcc', $email, $name); } /** * Add Bcc * * @param string|array $email Null to get, String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @return self */ public function addBcc($email, $name = null) { return $this->_addEmail('_bcc', $email, $name); } /** * Charset setter/getter * * @param string $charset Character set. * @return string this->charset */ public function charset($charset = null) { if ($charset === null) { return $this->charset; } $this->charset = $charset; if (empty($this->headerCharset)) { $this->headerCharset = $charset; } return $this->charset; } /** * HeaderCharset setter/getter * * @param string $charset Character set. * @return string this->charset */ public function headerCharset($charset = null) { if ($charset === null) { return $this->headerCharset; } return $this->headerCharset = $charset; } /** * EmailPattern setter/getter * * @param string|bool|null $regex The pattern to use for email address validation, * null to unset the pattern and make use of filter_var() instead, false or * nothing to return the current value * @return string|self */ public function emailPattern($regex = false) { if ($regex === false) { return $this->_emailPattern; } $this->_emailPattern = $regex; return $this; } /** * Set email * * @param string $varName Property name * @param string|array $email String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @return self */ protected function _setEmail($varName, $email, $name) { if (!is_array($email)) { $this->_validateEmail($email); if ($name === null) { $name = $email; } $this->{$varName} = array($email => $name); return $this; } $list = array(); foreach ($email as $key => $value) { if (is_int($key)) { $key = $value; } $this->_validateEmail($key); $list[$key] = $value; } $this->{$varName} = $list; return $this; } /** * Validate email address * * @param string $email Email * @return void * @throws SocketException If email address does not validate */ protected function _validateEmail($email) { if ($this->_emailPattern === null) { if (filter_var($email, FILTER_VALIDATE_EMAIL)) { return; } } elseif (preg_match($this->_emailPattern, $email)) { return; } throw new SocketException(__d('cake_dev', 'Invalid email: "%s"', $email)); } /** * Set only 1 email * * @param string $varName Property name * @param string|array $email String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @param string $throwMessage Exception message * @return self * @throws SocketException */ protected function _setEmailSingle($varName, $email, $name, $throwMessage) { $current = $this->{$varName}; $this->_setEmail($varName, $email, $name); if (count($this->{$varName}) !== 1) { $this->{$varName} = $current; throw new SocketException($throwMessage); } return $this; } /** * Add email * * @param string $varName Property name * @param string|array $email String with email, * Array with email as key, name as value or email as value (without name) * @param string $name Name * @return self * @throws SocketException */ protected function _addEmail($varName, $email, $name) { if (!is_array($email)) { $this->_validateEmail($email); if ($name === null) { $name = $email; } $this->{$varName}[$email] = $name; return $this; } $list = array(); foreach ($email as $key => $value) { if (is_int($key)) { $key = $value; } $this->_validateEmail($key); $list[$key] = $value; } $this->{$varName} = array_merge($this->{$varName}, $list); return $this; } /** * Get/Set Subject. * * @param string $subject Subject string. * @return string|self */ public function subject($subject = null) { if ($subject === null) { return $this->_subject; } $this->_subject = $this->_encode((string)$subject); return $this; } /** * Sets headers for the message * * @param array $headers Associative array containing headers to be set. * @return self * @throws SocketException */ public function setHeaders($headers) { if (!is_array($headers)) { throw new SocketException(__d('cake_dev', '$headers should be an array.')); } $this->_headers = $headers; return $this; } /** * Add header for the message * * @param array $headers Headers to set. * @return self * @throws SocketException */ public function addHeaders($headers) { if (!is_array($headers)) { throw new SocketException(__d('cake_dev', '$headers should be an array.')); } $this->_headers = array_merge($this->_headers, $headers); return $this; } /** * Get list of headers * * ### Includes: * * - `from` * - `replyTo` * - `readReceipt` * - `returnPath` * - `to` * - `cc` * - `bcc` * - `subject` * * @param array $include List of headers. * @return array */ public function getHeaders($include = array()) { if ($include == array_values($include)) { $include = array_fill_keys($include, true); } $defaults = array_fill_keys( array( 'from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc', 'subject'), false ); $include += $defaults; $headers = array(); $relation = array( 'from' => 'From', 'replyTo' => 'Reply-To', 'readReceipt' => 'Disposition-Notification-To', 'returnPath' => 'Return-Path' ); foreach ($relation as $var => $header) { if ($include[$var]) { $var = '_' . $var; $headers[$header] = current($this->_formatAddress($this->{$var})); } } if ($include['sender']) { if (key($this->_sender) === key($this->_from)) { $headers['Sender'] = ''; } else { $headers['Sender'] = current($this->_formatAddress($this->_sender)); } } foreach (array('to', 'cc', 'bcc') as $var) { if ($include[$var]) { $classVar = '_' . $var; $headers[ucfirst($var)] = implode(', ', $this->_formatAddress($this->{$classVar})); } } $headers += $this->_headers; if (!isset($headers['X-Mailer'])) { $headers['X-Mailer'] = static::EMAIL_CLIENT; } if (!isset($headers['Date'])) { $headers['Date'] = date(DATE_RFC2822); } if ($this->_messageId !== false) { if ($this->_messageId === true) { $headers['Message-ID'] = '<' . str_replace('-', '', CakeText::UUID()) . '@' . $this->_domain . '>'; } else { $headers['Message-ID'] = $this->_messageId; } } if ($include['subject']) { $headers['Subject'] = $this->_subject; } $headers['MIME-Version'] = '1.0'; if (!empty($this->_attachments)) { $headers['Content-Type'] = 'multipart/mixed; boundary="' . $this->_boundary . '"'; } elseif ($this->_emailFormat === 'both') { $headers['Content-Type'] = 'multipart/alternative; boundary="' . $this->_boundary . '"'; } elseif ($this->_emailFormat === 'text') { $headers['Content-Type'] = 'text/plain; charset=' . $this->_getContentTypeCharset(); } elseif ($this->_emailFormat === 'html') { $headers['Content-Type'] = 'text/html; charset=' . $this->_getContentTypeCharset(); } $headers['Content-Transfer-Encoding'] = $this->_getContentTransferEncoding(); return $headers; } /** * Format addresses * * If the address contains non alphanumeric/whitespace characters, it will * be quoted as characters like `:` and `,` are known to cause issues * in address header fields. * * @param array $address Addresses to format. * @return array */ protected function _formatAddress($address) { $return = array(); foreach ($address as $email => $alias) { if ($email === $alias) { $return[] = $email; } else { $encoded = $this->_encode($alias); if ($encoded === $alias && preg_match('/[^a-z0-9 ]/i', $encoded)) { $encoded = '"' . str_replace('"', '\"', $encoded) . '"'; } $return[] = sprintf('%s <%s>', $encoded, $email); } } return $return; } /** * Template and layout * * @param bool|string $template Template name or null to not use * @param bool|string $layout Layout name or null to not use * @return array|self */ public function template($template = false, $layout = false) { if ($template === false) { return array( 'template' => $this->_template, 'layout' => $this->_layout ); } $this->_template = $template; if ($layout !== false) { $this->_layout = $layout; } return $this; } /** * View class for render * * @param string $viewClass View class name. * @return string|self */ public function viewRender($viewClass = null) { if ($viewClass === null) { return $this->_viewRender; } $this->_viewRender = $viewClass; return $this; } /** * Variables to be set on render * * @param array $viewVars Variables to set for view. * @return array|self */ public function viewVars($viewVars = null) { if ($viewVars === null) { return $this->_viewVars; } $this->_viewVars = array_merge($this->_viewVars, (array)$viewVars); return $this; } /** * Theme to use when rendering * * @param string $theme Theme name. * @return string|self */ public function theme($theme = null) { if ($theme === null) { return $this->_theme; } $this->_theme = $theme; return $this; } /** * Helpers to be used in render * * @param array $helpers Helpers list. * @return array|self */ public function helpers($helpers = null) { if ($helpers === null) { return $this->_helpers; } $this->_helpers = (array)$helpers; return $this; } /** * Email format * * @param string $format Formatting string. * @return string|self * @throws SocketException */ public function emailFormat($format = null) { if ($format === null) { return $this->_emailFormat; } if (!in_array($format, $this->_emailFormatAvailable)) { throw new SocketException(__d('cake_dev', 'Format not available.')); } $this->_emailFormat = $format; return $this; } /** * Transport name * * @param string $name Transport name. * @return string|self */ public function transport($name = null) { if ($name === null) { return $this->_transportName; } $this->_transportName = (string)$name; $this->_transportClass = null; return $this; } /** * Return the transport class * * @return AbstractTransport * @throws SocketException */ public function transportClass() { if ($this->_transportClass) { return $this->_transportClass; } list($plugin, $transportClassname) = pluginSplit($this->_transportName, true); $transportClassname .= 'Transport'; App::uses($transportClassname, $plugin . 'Network/Email'); if (!class_exists($transportClassname)) { throw new SocketException(__d('cake_dev', 'Class "%s" not found.', $transportClassname)); } elseif (!method_exists($transportClassname, 'send')) { throw new SocketException(__d('cake_dev', 'The "%s" does not have a %s method.', $transportClassname, 'send()')); } return $this->_transportClass = new $transportClassname(); } /** * Message-ID * * @param bool|string $message True to generate a new Message-ID, False to ignore (not send in email), String to set as Message-ID * @return bool|string|self * @throws SocketException */ public function messageId($message = null) { if ($message === null) { return $this->_messageId; } if (is_bool($message)) { $this->_messageId = $message; } else { if (!preg_match('/^\<.+@.+\>$/', $message)) { throw new SocketException(__d('cake_dev', 'Invalid format for Message-ID. The text should be something like ""')); } $this->_messageId = $message; } return $this; } /** * Domain as top level (the part after @) * * @param string $domain Manually set the domain for CLI mailing * @return string|self */ public function domain($domain = null) { if ($domain === null) { return $this->_domain; } $this->_domain = $domain; return $this; } /** * Add attachments to the email message * * Attachments can be defined in a few forms depending on how much control you need: * * Attach a single file: * * ``` * $email->attachments('path/to/file'); * ``` * * Attach a file with a different filename: * * ``` * $email->attachments(array('custom_name.txt' => 'path/to/file.txt')); * ``` * * Attach a file and specify additional properties: * * ``` * $email->attachments(array('custom_name.png' => array( * 'file' => 'path/to/file', * 'mimetype' => 'image/png', * 'contentId' => 'abc123', * 'contentDisposition' => false * )); * ``` * * Attach a file from string and specify additional properties: * * ``` * $email->attachments(array('custom_name.png' => array( * 'data' => file_get_contents('path/to/file'), * 'mimetype' => 'image/png' * )); * ``` * * The `contentId` key allows you to specify an inline attachment. In your email text, you * can use `` to display the image inline. * * The `contentDisposition` key allows you to disable the `Content-Disposition` header, this can improve * attachment compatibility with outlook email clients. * * @param string|array $attachments String with the filename or array with filenames * @return array|self Either the array of attachments when getting or $this when setting. * @throws SocketException */ public function attachments($attachments = null) { if ($attachments === null) { return $this->_attachments; } $attach = array(); foreach ((array)$attachments as $name => $fileInfo) { if (!is_array($fileInfo)) { $fileInfo = array('file' => $fileInfo); } if (!isset($fileInfo['file'])) { if (!isset($fileInfo['data'])) { throw new SocketException(__d('cake_dev', 'No file or data specified.')); } if (is_int($name)) { throw new SocketException(__d('cake_dev', 'No filename specified.')); } $fileInfo['data'] = chunk_split(base64_encode($fileInfo['data']), 76, "\r\n"); } else { $fileName = $fileInfo['file']; $fileInfo['file'] = realpath($fileInfo['file']); if ($fileInfo['file'] === false || !file_exists($fileInfo['file'])) { throw new SocketException(__d('cake_dev', 'File not found: "%s"', $fileName)); } if (is_int($name)) { $name = basename($fileInfo['file']); } } if (!isset($fileInfo['mimetype'])) { $fileInfo['mimetype'] = 'application/octet-stream'; } $attach[$name] = $fileInfo; } $this->_attachments = $attach; return $this; } /** * Add attachments * * @param string|array $attachments String with the filename or array with filenames * @return self * @throws SocketException * @see CakeEmail::attachments() */ public function addAttachments($attachments) { $current = $this->_attachments; $this->attachments($attachments); $this->_attachments = array_merge($current, $this->_attachments); return $this; } /** * Get generated message (used by transport classes) * * @param string $type Use MESSAGE_* constants or null to return the full message as array * @return string|array String if have type, array if type is null */ public function message($type = null) { switch ($type) { case static::MESSAGE_HTML: return $this->_htmlMessage; case static::MESSAGE_TEXT: return $this->_textMessage; } return $this->_message; } /** * Configuration to use when send email * * ### Usage * * Load configuration from `app/Config/email.php`: * * `$email->config('default');` * * Merge an array of configuration into the instance: * * `$email->config(array('to' => 'bill@example.com'));` * * @param string|array $config String with configuration name (from email.php), array with config or null to return current config * @return string|array|self */ public function config($config = null) { if ($config === null) { return $this->_config; } if (!is_array($config)) { $config = (string)$config; } $this->_applyConfig($config); return $this; } /** * Send an email using the specified content, template and layout * * @param string|array $content String with message or array with messages * @return array * @throws SocketException */ public function send($content = null) { if (empty($this->_from)) { throw new SocketException(__d('cake_dev', 'From is not specified.')); } if (empty($this->_to) && empty($this->_cc) && empty($this->_bcc)) { throw new SocketException(__d('cake_dev', 'You need to specify at least one destination for to, cc or bcc.')); } if (is_array($content)) { $content = implode("\n", $content) . "\n"; } $this->_message = $this->_render($this->_wrap($content)); $contents = $this->transportClass()->send($this); if (!empty($this->_config['log'])) { $config = array( 'level' => LOG_DEBUG, 'scope' => 'email' ); if ($this->_config['log'] !== true) { if (!is_array($this->_config['log'])) { $this->_config['log'] = array('level' => $this->_config['log']); } $config = $this->_config['log'] + $config; } CakeLog::write( $config['level'], PHP_EOL . $contents['headers'] . PHP_EOL . $contents['message'], $config['scope'] ); } return $contents; } /** * Static method to fast create an instance of CakeEmail * * @param string|array $to Address to send (see CakeEmail::to()). If null, will try to use 'to' from transport config * @param string $subject String of subject or null to use 'subject' from transport config * @param string|array $message String with message or array with variables to be used in render * @param string|array $transportConfig String to use config from EmailConfig or array with configs * @param bool $send Send the email or just return the instance pre-configured * @return self Instance of CakeEmail * @throws SocketException */ public static function deliver($to = null, $subject = null, $message = null, $transportConfig = 'fast', $send = true) { $class = __CLASS__; /** @var CakeEmail $instance */ $instance = new $class($transportConfig); if ($to !== null) { $instance->to($to); } if ($subject !== null) { $instance->subject($subject); } if (is_array($message)) { $instance->viewVars($message); $message = null; } elseif ($message === null && array_key_exists('message', $config = $instance->config())) { $message = $config['message']; } if ($send === true) { $instance->send($message); } return $instance; } /** * Apply the config to an instance * * @param array $config Configuration options. * @return void * @throws ConfigureException When configuration file cannot be found, or is missing * the named config. */ protected function _applyConfig($config) { if (is_string($config)) { if (!$this->_configInstance) { if (!class_exists($this->_configClass) && !config('email')) { throw new ConfigureException(__d('cake_dev', '%s not found.', APP . 'Config' . DS . 'email.php')); } $this->_configInstance = new $this->_configClass(); } if (!isset($this->_configInstance->{$config})) { throw new ConfigureException(__d('cake_dev', 'Unknown email configuration "%s".', $config)); } $config = $this->_configInstance->{$config}; } $this->_config = $config + $this->_config; if (!empty($config['charset'])) { $this->charset = $config['charset']; } if (!empty($config['headerCharset'])) { $this->headerCharset = $config['headerCharset']; } if (empty($this->headerCharset)) { $this->headerCharset = $this->charset; } $simpleMethods = array( 'from', 'sender', 'to', 'replyTo', 'readReceipt', 'returnPath', 'cc', 'bcc', 'messageId', 'domain', 'subject', 'viewRender', 'viewVars', 'attachments', 'transport', 'emailFormat', 'theme', 'helpers', 'emailPattern' ); foreach ($simpleMethods as $method) { if (isset($config[$method])) { $this->$method($config[$method]); unset($config[$method]); } } if (isset($config['headers'])) { $this->setHeaders($config['headers']); unset($config['headers']); } if (array_key_exists('template', $config)) { $this->_template = $config['template']; } if (array_key_exists('layout', $config)) { $this->_layout = $config['layout']; } $this->transportClass()->config($config); } /** * Reset all CakeEmail internal variables to be able to send out a new email. * * @return self */ public function reset() { $this->_to = array(); $this->_from = array(); $this->_sender = array(); $this->_replyTo = array(); $this->_readReceipt = array(); $this->_returnPath = array(); $this->_cc = array(); $this->_bcc = array(); $this->_messageId = true; $this->_subject = ''; $this->_headers = array(); $this->_layout = 'default'; $this->_template = ''; $this->_viewRender = 'View'; $this->_viewVars = array(); $this->_theme = null; $this->_helpers = array('Html'); $this->_textMessage = ''; $this->_htmlMessage = ''; $this->_message = ''; $this->_emailFormat = 'text'; $this->_transportName = 'Mail'; $this->_transportClass = null; $this->charset = 'utf-8'; $this->headerCharset = null; $this->_attachments = array(); $this->_config = array(); $this->_emailPattern = static::EMAIL_PATTERN; return $this; } /** * Encode the specified string using the current charset * * @param string $text String to encode * @return string Encoded string */ protected function _encode($text) { $internalEncoding = function_exists('mb_internal_encoding'); if ($internalEncoding) { $restore = mb_internal_encoding(); mb_internal_encoding($this->_appCharset); } if (empty($this->headerCharset)) { $this->headerCharset = $this->charset; } $return = mb_encode_mimeheader($text, $this->headerCharset, 'B'); if ($internalEncoding) { mb_internal_encoding($restore); } return $return; } /** * Translates a string for one charset to another if the App.encoding value * differs and the mb_convert_encoding function exists * * @param string $text The text to be converted * @param string $charset the target encoding * @return string */ protected function _encodeString($text, $charset) { if ($this->_appCharset === $charset || !function_exists('mb_convert_encoding')) { return $text; } return mb_convert_encoding($text, $charset, $this->_appCharset); } /** * Wrap the message to follow the RFC 2822 - 2.1.1 * * @param string $message Message to wrap * @param int $wrapLength The line length * @return array Wrapped message */ protected function _wrap($message, $wrapLength = CakeEmail::LINE_LENGTH_MUST) { if (strlen($message) === 0) { return array(''); } $message = str_replace(array("\r\n", "\r"), "\n", $message); $lines = explode("\n", $message); $formatted = array(); $cut = ($wrapLength == CakeEmail::LINE_LENGTH_MUST); foreach ($lines as $line) { if (empty($line) && $line !== '0') { $formatted[] = ''; continue; } if (strlen($line) < $wrapLength) { $formatted[] = $line; continue; } if (!preg_match('/<[a-z]+.*>/i', $line)) { $formatted = array_merge( $formatted, explode("\n", wordwrap($line, $wrapLength, "\n", $cut)) ); continue; } $tagOpen = false; $tmpLine = $tag = ''; $tmpLineLength = 0; for ($i = 0, $count = strlen($line); $i < $count; $i++) { $char = $line[$i]; if ($tagOpen) { $tag .= $char; if ($char === '>') { $tagLength = strlen($tag); if ($tagLength + $tmpLineLength < $wrapLength) { $tmpLine .= $tag; $tmpLineLength += $tagLength; } else { if ($tmpLineLength > 0) { $formatted = array_merge( $formatted, explode("\n", wordwrap(trim($tmpLine), $wrapLength, "\n", $cut)) ); $tmpLine = ''; $tmpLineLength = 0; } if ($tagLength > $wrapLength) { $formatted[] = $tag; } else { $tmpLine = $tag; $tmpLineLength = $tagLength; } } $tag = ''; $tagOpen = false; } continue; } if ($char === '<') { $tagOpen = true; $tag = '<'; continue; } if ($char === ' ' && $tmpLineLength >= $wrapLength) { $formatted[] = $tmpLine; $tmpLineLength = 0; continue; } $tmpLine .= $char; $tmpLineLength++; if ($tmpLineLength === $wrapLength) { $nextChar = isset($line[$i + 1]) ? $line[$i + 1] : ''; if ($nextChar === ' ' || $nextChar === '<') { $formatted[] = trim($tmpLine); $tmpLine = ''; $tmpLineLength = 0; if ($nextChar === ' ') { $i++; } } else { $lastSpace = strrpos($tmpLine, ' '); if ($lastSpace === false) { continue; } $formatted[] = trim(substr($tmpLine, 0, $lastSpace)); $tmpLine = substr($tmpLine, $lastSpace + 1); $tmpLineLength = strlen($tmpLine); } } } if (!empty($tmpLine)) { $formatted[] = $tmpLine; } } $formatted[] = ''; return $formatted; } /** * Create unique boundary identifier * * @return void */ protected function _createBoundary() { if (!empty($this->_attachments) || $this->_emailFormat === 'both') { $this->_boundary = md5(uniqid(time())); } } /** * Attach non-embedded files by adding file contents inside boundaries. * * @param string $boundary Boundary to use. If null, will default to $this->_boundary * @return array An array of lines to add to the message */ protected function _attachFiles($boundary = null) { if ($boundary === null) { $boundary = $this->_boundary; } $msg = array(); foreach ($this->_attachments as $filename => $fileInfo) { if (!empty($fileInfo['contentId'])) { continue; } $data = isset($fileInfo['data']) ? $fileInfo['data'] : $this->_readFile($fileInfo['file']); $msg[] = '--' . $boundary; $msg[] = 'Content-Type: ' . $fileInfo['mimetype']; $msg[] = 'Content-Transfer-Encoding: base64'; if (!isset($fileInfo['contentDisposition']) || $fileInfo['contentDisposition'] ) { $msg[] = 'Content-Disposition: attachment; filename="' . $filename . '"'; } $msg[] = ''; $msg[] = $data; $msg[] = ''; } return $msg; } /** * Read the file contents and return a base64 version of the file contents. * * @param string $path The absolute path to the file to read. * @return string File contents in base64 encoding */ protected function _readFile($path) { $File = new File($path); return chunk_split(base64_encode($File->read())); } /** * Attach inline/embedded files to the message. * * @param string $boundary Boundary to use. If null, will default to $this->_boundary * @return array An array of lines to add to the message */ protected function _attachInlineFiles($boundary = null) { if ($boundary === null) { $boundary = $this->_boundary; } $msg = array(); foreach ($this->_attachments as $filename => $fileInfo) { if (empty($fileInfo['contentId'])) { continue; } $data = isset($fileInfo['data']) ? $fileInfo['data'] : $this->_readFile($fileInfo['file']); $msg[] = '--' . $boundary; $msg[] = 'Content-Type: ' . $fileInfo['mimetype']; $msg[] = 'Content-Transfer-Encoding: base64'; $msg[] = 'Content-ID: <' . $fileInfo['contentId'] . '>'; $msg[] = 'Content-Disposition: inline; filename="' . $filename . '"'; $msg[] = ''; $msg[] = $data; $msg[] = ''; } return $msg; } /** * Render the body of the email. * * @param array $content Content to render * @return array Email body ready to be sent */ protected function _render($content) { $this->_textMessage = $this->_htmlMessage = ''; $content = implode("\n", $content); $rendered = $this->_renderTemplates($content); $this->_createBoundary(); $msg = array(); $contentIds = array_filter((array)Hash::extract($this->_attachments, '{s}.contentId')); $hasInlineAttachments = count($contentIds) > 0; $hasAttachments = !empty($this->_attachments); $hasMultipleTypes = count($rendered) > 1; $multiPart = ($hasAttachments || $hasMultipleTypes); $boundary = $relBoundary = $textBoundary = $this->_boundary; if ($hasInlineAttachments) { $msg[] = '--' . $boundary; $msg[] = 'Content-Type: multipart/related; boundary="rel-' . $boundary . '"'; $msg[] = ''; $relBoundary = $textBoundary = 'rel-' . $boundary; } if ($hasMultipleTypes && $hasAttachments) { $msg[] = '--' . $relBoundary; $msg[] = 'Content-Type: multipart/alternative; boundary="alt-' . $boundary . '"'; $msg[] = ''; $textBoundary = 'alt-' . $boundary; } if (isset($rendered['text'])) { if ($multiPart) { $msg[] = '--' . $textBoundary; $msg[] = 'Content-Type: text/plain; charset=' . $this->_getContentTypeCharset(); $msg[] = 'Content-Transfer-Encoding: ' . $this->_getContentTransferEncoding(); $msg[] = ''; } $this->_textMessage = $rendered['text']; $content = explode("\n", $this->_textMessage); $msg = array_merge($msg, $content); $msg[] = ''; } if (isset($rendered['html'])) { if ($multiPart) { $msg[] = '--' . $textBoundary; $msg[] = 'Content-Type: text/html; charset=' . $this->_getContentTypeCharset(); $msg[] = 'Content-Transfer-Encoding: ' . $this->_getContentTransferEncoding(); $msg[] = ''; } $this->_htmlMessage = $rendered['html']; $content = explode("\n", $this->_htmlMessage); $msg = array_merge($msg, $content); $msg[] = ''; } if ($textBoundary !== $relBoundary) { $msg[] = '--' . $textBoundary . '--'; $msg[] = ''; } if ($hasInlineAttachments) { $attachments = $this->_attachInlineFiles($relBoundary); $msg = array_merge($msg, $attachments); $msg[] = ''; $msg[] = '--' . $relBoundary . '--'; $msg[] = ''; } if ($hasAttachments) { $attachments = $this->_attachFiles($boundary); $msg = array_merge($msg, $attachments); } if ($hasAttachments || $hasMultipleTypes) { $msg[] = ''; $msg[] = '--' . $boundary . '--'; $msg[] = ''; } return $msg; } /** * Gets the text body types that are in this email message * * @return array Array of types. Valid types are 'text' and 'html' */ protected function _getTypes() { $types = array($this->_emailFormat); if ($this->_emailFormat === 'both') { $types = array('html', 'text'); } return $types; } /** * Build and set all the view properties needed to render the templated emails. * If there is no template set, the $content will be returned in a hash * of the text content types for the email. * * @param string $content The content passed in from send() in most cases. * @return array The rendered content with html and text keys. */ protected function _renderTemplates($content) { $types = $this->_getTypes(); $rendered = array(); if (empty($this->_template)) { foreach ($types as $type) { $rendered[$type] = $this->_encodeString($content, $this->charset); } return $rendered; } $viewClass = $this->_viewRender; if ($viewClass !== 'View') { list($plugin, $viewClass) = pluginSplit($viewClass, true); $viewClass .= 'View'; App::uses($viewClass, $plugin . 'View'); } /** @var View $View */ $View = new $viewClass(null); $View->viewVars = $this->_viewVars; $View->helpers = $this->_helpers; if ($this->_theme) { $View->theme = $this->_theme; } $View->loadHelpers(); list($templatePlugin, $template) = pluginSplit($this->_template); list($layoutPlugin, $layout) = pluginSplit($this->_layout); if ($templatePlugin) { $View->plugin = $templatePlugin; } elseif ($layoutPlugin) { $View->plugin = $layoutPlugin; } if ($View->get('content') === null) { $View->set('content', $content); } // Convert null to false, as View needs false to disable // the layout. if ($this->_layout === null) { $this->_layout = false; } foreach ($types as $type) { $View->hasRendered = false; $View->viewPath = $View->layoutPath = 'Emails' . DS . $type; $render = $View->render($this->_template, $this->_layout); $render = str_replace(array("\r\n", "\r"), "\n", $render); $rendered[$type] = $this->_encodeString($render, $this->charset); } foreach ($rendered as $type => $content) { $rendered[$type] = $this->_wrap($content); $rendered[$type] = implode("\n", $rendered[$type]); $rendered[$type] = rtrim($rendered[$type], "\n"); } return $rendered; } /** * Return the Content-Transfer Encoding value based on the set charset * * @return string */ protected function _getContentTransferEncoding() { $charset = strtoupper($this->charset); if (in_array($charset, $this->_charset8bit)) { return '8bit'; } return '7bit'; } /** * Return charset value for Content-Type. * * Checks fallback/compatibility types which include workarounds * for legacy japanese character sets. * * @return string */ protected function _getContentTypeCharset() { $charset = strtoupper($this->charset); if (array_key_exists($charset, $this->_contentTypeCharset)) { return strtoupper($this->_contentTypeCharset[$charset]); } return strtoupper($this->charset); } } cakephp-2.8.0/lib/Cake/Network/Email/DebugTransport.php000066400000000000000000000025341265552240500227130ustar00rootroot00000000000000getHeaders(array('from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'subject')); $headers = $this->_headersToString($headers); $message = implode("\r\n", (array)$email->message()); return array('headers' => $headers, 'message' => $message); } } cakephp-2.8.0/lib/Cake/Network/Email/MailTransport.php000066400000000000000000000055011265552240500225440ustar00rootroot00000000000000_config['eol'])) { $eol = $this->_config['eol']; } $headers = $email->getHeaders(array('from', 'sender', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc')); $to = $headers['To']; unset($headers['To']); foreach ($headers as $key => $header) { $headers[$key] = str_replace(array("\r", "\n"), '', $header); } $headers = $this->_headersToString($headers, $eol); $subject = str_replace(array("\r", "\n"), '', $email->subject()); $to = str_replace(array("\r", "\n"), '', $to); $message = implode($eol, $email->message()); $params = isset($this->_config['additionalParameters']) ? $this->_config['additionalParameters'] : null; $this->_mail($to, $subject, $message, $headers, $params); return array('headers' => $headers, 'message' => $message); } /** * Wraps internal function mail() and throws exception instead of errors if anything goes wrong * * @param string $to email's recipient * @param string $subject email's subject * @param string $message email's body * @param string $headers email's custom headers * @param string $params additional params for sending email, will be ignored when in safe_mode * @throws SocketException if mail could not be sent * @return void */ protected function _mail($to, $subject, $message, $headers, $params = null) { if (ini_get('safe_mode')) { //@codingStandardsIgnoreStart if (!@mail($to, $subject, $message, $headers)) { $error = error_get_last(); $msg = 'Could not send email: ' . isset($error['message']) ? $error['message'] : 'unknown'; throw new SocketException($msg); } } elseif (!@mail($to, $subject, $message, $headers, $params)) { $error = error_get_last(); $msg = 'Could not send email: ' . isset($error['message']) ? $error['message'] : 'unknown'; //@codingStandardsIgnoreEnd throw new SocketException($msg); } } } cakephp-2.8.0/lib/Cake/Network/Email/SmtpTransport.php000066400000000000000000000217611265552240500226130ustar00rootroot00000000000000 '250', * 'message' => 'mail.example.com' * ), * array( * 'code' => '250', * 'message' => 'PIPELINING' * ), * array( * 'code' => '250', * 'message' => '8BITMIME' * ), * // etc... * ) * ``` * * @return array */ public function getLastResponse() { return $this->_lastResponse; } /** * Send mail * * @param CakeEmail $email CakeEmail * @return array * @throws SocketException */ public function send(CakeEmail $email) { $this->_cakeEmail = $email; $this->_connect(); $this->_auth(); $this->_sendRcpt(); $this->_sendData(); $this->_disconnect(); return $this->_content; } /** * Set the configuration * * @param array $config Configuration options. * @return array Returns configs */ public function config($config = null) { if ($config === null) { return $this->_config; } $default = array( 'host' => 'localhost', 'port' => 25, 'timeout' => 30, 'username' => null, 'password' => null, 'client' => null, 'tls' => false, 'ssl_allow_self_signed' => false ); $this->_config = array_merge($default, $this->_config, $config); return $this->_config; } /** * Parses and stores the reponse lines in `'code' => 'message'` format. * * @param array $responseLines Response lines to parse. * @return void */ protected function _bufferResponseLines(array $responseLines) { $response = array(); foreach ($responseLines as $responseLine) { if (preg_match('/^(\d{3})(?:[ -]+(.*))?$/', $responseLine, $match)) { $response[] = array( 'code' => $match[1], 'message' => isset($match[2]) ? $match[2] : null ); } } $this->_lastResponse = array_merge($this->_lastResponse, $response); } /** * Connect to SMTP Server * * @return void * @throws SocketException */ protected function _connect() { $this->_generateSocket(); if (!$this->_socket->connect()) { throw new SocketException(__d('cake_dev', 'Unable to connect to SMTP server.')); } $this->_smtpSend(null, '220'); if (isset($this->_config['client'])) { $host = $this->_config['client']; } elseif ($httpHost = env('HTTP_HOST')) { list($host) = explode(':', $httpHost); } else { $host = 'localhost'; } try { $this->_smtpSend("EHLO {$host}", '250'); if ($this->_config['tls']) { $this->_smtpSend("STARTTLS", '220'); $this->_socket->enableCrypto('tls'); $this->_smtpSend("EHLO {$host}", '250'); } } catch (SocketException $e) { if ($this->_config['tls']) { throw new SocketException(__d('cake_dev', 'SMTP server did not accept the connection or trying to connect to non TLS SMTP server using TLS.')); } try { $this->_smtpSend("HELO {$host}", '250'); } catch (SocketException $e2) { throw new SocketException(__d('cake_dev', 'SMTP server did not accept the connection.')); } } } /** * Send authentication * * @return void * @throws SocketException */ protected function _auth() { if (isset($this->_config['username']) && isset($this->_config['password'])) { $replyCode = $this->_smtpSend('AUTH LOGIN', '334|500|502|504'); if ($replyCode == '334') { try { $this->_smtpSend(base64_encode($this->_config['username']), '334'); } catch (SocketException $e) { throw new SocketException(__d('cake_dev', 'SMTP server did not accept the username.')); } try { $this->_smtpSend(base64_encode($this->_config['password']), '235'); } catch (SocketException $e) { throw new SocketException(__d('cake_dev', 'SMTP server did not accept the password.')); } } elseif ($replyCode == '504') { throw new SocketException(__d('cake_dev', 'SMTP authentication method not allowed, check if SMTP server requires TLS.')); } else { throw new SocketException(__d('cake_dev', 'AUTH command not recognized or not implemented, SMTP server may not require authentication.')); } } } /** * Prepares the `MAIL FROM` SMTP command. * * @param string $email The email address to send with the command. * @return string */ protected function _prepareFromCmd($email) { return 'MAIL FROM:<' . $email . '>'; } /** * Prepares the `RCPT TO` SMTP command. * * @param string $email The email address to send with the command. * @return string */ protected function _prepareRcptCmd($email) { return 'RCPT TO:<' . $email . '>'; } /** * Prepares the `from` email address. * * @return array */ protected function _prepareFromAddress() { $from = $this->_cakeEmail->returnPath(); if (empty($from)) { $from = $this->_cakeEmail->from(); } return $from; } /** * Prepares the recipient email addresses. * * @return array */ protected function _prepareRecipientAddresses() { $to = $this->_cakeEmail->to(); $cc = $this->_cakeEmail->cc(); $bcc = $this->_cakeEmail->bcc(); return array_merge(array_keys($to), array_keys($cc), array_keys($bcc)); } /** * Prepares the message headers. * * @return array */ protected function _prepareMessageHeaders() { return $this->_cakeEmail->getHeaders(array('from', 'sender', 'replyTo', 'readReceipt', 'to', 'cc', 'subject')); } /** * Prepares the message body. * * @return string */ protected function _prepareMessage() { $lines = $this->_cakeEmail->message(); $messages = array(); foreach ($lines as $line) { if ((!empty($line)) && ($line[0] === '.')) { $messages[] = '.' . $line; } else { $messages[] = $line; } } return implode("\r\n", $messages); } /** * Send emails * * @return void * @throws SocketException */ protected function _sendRcpt() { $from = $this->_prepareFromAddress(); $this->_smtpSend($this->_prepareFromCmd(key($from))); $emails = $this->_prepareRecipientAddresses(); foreach ($emails as $email) { $this->_smtpSend($this->_prepareRcptCmd($email)); } } /** * Send Data * * @return void * @throws SocketException */ protected function _sendData() { $this->_smtpSend('DATA', '354'); $headers = $this->_headersToString($this->_prepareMessageHeaders()); $message = $this->_prepareMessage(); $this->_smtpSend($headers . "\r\n\r\n" . $message . "\r\n\r\n\r\n."); $this->_content = array('headers' => $headers, 'message' => $message); } /** * Disconnect * * @return void * @throws SocketException */ protected function _disconnect() { $this->_smtpSend('QUIT', false); $this->_socket->disconnect(); } /** * Helper method to generate socket * * @return void * @throws SocketException */ protected function _generateSocket() { $this->_socket = new CakeSocket($this->_config); } /** * Protected method for sending data to SMTP connection * * @param string|null $data Data to be sent to SMTP server * @param string|bool $checkCode Code to check for in server response, false to skip * @return string|null The matched code, or null if nothing matched * @throws SocketException */ protected function _smtpSend($data, $checkCode = '250') { $this->_lastResponse = array(); if ($data !== null) { $this->_socket->write($data . "\r\n"); } while ($checkCode !== false) { $response = ''; $startTime = time(); while (substr($response, -2) !== "\r\n" && ((time() - $startTime) < $this->_config['timeout'])) { $response .= $this->_socket->read(); } if (substr($response, -2) !== "\r\n") { throw new SocketException(__d('cake_dev', 'SMTP timeout.')); } $responseLines = explode("\r\n", rtrim($response, "\r\n")); $response = end($responseLines); $this->_bufferResponseLines($responseLines); if (preg_match('/^(' . $checkCode . ')(.)/', $response, $code)) { if ($code[2] === '-') { continue; } return $code[1]; } throw new SocketException(__d('cake_dev', 'SMTP Error: %s', $response)); } } } cakephp-2.8.0/lib/Cake/Network/Http/000077500000000000000000000000001265552240500171235ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Network/Http/BasicAuthentication.php000066400000000000000000000035571265552240500235670ustar00rootroot00000000000000request['header']['Authorization'] = static::_generateHeader($authInfo['user'], $authInfo['pass']); } } /** * Proxy Authentication * * @param HttpSocket $http Http socket instance. * @param array &$proxyInfo Proxy info. * @return void * @see http://www.ietf.org/rfc/rfc2617.txt */ public static function proxyAuthentication(HttpSocket $http, &$proxyInfo) { if (isset($proxyInfo['user'], $proxyInfo['pass'])) { $http->request['header']['Proxy-Authorization'] = static::_generateHeader($proxyInfo['user'], $proxyInfo['pass']); } } /** * Generate basic [proxy] authentication header * * @param string $user Username. * @param string $pass Password. * @return string */ protected static function _generateHeader($user, $pass) { return 'Basic ' . base64_encode($user . ':' . $pass); } } cakephp-2.8.0/lib/Cake/Network/Http/DigestAuthentication.php000066400000000000000000000065611265552240500237630ustar00rootroot00000000000000request['header']['Authorization'] = static::_generateHeader($http, $authInfo); } } /** * Retrieve information about the authentication * * @param HttpSocket $http Http socket instance. * @param array &$authInfo Authentication info. * @return bool */ protected static function _getServerInformation(HttpSocket $http, &$authInfo) { $originalRequest = $http->request; $http->configAuth(false); $http->request($http->request); $http->request = $originalRequest; $http->configAuth('Digest', $authInfo); if (empty($http->response['header']['WWW-Authenticate'])) { return false; } preg_match_all('@(\w+)=(?:(?:")([^"]+)"|([^\s,$]+))@', $http->response['header']['WWW-Authenticate'], $matches, PREG_SET_ORDER); foreach ($matches as $match) { $authInfo[$match[1]] = $match[2]; } if (!empty($authInfo['qop']) && empty($authInfo['nc'])) { $authInfo['nc'] = 1; } return true; } /** * Generate the header Authorization * * @param HttpSocket $http Http socket instance. * @param array &$authInfo Authentication info. * @return string */ protected static function _generateHeader(HttpSocket $http, &$authInfo) { $a1 = md5($authInfo['user'] . ':' . $authInfo['realm'] . ':' . $authInfo['pass']); $a2 = md5($http->request['method'] . ':' . $http->request['uri']['path']); if (empty($authInfo['qop'])) { $response = md5($a1 . ':' . $authInfo['nonce'] . ':' . $a2); } else { $authInfo['cnonce'] = uniqid(); $nc = sprintf('%08x', $authInfo['nc']++); $response = md5($a1 . ':' . $authInfo['nonce'] . ':' . $nc . ':' . $authInfo['cnonce'] . ':auth:' . $a2); } $authHeader = 'Digest '; $authHeader .= 'username="' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $authInfo['user']) . '", '; $authHeader .= 'realm="' . $authInfo['realm'] . '", '; $authHeader .= 'nonce="' . $authInfo['nonce'] . '", '; $authHeader .= 'uri="' . $http->request['uri']['path'] . '", '; $authHeader .= 'response="' . $response . '"'; if (!empty($authInfo['opaque'])) { $authHeader .= ', opaque="' . $authInfo['opaque'] . '"'; } if (!empty($authInfo['qop'])) { $authHeader .= ', qop="auth", nc=' . $nc . ', cnonce="' . $authInfo['cnonce'] . '"'; } return $authHeader; } } cakephp-2.8.0/lib/Cake/Network/Http/HttpResponse.php000066400000000000000000000021051265552240500222700ustar00rootroot00000000000000 'GET', 'uri' => array( 'scheme' => 'http', 'host' => null, 'port' => 80, 'user' => null, 'pass' => null, 'path' => null, 'query' => null, 'fragment' => null ), 'version' => '1.1', 'body' => '', 'line' => null, 'header' => array( 'Connection' => 'close', 'User-Agent' => 'CakePHP' ), 'raw' => null, 'redirect' => false, 'cookies' => array(), ); /** * Contain information about the last response (read only) * * @var array */ public $response = null; /** * Response class name * * @var string */ public $responseClass = 'HttpSocketResponse'; /** * Configuration settings for the HttpSocket and the requests * * @var array */ public $config = array( 'persistent' => false, 'host' => 'localhost', 'protocol' => 'tcp', 'port' => 80, 'timeout' => 30, 'ssl_verify_peer' => true, 'ssl_allow_self_signed' => false, 'ssl_verify_depth' => 5, 'ssl_verify_host' => true, 'request' => array( 'uri' => array( 'scheme' => array('http', 'https'), 'host' => 'localhost', 'port' => array(80, 443) ), 'redirect' => false, 'cookies' => array(), ) ); /** * Authentication settings * * @var array */ protected $_auth = array(); /** * Proxy settings * * @var array */ protected $_proxy = array(); /** * Resource to receive the content of request * * @var mixed */ protected $_contentResource = null; /** * Build an HTTP Socket using the specified configuration. * * You can use a URL string to set the URL and use default configurations for * all other options: * * `$http = new HttpSocket('http://cakephp.org/');` * * Or use an array to configure multiple options: * * ``` * $http = new HttpSocket(array( * 'host' => 'cakephp.org', * 'timeout' => 20 * )); * ``` * * See HttpSocket::$config for options that can be used. * * @param string|array $config Configuration information, either a string URL or an array of options. */ public function __construct($config = array()) { if (is_string($config)) { $this->_configUri($config); } elseif (is_array($config)) { if (isset($config['request']['uri']) && is_string($config['request']['uri'])) { $this->_configUri($config['request']['uri']); unset($config['request']['uri']); } $this->config = Hash::merge($this->config, $config); } parent::__construct($this->config); } /** * Set authentication settings. * * Accepts two forms of parameters. If all you need is a username + password, as with * Basic authentication you can do the following: * * ``` * $http->configAuth('Basic', 'mark', 'secret'); * ``` * * If you are using an authentication strategy that requires more inputs, like Digest authentication * you can call `configAuth()` with an array of user information. * * ``` * $http->configAuth('Digest', array( * 'user' => 'mark', * 'pass' => 'secret', * 'realm' => 'my-realm', * 'nonce' => 1235 * )); * ``` * * To remove any set authentication strategy, call `configAuth()` with no parameters: * * `$http->configAuth();` * * @param string $method Authentication method (ie. Basic, Digest). If empty, disable authentication * @param string|array $user Username for authentication. Can be an array with settings to authentication class * @param string $pass Password for authentication * @return void */ public function configAuth($method, $user = null, $pass = null) { if (empty($method)) { $this->_auth = array(); return; } if (is_array($user)) { $this->_auth = array($method => $user); return; } $this->_auth = array($method => compact('user', 'pass')); } /** * Set proxy settings * * @param string|array $host Proxy host. Can be an array with settings to authentication class * @param int $port Port. Default 3128. * @param string $method Proxy method (ie, Basic, Digest). If empty, disable proxy authentication * @param string $user Username if your proxy need authentication * @param string $pass Password to proxy authentication * @return void */ public function configProxy($host, $port = 3128, $method = null, $user = null, $pass = null) { if (empty($host)) { $this->_proxy = array(); return; } if (is_array($host)) { $this->_proxy = $host + array('host' => null); return; } $this->_proxy = compact('host', 'port', 'method', 'user', 'pass'); } /** * Set the resource to receive the request content. This resource must support fwrite. * * @param resource|bool $resource Resource or false to disable the resource use * @return void * @throws SocketException */ public function setContentResource($resource) { if ($resource === false) { $this->_contentResource = null; return; } if (!is_resource($resource)) { throw new SocketException(__d('cake_dev', 'Invalid resource.')); } $this->_contentResource = $resource; } /** * Issue the specified request. HttpSocket::get() and HttpSocket::post() wrap this * method and provide a more granular interface. * * @param string|array $request Either an URI string, or an array defining host/uri * @return mixed false on error, HttpSocketResponse on success * @throws SocketException */ public function request($request = array()) { $this->reset(false); if (is_string($request)) { $request = array('uri' => $request); } elseif (!is_array($request)) { return false; } if (!isset($request['uri'])) { $request['uri'] = null; } $uri = $this->_parseUri($request['uri']); if (!isset($uri['host'])) { $host = $this->config['host']; } if (isset($request['host'])) { $host = $request['host']; unset($request['host']); } $request['uri'] = $this->url($request['uri']); $request['uri'] = $this->_parseUri($request['uri'], true); $this->request = Hash::merge($this->request, array_diff_key($this->config['request'], array('cookies' => true)), $request); $this->_configUri($this->request['uri']); $Host = $this->request['uri']['host']; if (!empty($this->config['request']['cookies'][$Host])) { if (!isset($this->request['cookies'])) { $this->request['cookies'] = array(); } if (!isset($request['cookies'])) { $request['cookies'] = array(); } $this->request['cookies'] = array_merge($this->request['cookies'], $this->config['request']['cookies'][$Host], $request['cookies']); } if (isset($host)) { $this->config['host'] = $host; } $this->_setProxy(); $this->request['proxy'] = $this->_proxy; $cookies = null; if (is_array($this->request['header'])) { if (!empty($this->request['cookies'])) { $cookies = $this->buildCookies($this->request['cookies']); } $scheme = ''; $port = 0; if (isset($this->request['uri']['scheme'])) { $scheme = $this->request['uri']['scheme']; } if (isset($this->request['uri']['port'])) { $port = $this->request['uri']['port']; } if (($scheme === 'http' && $port != 80) || ($scheme === 'https' && $port != 443) || ($port != 80 && $port != 443) ) { $Host .= ':' . $port; } $this->request['header'] = array_merge(compact('Host'), $this->request['header']); } if (isset($this->request['uri']['user'], $this->request['uri']['pass'])) { $this->configAuth('Basic', $this->request['uri']['user'], $this->request['uri']['pass']); } elseif (isset($this->request['auth'], $this->request['auth']['method'], $this->request['auth']['user'], $this->request['auth']['pass'])) { $this->configAuth($this->request['auth']['method'], $this->request['auth']['user'], $this->request['auth']['pass']); } $authHeader = Hash::get($this->request, 'header.Authorization'); if (empty($authHeader)) { $this->_setAuth(); $this->request['auth'] = $this->_auth; } if (is_array($this->request['body'])) { $this->request['body'] = http_build_query($this->request['body'], '', '&'); } if (!empty($this->request['body']) && !isset($this->request['header']['Content-Type'])) { $this->request['header']['Content-Type'] = 'application/x-www-form-urlencoded'; } if (!empty($this->request['body']) && !isset($this->request['header']['Content-Length'])) { $this->request['header']['Content-Length'] = strlen($this->request['body']); } if (isset($this->request['uri']['scheme']) && $this->request['uri']['scheme'] === 'https' && in_array($this->config['protocol'], array(false, 'tcp'))) { $this->config['protocol'] = 'ssl'; } $connectionType = null; if (isset($this->request['header']['Connection'])) { $connectionType = $this->request['header']['Connection']; } $this->request['header'] = $this->_buildHeader($this->request['header']) . $cookies; if (empty($this->request['line'])) { $this->request['line'] = $this->_buildRequestLine($this->request); } if ($this->quirksMode === false && $this->request['line'] === false) { return false; } $this->request['raw'] = ''; if ($this->request['line'] !== false) { $this->request['raw'] = $this->request['line']; } if ($this->request['header'] !== false) { $this->request['raw'] .= $this->request['header']; } $this->request['raw'] .= "\r\n"; $this->request['raw'] .= $this->request['body']; // SSL context is set during the connect() method. $this->write($this->request['raw']); $response = null; $inHeader = true; while (($data = $this->read()) !== false) { if ($this->_contentResource) { if ($inHeader) { $response .= $data; $pos = strpos($response, "\r\n\r\n"); if ($pos !== false) { $pos += 4; $data = substr($response, $pos); fwrite($this->_contentResource, $data); $response = substr($response, 0, $pos); $inHeader = false; } } else { fwrite($this->_contentResource, $data); fflush($this->_contentResource); } } else { $response .= $data; } } if ($connectionType === 'close') { $this->disconnect(); } list($plugin, $responseClass) = pluginSplit($this->responseClass, true); App::uses($responseClass, $plugin . 'Network/Http'); if (!class_exists($responseClass)) { throw new SocketException(__d('cake_dev', 'Class %s not found.', $this->responseClass)); } $this->response = new $responseClass($response); if (!empty($this->response->cookies)) { if (!isset($this->config['request']['cookies'][$Host])) { $this->config['request']['cookies'][$Host] = array(); } $this->config['request']['cookies'][$Host] = array_merge($this->config['request']['cookies'][$Host], $this->response->cookies); } if ($this->request['redirect'] && $this->response->isRedirect()) { $location = trim($this->response->getHeader('Location'), '='); $request['uri'] = str_replace('%2F', '/', $location); $request['redirect'] = is_int($this->request['redirect']) ? $this->request['redirect'] - 1 : $this->request['redirect']; $this->response = $this->request($request); } return $this->response; } /** * Issues a GET request to the specified URI, query, and request. * * Using a string uri and an array of query string parameters: * * `$response = $http->get('http://google.com/search', array('q' => 'cakephp', 'client' => 'safari'));` * * Would do a GET request to `http://google.com/search?q=cakephp&client=safari` * * You could express the same thing using a uri array and query string parameters: * * ``` * $response = $http->get( * array('host' => 'google.com', 'path' => '/search'), * array('q' => 'cakephp', 'client' => 'safari') * ); * ``` * * @param string|array $uri URI to request. Either a string uri, or a uri array, see HttpSocket::_parseUri() * @param array $query Querystring parameters to append to URI * @param array $request An indexed array with indexes such as 'method' or uri * @return mixed Result of request, either false on failure or the response to the request. */ public function get($uri = null, $query = array(), $request = array()) { if (!empty($query)) { $uri = $this->_parseUri($uri, $this->config['request']['uri']); if (isset($uri['query'])) { $uri['query'] = array_merge($uri['query'], $query); } else { $uri['query'] = $query; } $uri = $this->_buildUri($uri); } $request = Hash::merge(array('method' => 'GET', 'uri' => $uri), $request); return $this->request($request); } /** * Issues a HEAD request to the specified URI, query, and request. * * By definition HEAD request are identical to GET request except they return no response body. This means that all * information and examples relevant to GET also applys to HEAD. * * @param string|array $uri URI to request. Either a string URI, or a URI array, see HttpSocket::_parseUri() * @param array $query Querystring parameters to append to URI * @param array $request An indexed array with indexes such as 'method' or uri * @return mixed Result of request, either false on failure or the response to the request. */ public function head($uri = null, $query = array(), $request = array()) { if (!empty($query)) { $uri = $this->_parseUri($uri, $this->config['request']['uri']); if (isset($uri['query'])) { $uri['query'] = array_merge($uri['query'], $query); } else { $uri['query'] = $query; } $uri = $this->_buildUri($uri); } $request = Hash::merge(array('method' => 'HEAD', 'uri' => $uri), $request); return $this->request($request); } /** * Issues a POST request to the specified URI, query, and request. * * `post()` can be used to post simple data arrays to a URL: * * ``` * $response = $http->post('http://example.com', array( * 'username' => 'batman', * 'password' => 'bruce_w4yne' * )); * ``` * * @param string|array $uri URI to request. See HttpSocket::_parseUri() * @param array $data Array of request body data keys and values. * @param array $request An indexed array with indexes such as 'method' or uri * @return mixed Result of request, either false on failure or the response to the request. */ public function post($uri = null, $data = array(), $request = array()) { $request = Hash::merge(array('method' => 'POST', 'uri' => $uri, 'body' => $data), $request); return $this->request($request); } /** * Issues a PUT request to the specified URI, query, and request. * * @param string|array $uri URI to request, See HttpSocket::_parseUri() * @param array $data Array of request body data keys and values. * @param array $request An indexed array with indexes such as 'method' or uri * @return mixed Result of request */ public function put($uri = null, $data = array(), $request = array()) { $request = Hash::merge(array('method' => 'PUT', 'uri' => $uri, 'body' => $data), $request); return $this->request($request); } /** * Issues a PATCH request to the specified URI, query, and request. * * @param string|array $uri URI to request, See HttpSocket::_parseUri() * @param array $data Array of request body data keys and values. * @param array $request An indexed array with indexes such as 'method' or uri * @return mixed Result of request */ public function patch($uri = null, $data = array(), $request = array()) { $request = Hash::merge(array('method' => 'PATCH', 'uri' => $uri, 'body' => $data), $request); return $this->request($request); } /** * Issues a DELETE request to the specified URI, query, and request. * * @param string|array $uri URI to request (see {@link _parseUri()}) * @param array $data Array of request body data keys and values. * @param array $request An indexed array with indexes such as 'method' or uri * @return mixed Result of request */ public function delete($uri = null, $data = array(), $request = array()) { $request = Hash::merge(array('method' => 'DELETE', 'uri' => $uri, 'body' => $data), $request); return $this->request($request); } /** * Normalizes URLs into a $uriTemplate. If no template is provided * a default one will be used. Will generate the URL using the * current config information. * * ### Usage: * * After configuring part of the request parameters, you can use url() to generate * URLs. * * ``` * $http = new HttpSocket('http://www.cakephp.org'); * $url = $http->url('/search?q=bar'); * ``` * * Would return `http://www.cakephp.org/search?q=bar` * * url() can also be used with custom templates: * * `$url = $http->url('http://www.cakephp/search?q=socket', '/%path?%query');` * * Would return `/search?q=socket`. * * @param string|array $url Either a string or array of URL options to create a URL with. * @param string $uriTemplate A template string to use for URL formatting. * @return mixed Either false on failure or a string containing the composed URL. */ public function url($url = null, $uriTemplate = null) { if ($url === null) { $url = '/'; } if (is_string($url)) { $scheme = $this->config['request']['uri']['scheme']; if (is_array($scheme)) { $scheme = $scheme[0]; } $port = $this->config['request']['uri']['port']; if (is_array($port)) { $port = $port[0]; } if ($url{0} === '/') { $url = $this->config['request']['uri']['host'] . ':' . $port . $url; } if (!preg_match('/^.+:\/\/|\*|^\//', $url)) { $url = $scheme . '://' . $url; } } elseif (!is_array($url) && !empty($url)) { return false; } $base = array_merge($this->config['request']['uri'], array('scheme' => array('http', 'https'), 'port' => array(80, 443))); $url = $this->_parseUri($url, $base); if (empty($url)) { $url = $this->config['request']['uri']; } if (!empty($uriTemplate)) { return $this->_buildUri($url, $uriTemplate); } return $this->_buildUri($url); } /** * Set authentication in request * * @return void * @throws SocketException */ protected function _setAuth() { if (empty($this->_auth)) { return; } $method = key($this->_auth); list($plugin, $authClass) = pluginSplit($method, true); $authClass = Inflector::camelize($authClass) . 'Authentication'; App::uses($authClass, $plugin . 'Network/Http'); if (!class_exists($authClass)) { throw new SocketException(__d('cake_dev', 'Unknown authentication method.')); } if (!method_exists($authClass, 'authentication')) { throw new SocketException(__d('cake_dev', 'The %s does not support authentication.', $authClass)); } call_user_func_array("$authClass::authentication", array($this, &$this->_auth[$method])); } /** * Set the proxy configuration and authentication * * @return void * @throws SocketException */ protected function _setProxy() { if (empty($this->_proxy) || !isset($this->_proxy['host'], $this->_proxy['port'])) { return; } $this->config['host'] = $this->_proxy['host']; $this->config['port'] = $this->_proxy['port']; $this->config['proxy'] = true; if (empty($this->_proxy['method']) || !isset($this->_proxy['user'], $this->_proxy['pass'])) { return; } list($plugin, $authClass) = pluginSplit($this->_proxy['method'], true); $authClass = Inflector::camelize($authClass) . 'Authentication'; App::uses($authClass, $plugin . 'Network/Http'); if (!class_exists($authClass)) { throw new SocketException(__d('cake_dev', 'Unknown authentication method for proxy.')); } if (!method_exists($authClass, 'proxyAuthentication')) { throw new SocketException(__d('cake_dev', 'The %s does not support proxy authentication.', $authClass)); } call_user_func_array("$authClass::proxyAuthentication", array($this, &$this->_proxy)); if (!empty($this->request['header']['Proxy-Authorization'])) { $this->config['proxyauth'] = $this->request['header']['Proxy-Authorization']; if ($this->request['uri']['scheme'] === 'https') { $this->request['header'] = Hash::remove($this->request['header'], 'Proxy-Authorization'); } } } /** * Parses and sets the specified URI into current request configuration. * * @param string|array $uri URI, See HttpSocket::_parseUri() * @return bool If uri has merged in config */ protected function _configUri($uri = null) { if (empty($uri)) { return false; } if (is_array($uri)) { $uri = $this->_parseUri($uri); } else { $uri = $this->_parseUri($uri, true); } if (!isset($uri['host'])) { return false; } $config = array( 'request' => array( 'uri' => array_intersect_key($uri, $this->config['request']['uri']) ) ); $this->config = Hash::merge($this->config, $config); $this->config = Hash::merge($this->config, array_intersect_key($this->config['request']['uri'], $this->config)); return true; } /** * Takes a $uri array and turns it into a fully qualified URL string * * @param string|array $uri Either A $uri array, or a request string. Will use $this->config if left empty. * @param string $uriTemplate The Uri template/format to use. * @return mixed A fully qualified URL formatted according to $uriTemplate, or false on failure */ protected function _buildUri($uri = array(), $uriTemplate = '%scheme://%user:%pass@%host:%port/%path?%query#%fragment') { if (is_string($uri)) { $uri = array('host' => $uri); } $uri = $this->_parseUri($uri, true); if (!is_array($uri) || empty($uri)) { return false; } $uri['path'] = preg_replace('/^\//', null, $uri['path']); $uri['query'] = http_build_query($uri['query'], '', '&'); $uri['query'] = rtrim($uri['query'], '='); $stripIfEmpty = array( 'query' => '?%query', 'fragment' => '#%fragment', 'user' => '%user:%pass@', 'host' => '%host:%port/' ); foreach ($stripIfEmpty as $key => $strip) { if (empty($uri[$key])) { $uriTemplate = str_replace($strip, null, $uriTemplate); } } $defaultPorts = array('http' => 80, 'https' => 443); if (array_key_exists($uri['scheme'], $defaultPorts) && $defaultPorts[$uri['scheme']] == $uri['port']) { $uriTemplate = str_replace(':%port', null, $uriTemplate); } foreach ($uri as $property => $value) { $uriTemplate = str_replace('%' . $property, $value, $uriTemplate); } if ($uriTemplate === '/*') { $uriTemplate = '*'; } return $uriTemplate; } /** * Parses the given URI and breaks it down into pieces as an indexed array with elements * such as 'scheme', 'port', 'query'. * * @param string|array $uri URI to parse * @param bool|array $base If true use default URI config, otherwise indexed array to set 'scheme', 'host', 'port', etc. * @return array Parsed URI */ protected function _parseUri($uri = null, $base = array()) { $uriBase = array( 'scheme' => array('http', 'https'), 'host' => null, 'port' => array(80, 443), 'user' => null, 'pass' => null, 'path' => '/', 'query' => null, 'fragment' => null ); if (is_string($uri)) { $uri = parse_url($uri); } if (!is_array($uri) || empty($uri)) { return false; } if ($base === true) { $base = $uriBase; } if (isset($base['port'], $base['scheme']) && is_array($base['port']) && is_array($base['scheme'])) { if (isset($uri['scheme']) && !isset($uri['port'])) { $base['port'] = $base['port'][array_search($uri['scheme'], $base['scheme'])]; } elseif (isset($uri['port']) && !isset($uri['scheme'])) { $base['scheme'] = $base['scheme'][array_search($uri['port'], $base['port'])]; } } if (is_array($base) && !empty($base)) { $uri = array_merge($base, $uri); } if (isset($uri['scheme']) && is_array($uri['scheme'])) { $uri['scheme'] = array_shift($uri['scheme']); } if (isset($uri['port']) && is_array($uri['port'])) { $uri['port'] = array_shift($uri['port']); } if (array_key_exists('query', $uri)) { $uri['query'] = $this->_parseQuery($uri['query']); } if (!array_intersect_key($uriBase, $uri)) { return false; } return $uri; } /** * This function can be thought of as a reverse to PHP5's http_build_query(). It takes a given query string and turns it into an array and * supports nesting by using the php bracket syntax. So this means you can parse queries like: * * - ?key[subKey]=value * - ?key[]=value1&key[]=value2 * * A leading '?' mark in $query is optional and does not effect the outcome of this function. * For the complete capabilities of this implementation take a look at HttpSocketTest::testparseQuery() * * @param string|array $query A query string to parse into an array or an array to return directly "as is" * @return array The $query parsed into a possibly multi-level array. If an empty $query is * given, an empty array is returned. */ protected function _parseQuery($query) { if (is_array($query)) { return $query; } $parsedQuery = array(); if (is_string($query) && !empty($query)) { $query = preg_replace('/^\?/', '', $query); $items = explode('&', $query); foreach ($items as $item) { if (strpos($item, '=') !== false) { list($key, $value) = explode('=', $item, 2); } else { $key = $item; $value = null; } $key = urldecode($key); $value = urldecode($value); if (preg_match_all('/\[([^\[\]]*)\]/iUs', $key, $matches)) { $subKeys = $matches[1]; $rootKey = substr($key, 0, strpos($key, '[')); if (!empty($rootKey)) { array_unshift($subKeys, $rootKey); } $queryNode =& $parsedQuery; foreach ($subKeys as $subKey) { if (!is_array($queryNode)) { $queryNode = array(); } if ($subKey === '') { $queryNode[] = array(); end($queryNode); $subKey = key($queryNode); } $queryNode =& $queryNode[$subKey]; } $queryNode = $value; continue; } if (!isset($parsedQuery[$key])) { $parsedQuery[$key] = $value; } else { $parsedQuery[$key] = (array)$parsedQuery[$key]; $parsedQuery[$key][] = $value; } } } return $parsedQuery; } /** * Builds a request line according to HTTP/1.1 specs. Activate quirks mode to work outside specs. * * @param array $request Needs to contain a 'uri' key. Should also contain a 'method' key, otherwise defaults to GET. * @return string Request line * @throws SocketException */ protected function _buildRequestLine($request = array()) { $asteriskMethods = array('OPTIONS'); if (is_string($request)) { $isValid = preg_match("/(.+) (.+) (.+)\r\n/U", $request, $match); if (!$this->quirksMode && (!$isValid || ($match[2] === '*' && !in_array($match[3], $asteriskMethods)))) { throw new SocketException(__d('cake_dev', 'HttpSocket::_buildRequestLine - Passed an invalid request line string. Activate quirks mode to do this.')); } return $request; } elseif (!is_array($request)) { return false; } elseif (!array_key_exists('uri', $request)) { return false; } $request['uri'] = $this->_parseUri($request['uri']); $request += array('method' => 'GET'); if (!empty($this->_proxy['host']) && $request['uri']['scheme'] !== 'https') { $request['uri'] = $this->_buildUri($request['uri'], '%scheme://%host:%port/%path?%query'); } else { $request['uri'] = $this->_buildUri($request['uri'], '/%path?%query'); } if (!$this->quirksMode && $request['uri'] === '*' && !in_array($request['method'], $asteriskMethods)) { throw new SocketException(__d('cake_dev', 'HttpSocket::_buildRequestLine - The "*" asterisk character is only allowed for the following methods: %s. Activate quirks mode to work outside of HTTP/1.1 specs.', implode(',', $asteriskMethods))); } $version = isset($request['version']) ? $request['version'] : '1.1'; return $request['method'] . ' ' . $request['uri'] . ' HTTP/' . $version . "\r\n"; } /** * Builds the header. * * @param array $header Header to build * @param string $mode Mode * @return string Header built from array */ protected function _buildHeader($header, $mode = 'standard') { if (is_string($header)) { return $header; } elseif (!is_array($header)) { return false; } $fieldsInHeader = array(); foreach ($header as $key => $value) { $lowKey = strtolower($key); if (array_key_exists($lowKey, $fieldsInHeader)) { $header[$fieldsInHeader[$lowKey]] = $value; unset($header[$key]); } else { $fieldsInHeader[$lowKey] = $key; } } $returnHeader = ''; foreach ($header as $field => $contents) { if (is_array($contents) && $mode === 'standard') { $contents = implode(',', $contents); } foreach ((array)$contents as $content) { $contents = preg_replace("/\r\n(?![\t ])/", "\r\n ", $content); $field = $this->_escapeToken($field); $returnHeader .= $field . ': ' . $contents . "\r\n"; } } return $returnHeader; } /** * Builds cookie headers for a request. * * Cookies can either be in the format returned in responses, or * a simple key => value pair. * * @param array $cookies Array of cookies to send with the request. * @return string Cookie header string to be sent with the request. */ public function buildCookies($cookies) { $header = array(); foreach ($cookies as $name => $cookie) { if (is_array($cookie)) { $value = $this->_escapeToken($cookie['value'], array(';')); } else { $value = $this->_escapeToken($cookie, array(';')); } $header[] = $name . '=' . $value; } return $this->_buildHeader(array('Cookie' => implode('; ', $header)), 'pragmatic'); } /** * Escapes a given $token according to RFC 2616 (HTTP 1.1 specs) * * @param string $token Token to escape * @param array $chars Characters to escape * @return string Escaped token */ protected function _escapeToken($token, $chars = null) { $regex = '/([' . implode('', $this->_tokenEscapeChars(true, $chars)) . '])/'; $token = preg_replace($regex, '"\\1"', $token); return $token; } /** * Gets escape chars according to RFC 2616 (HTTP 1.1 specs). * * @param bool $hex true to get them as HEX values, false otherwise * @param array $chars Characters to escape * @return array Escape chars */ protected function _tokenEscapeChars($hex = true, $chars = null) { if (!empty($chars)) { $escape = $chars; } else { $escape = array('"', "(", ")", "<", ">", "@", ",", ";", ":", "\\", "/", "[", "]", "?", "=", "{", "}", " "); for ($i = 0; $i <= 31; $i++) { $escape[] = chr($i); } $escape[] = chr(127); } if (!$hex) { return $escape; } foreach ($escape as $key => $char) { $escape[$key] = '\\x' . str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT); } return $escape; } /** * Resets the state of this HttpSocket instance to it's initial state (before Object::__construct got executed) or does * the same thing partially for the request and the response property only. * * @param bool $full If set to false only HttpSocket::response and HttpSocket::request are reset * @return bool True on success */ public function reset($full = true) { static $initalState = array(); if (empty($initalState)) { $initalState = get_class_vars(__CLASS__); } if (!$full) { $this->request = $initalState['request']; $this->response = $initalState['response']; return true; } parent::reset($initalState); return true; } } cakephp-2.8.0/lib/Cake/Network/Http/HttpSocketResponse.php000066400000000000000000000245671265552240500234610ustar00rootroot00000000000000parseResponse($message); } } /** * Body content * * @return string */ public function body() { return (string)$this->body; } /** * Get header in case insensitive * * @param string $name Header name. * @param array $headers Headers to format. * @return mixed String if header exists or null */ public function getHeader($name, $headers = null) { if (!is_array($headers)) { $headers =& $this->headers; } if (isset($headers[$name])) { return $headers[$name]; } foreach ($headers as $key => $value) { if (strcasecmp($key, $name) === 0) { return $value; } } return null; } /** * If return is 200 (OK) * * @return bool */ public function isOk() { return in_array($this->code, array(200, 201, 202, 203, 204, 205, 206)); } /** * If return is a valid 3xx (Redirection) * * @return bool */ public function isRedirect() { return in_array($this->code, array(301, 302, 303, 307)) && $this->getHeader('Location') !== null; } /** * Parses the given message and breaks it down in parts. * * @param string $message Message to parse * @return void * @throws SocketException */ public function parseResponse($message) { if (!is_string($message)) { throw new SocketException(__d('cake_dev', 'Invalid response.')); } if (!preg_match("/^(.+\r\n)(.*)(?<=\r\n)\r\n/Us", $message, $match)) { throw new SocketException(__d('cake_dev', 'Invalid HTTP response.')); } list(, $statusLine, $header) = $match; $this->raw = $message; $this->body = (string)substr($message, strlen($match[0])); if (preg_match("/(.+) ([0-9]{3})(?:\s+(\w.+))?\s*\r\n/DU", $statusLine, $match)) { $this->httpVersion = $match[1]; $this->code = $match[2]; if (isset($match[3])) { $this->reasonPhrase = $match[3]; } } $this->headers = $this->_parseHeader($header); $transferEncoding = $this->getHeader('Transfer-Encoding'); $decoded = $this->_decodeBody($this->body, $transferEncoding); $this->body = $decoded['body']; if (!empty($decoded['header'])) { $this->headers = $this->_parseHeader($this->_buildHeader($this->headers) . $this->_buildHeader($decoded['header'])); } if (!empty($this->headers)) { $this->cookies = $this->parseCookies($this->headers); } } /** * Generic function to decode a $body with a given $encoding. Returns either an array with the keys * 'body' and 'header' or false on failure. * * @param string $body A string containing the body to decode. * @param string|bool $encoding Can be false in case no encoding is being used, or a string representing the encoding. * @return mixed Array of response headers and body or false. */ protected function _decodeBody($body, $encoding = 'chunked') { if (!is_string($body)) { return false; } if (empty($encoding)) { return array('body' => $body, 'header' => false); } $decodeMethod = '_decode' . Inflector::camelize(str_replace('-', '_', $encoding)) . 'Body'; if (!is_callable(array(&$this, $decodeMethod))) { return array('body' => $body, 'header' => false); } return $this->{$decodeMethod}($body); } /** * Decodes a chunked message $body and returns either an array with the keys 'body' and 'header' or false as * a result. * * @param string $body A string containing the chunked body to decode. * @return mixed Array of response headers and body or false. * @throws SocketException */ protected function _decodeChunkedBody($body) { if (!is_string($body)) { return false; } $decodedBody = null; $chunkLength = null; while ($chunkLength !== 0) { if (!preg_match('/^([0-9a-f]+)[ ]*(?:;(.+)=(.+))?(?:\r\n|\n)/iU', $body, $match)) { // Handle remaining invalid data as one big chunk. preg_match('/^(.*?)\r\n/', $body, $invalidMatch); $length = isset($invalidMatch[1]) ? strlen($invalidMatch[1]) : 0; $match = array( 0 => '', 1 => dechex($length) ); } $chunkSize = 0; $hexLength = 0; if (isset($match[0])) { $chunkSize = $match[0]; } if (isset($match[1])) { $hexLength = $match[1]; } $chunkLength = hexdec($hexLength); $body = substr($body, strlen($chunkSize)); $decodedBody .= substr($body, 0, $chunkLength); if ($chunkLength) { $body = substr($body, $chunkLength + strlen("\r\n")); } } $entityHeader = false; if (!empty($body)) { $entityHeader = $this->_parseHeader($body); } return array('body' => $decodedBody, 'header' => $entityHeader); } /** * Parses an array based header. * * @param array $header Header as an indexed array (field => value) * @return array Parsed header */ protected function _parseHeader($header) { if (is_array($header)) { return $header; } elseif (!is_string($header)) { return false; } preg_match_all("/(.+):(.+)(?:(?_unescapeToken($field); if (!isset($header[$field])) { $header[$field] = $value; } else { $header[$field] = array_merge((array)$header[$field], (array)$value); } } return $header; } /** * Parses cookies in response headers. * * @param array $header Header array containing one ore more 'Set-Cookie' headers. * @return mixed Either false on no cookies, or an array of cookies received. */ public function parseCookies($header) { $cookieHeader = $this->getHeader('Set-Cookie', $header); if (!$cookieHeader) { return false; } $cookies = array(); foreach ((array)$cookieHeader as $cookie) { if (strpos($cookie, '";"') !== false) { $cookie = str_replace('";"', "{__cookie_replace__}", $cookie); $parts = str_replace("{__cookie_replace__}", '";"', explode(';', $cookie)); } else { $parts = preg_split('/\;[ \t]*/', $cookie); } list($name, $value) = explode('=', array_shift($parts), 2); $cookies[$name] = compact('value'); foreach ($parts as $part) { if (strpos($part, '=') !== false) { list($key, $value) = explode('=', $part); } else { $key = $part; $value = true; } $key = strtolower($key); if (!isset($cookies[$name][$key])) { $cookies[$name][$key] = $value; } } } return $cookies; } /** * Unescapes a given $token according to RFC 2616 (HTTP 1.1 specs) * * @param string $token Token to unescape. * @param array $chars Characters to unescape. * @return string Unescaped token */ protected function _unescapeToken($token, $chars = null) { $regex = '/"([' . implode('', $this->_tokenEscapeChars(true, $chars)) . '])"/'; $token = preg_replace($regex, '\\1', $token); return $token; } /** * Gets escape chars according to RFC 2616 (HTTP 1.1 specs). * * @param bool $hex True to get them as HEX values, false otherwise. * @param array $chars Characters to uescape. * @return array Escape chars */ protected function _tokenEscapeChars($hex = true, $chars = null) { if (!empty($chars)) { $escape = $chars; } else { $escape = array('"', "(", ")", "<", ">", "@", ",", ";", ":", "\\", "/", "[", "]", "?", "=", "{", "}", " "); for ($i = 0; $i <= 31; $i++) { $escape[] = chr($i); } $escape[] = chr(127); } if (!$hex) { return $escape; } foreach ($escape as $key => $char) { $escape[$key] = '\\x' . str_pad(dechex(ord($char)), 2, '0', STR_PAD_LEFT); } return $escape; } /** * ArrayAccess - Offset Exists * * @param string $offset Offset to check. * @return bool */ public function offsetExists($offset) { return in_array($offset, array('raw', 'status', 'header', 'body', 'cookies')); } /** * ArrayAccess - Offset Get * * @param string $offset Offset to get. * @return mixed */ public function offsetGet($offset) { switch ($offset) { case 'raw': $firstLineLength = strpos($this->raw, "\r\n") + 2; if ($this->raw[$firstLineLength] === "\r") { $header = null; } else { $header = substr($this->raw, $firstLineLength, strpos($this->raw, "\r\n\r\n") - $firstLineLength) . "\r\n"; } return array( 'status-line' => $this->httpVersion . ' ' . $this->code . ' ' . $this->reasonPhrase . "\r\n", 'header' => $header, 'body' => $this->body, 'response' => $this->raw ); case 'status': return array( 'http-version' => $this->httpVersion, 'code' => $this->code, 'reason-phrase' => $this->reasonPhrase ); case 'header': return $this->headers; case 'body': return $this->body; case 'cookies': return $this->cookies; } return null; } /** * ArrayAccess - Offset Set * * @param string $offset Offset to set. * @param mixed $value Value. * @return void */ public function offsetSet($offset, $value) { } /** * ArrayAccess - Offset Unset * * @param string $offset Offset to unset. * @return void */ public function offsetUnset($offset) { } /** * Instance as string * * @return string */ public function __toString() { return $this->body(); } } cakephp-2.8.0/lib/Cake/Routing/000077500000000000000000000000001265552240500162025ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Routing/Dispatcher.php000066400000000000000000000221471265552240500210070ustar00rootroot00000000000000_eventManager) { $this->_eventManager = new CakeEventManager(); $this->_eventManager->attach($this); $this->_attachFilters($this->_eventManager); } return $this->_eventManager; } /** * Returns the list of events this object listens to. * * @return array */ public function implementedEvents() { return array('Dispatcher.beforeDispatch' => 'parseParams'); } /** * Attaches all event listeners for this dispatcher instance. Loads the * dispatcher filters from the configured locations. * * @param CakeEventManager $manager Event manager instance. * @return void * @throws MissingDispatcherFilterException */ protected function _attachFilters($manager) { $filters = Configure::read('Dispatcher.filters'); if (empty($filters)) { return; } foreach ($filters as $index => $filter) { $settings = array(); if (is_array($filter) && !is_int($index) && class_exists($index)) { $settings = $filter; $filter = $index; } if (is_string($filter)) { $filter = array('callable' => $filter); } if (is_string($filter['callable'])) { list($plugin, $callable) = pluginSplit($filter['callable'], true); App::uses($callable, $plugin . 'Routing/Filter'); if (!class_exists($callable)) { throw new MissingDispatcherFilterException($callable); } $manager->attach(new $callable($settings)); } else { $on = strtolower($filter['on']); $options = array(); if (isset($filter['priority'])) { $options = array('priority' => $filter['priority']); } $manager->attach($filter['callable'], 'Dispatcher.' . $on . 'Dispatch', $options); } } } /** * Dispatches and invokes given Request, handing over control to the involved controller. If the controller is set * to autoRender, via Controller::$autoRender, then Dispatcher will render the view. * * Actions in CakePHP can be any public method on a controller, that is not declared in Controller. If you * want controller methods to be public and in-accessible by URL, then prefix them with a `_`. * For example `public function _loadPosts() { }` would not be accessible via URL. Private and protected methods * are also not accessible via URL. * * If no controller of given name can be found, invoke() will throw an exception. * If the controller is found, and the action is not found an exception will be thrown. * * @param CakeRequest $request Request object to dispatch. * @param CakeResponse $response Response object to put the results of the dispatch into. * @param array $additionalParams Settings array ("bare", "return") which is melded with the GET and POST params * @return string|null if `$request['return']` is set then it returns response body, null otherwise * @triggers Dispatcher.beforeDispatch $this, compact('request', 'response', 'additionalParams') * @triggers Dispatcher.afterDispatch $this, compact('request', 'response') * @throws MissingControllerException When the controller is missing. */ public function dispatch(CakeRequest $request, CakeResponse $response, $additionalParams = array()) { $beforeEvent = new CakeEvent('Dispatcher.beforeDispatch', $this, compact('request', 'response', 'additionalParams')); $this->getEventManager()->dispatch($beforeEvent); $request = $beforeEvent->data['request']; if ($beforeEvent->result instanceof CakeResponse) { if (isset($request->params['return'])) { return $beforeEvent->result->body(); } $beforeEvent->result->send(); return null; } $controller = $this->_getController($request, $response); if (!($controller instanceof Controller)) { throw new MissingControllerException(array( 'class' => Inflector::camelize($request->params['controller']) . 'Controller', 'plugin' => empty($request->params['plugin']) ? null : Inflector::camelize($request->params['plugin']) )); } $response = $this->_invoke($controller, $request); if (isset($request->params['return'])) { return $response->body(); } $afterEvent = new CakeEvent('Dispatcher.afterDispatch', $this, compact('request', 'response')); $this->getEventManager()->dispatch($afterEvent); $afterEvent->data['response']->send(); } /** * Initializes the components and models a controller will be using. * Triggers the controller action, and invokes the rendering if Controller::$autoRender * is true and echo's the output. Otherwise the return value of the controller * action are returned. * * @param Controller $controller Controller to invoke * @param CakeRequest $request The request object to invoke the controller for. * @return CakeResponse the resulting response object */ protected function _invoke(Controller $controller, CakeRequest $request) { $controller->constructClasses(); $controller->startupProcess(); $response = $controller->response; $render = true; $result = $controller->invokeAction($request); if ($result instanceof CakeResponse) { $render = false; $response = $result; } if ($render && $controller->autoRender) { $response = $controller->render(); } elseif (!($result instanceof CakeResponse) && $response->body() === null) { $response->body($result); } $controller->shutdownProcess(); return $response; } /** * Applies Routing and additionalParameters to the request to be dispatched. * If Routes have not been loaded they will be loaded, and app/Config/routes.php will be run. * * @param CakeEvent $event containing the request, response and additional params * @return void */ public function parseParams($event) { $request = $event->data['request']; Router::setRequestInfo($request); $params = Router::parse($request->url); $request->addParams($params); if (!empty($event->data['additionalParams'])) { $request->addParams($event->data['additionalParams']); } } /** * Get controller to use, either plugin controller or application controller * * @param CakeRequest $request Request object * @param CakeResponse $response Response for the controller. * @return mixed name of controller if not loaded, or object if loaded */ protected function _getController($request, $response) { $ctrlClass = $this->_loadController($request); if (!$ctrlClass) { return false; } $reflection = new ReflectionClass($ctrlClass); if ($reflection->isAbstract() || $reflection->isInterface()) { return false; } return $reflection->newInstance($request, $response); } /** * Load controller and return controller class name * * @param CakeRequest $request Request instance. * @return string|bool Name of controller class name */ protected function _loadController($request) { $pluginName = $pluginPath = $controller = null; if (!empty($request->params['plugin'])) { $pluginName = $controller = Inflector::camelize($request->params['plugin']); $pluginPath = $pluginName . '.'; } if (!empty($request->params['controller'])) { $controller = Inflector::camelize($request->params['controller']); } if ($pluginPath . $controller) { $class = $controller . 'Controller'; App::uses('AppController', 'Controller'); App::uses($pluginName . 'AppController', $pluginPath . 'Controller'); App::uses($class, $pluginPath . 'Controller'); if (class_exists($class)) { return $class; } } return false; } } cakephp-2.8.0/lib/Cake/Routing/DispatcherFilter.php000066400000000000000000000066661265552240500221650ustar00rootroot00000000000000settings = Hash::merge($this->settings, $settings); } /** * Returns the list of events this filter listens to. * Dispatcher notifies 2 different events `Dispatcher.before` and `Dispatcher.after`. * By default this class will attach `preDispatch` and `postDispatch` method respectively. * * Override this method at will to only listen to the events you are interested in. * * @return array */ public function implementedEvents() { return array( 'Dispatcher.beforeDispatch' => array('callable' => 'beforeDispatch', 'priority' => $this->priority), 'Dispatcher.afterDispatch' => array('callable' => 'afterDispatch', 'priority' => $this->priority), ); } /** * Method called before the controller is instantiated and called to serve a request. * If used with default priority, it will be called after the Router has parsed the * URL and set the routing params into the request object. * * If a CakeResponse object instance is returned, it will be served at the end of the * event cycle, not calling any controller as a result. This will also have the effect of * not calling the after event in the dispatcher. * * If false is returned, the event will be stopped and no more listeners will be notified. * Alternatively you can call `$event->stopPropagation()` to achieve the same result. * * @param CakeEvent $event container object having the `request`, `response` and `additionalParams` * keys in the data property. * @return CakeResponse|bool */ public function beforeDispatch(CakeEvent $event) { } /** * Method called after the controller served a request and generated a response. * It is possible to alter the response object at this point as it is not sent to the * client yet. * * If false is returned, the event will be stopped and no more listeners will be notified. * Alternatively you can call `$event->stopPropagation()` to achieve the same result. * * @param CakeEvent $event container object having the `request` and `response` * keys in the data property. * @return mixed boolean to stop the event dispatching or null to continue */ public function afterDispatch(CakeEvent $event) { } } cakephp-2.8.0/lib/Cake/Routing/Filter/000077500000000000000000000000001265552240500174275ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Routing/Filter/AssetDispatcher.php000066400000000000000000000113051265552240500232260ustar00rootroot00000000000000data['request']->url); if (strpos($url, '..') !== false || strpos($url, '.') === false) { return null; } if ($result = $this->_filterAsset($event)) { $event->stopPropagation(); return $result; } $assetFile = $this->_getAssetFile($url); if ($assetFile === null || !file_exists($assetFile)) { return null; } $response = $event->data['response']; $event->stopPropagation(); $response->modified(filemtime($assetFile)); if ($response->checkNotModified($event->data['request'])) { return $response; } $pathSegments = explode('.', $url); $ext = array_pop($pathSegments); $this->_deliverAsset($response, $assetFile, $ext); return $response; } /** * Checks if the client is requesting a filtered asset and runs the corresponding * filter if any is configured * * @param CakeEvent $event containing the request and response object * @return CakeResponse if the client is requesting a recognized asset, null otherwise */ protected function _filterAsset(CakeEvent $event) { $url = $event->data['request']->url; $response = $event->data['response']; $filters = Configure::read('Asset.filter'); $isCss = ( strpos($url, 'ccss/') === 0 || preg_match('#^(theme/([^/]+)/ccss/)|(([^/]+)(?statusCode(404); return $response; } if ($isCss) { include WWW_ROOT . DS . $filters['css']; return $response; } if ($isJs) { include WWW_ROOT . DS . $filters['js']; return $response; } } /** * Builds asset file path based off url * * @param string $url URL * @return string Absolute path for asset file */ protected function _getAssetFile($url) { $parts = explode('/', $url); if ($parts[0] === 'theme') { $themeName = $parts[1]; unset($parts[0], $parts[1]); $fileFragment = implode(DS, $parts); $path = App::themePath($themeName) . 'webroot' . DS; return $path . $fileFragment; } $plugin = Inflector::camelize($parts[0]); if ($plugin && CakePlugin::loaded($plugin)) { unset($parts[0]); $fileFragment = implode(DS, $parts); $pluginWebroot = CakePlugin::path($plugin) . 'webroot' . DS; return $pluginWebroot . $fileFragment; } } /** * Sends an asset file to the client * * @param CakeResponse $response The response object to use. * @param string $assetFile Path to the asset file in the file system * @param string $ext The extension of the file to determine its mime type * @return void */ protected function _deliverAsset(CakeResponse $response, $assetFile, $ext) { ob_start(); $compressionEnabled = Configure::read('Asset.compress') && $response->compress(); if ($response->type($ext) === $ext) { $contentType = 'application/octet-stream'; $agent = env('HTTP_USER_AGENT'); if (preg_match('%Opera(/| )([0-9].[0-9]{1,2})%', $agent) || preg_match('/MSIE ([0-9].[0-9]{1,2})/', $agent)) { $contentType = 'application/octetstream'; } $response->type($contentType); } $response->length(false); $response->cache(filemtime($assetFile)); $response->send(); ob_clean(); if ($ext === 'css' || $ext === 'js') { include $assetFile; } else { readfile($assetFile); } if ($compressionEnabled) { ob_end_flush(); } } } cakephp-2.8.0/lib/Cake/Routing/Filter/CacheDispatcher.php000066400000000000000000000041251265552240500231540ustar00rootroot00000000000000data['request']->here(); if ($path === '/') { $path = 'home'; } $prefix = Configure::read('Cache.viewPrefix'); if ($prefix) { $path = $prefix . '_' . $path; } $path = strtolower(Inflector::slug($path)); $filename = CACHE . 'views' . DS . $path . '.php'; if (!file_exists($filename)) { $filename = CACHE . 'views' . DS . $path . '_index.php'; } if (file_exists($filename)) { $controller = null; $view = new View($controller); $view->response = $event->data['response']; $result = $view->renderCache($filename, microtime(true)); if ($result !== false) { $event->stopPropagation(); $event->data['response']->body($result); return $event->data['response']; } } } } cakephp-2.8.0/lib/Cake/Routing/Route/000077500000000000000000000000001265552240500173005ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Routing/Route/CakeRoute.php000066400000000000000000000372101265552240500216760ustar00rootroot00000000000000 'content_type', 'method' => 'request_method', 'server' => 'server_name' ); /** * Constructor for a Route * * @param string $template Template string with parameter placeholders * @param array $defaults Array of defaults for the route. * @param array $options Array of additional options for the Route */ public function __construct($template, $defaults = array(), $options = array()) { $this->template = $template; $this->defaults = (array)$defaults; $this->options = (array)$options; } /** * Check if a Route has been compiled into a regular expression. * * @return bool */ public function compiled() { return !empty($this->_compiledRoute); } /** * Compiles the route's regular expression. * * Modifies defaults property so all necessary keys are set * and populates $this->names with the named routing elements. * * @return array Returns a string regular expression of the compiled route. */ public function compile() { if ($this->compiled()) { return $this->_compiledRoute; } $this->_writeRoute(); return $this->_compiledRoute; } /** * Builds a route regular expression. * * Uses the template, defaults and options properties to compile a * regular expression that can be used to parse request strings. * * @return void */ protected function _writeRoute() { if (empty($this->template) || ($this->template === '/')) { $this->_compiledRoute = '#^/*$#'; $this->keys = array(); return; } $route = $this->template; $names = $routeParams = array(); $parsed = preg_quote($this->template, '#'); preg_match_all('#:([A-Za-z0-9_-]+[A-Z0-9a-z])#', $route, $namedElements); foreach ($namedElements[1] as $i => $name) { $search = '\\' . $namedElements[0][$i]; if (isset($this->options[$name])) { $option = null; if ($name !== 'plugin' && array_key_exists($name, $this->defaults)) { $option = '?'; } $slashParam = '/\\' . $namedElements[0][$i]; if (strpos($parsed, $slashParam) !== false) { $routeParams[$slashParam] = '(?:/(?P<' . $name . '>' . $this->options[$name] . ')' . $option . ')' . $option; } else { $routeParams[$search] = '(?:(?P<' . $name . '>' . $this->options[$name] . ')' . $option . ')' . $option; } } else { $routeParams[$search] = '(?:(?P<' . $name . '>[^/]+))'; } $names[] = $name; } if (preg_match('#\/\*\*$#', $route)) { $parsed = preg_replace('#/\\\\\*\\\\\*$#', '(?:/(?P<_trailing_>.*))?', $parsed); $this->_greedy = true; } if (preg_match('#\/\*$#', $route)) { $parsed = preg_replace('#/\\\\\*$#', '(?:/(?P<_args_>.*))?', $parsed); $this->_greedy = true; } krsort($routeParams); $parsed = str_replace(array_keys($routeParams), array_values($routeParams), $parsed); $this->_compiledRoute = '#^' . $parsed . '[/]*$#'; $this->keys = $names; // Remove defaults that are also keys. They can cause match failures foreach ($this->keys as $key) { unset($this->defaults[$key]); } $keys = $this->keys; sort($keys); $this->keys = array_reverse($keys); } /** * Checks to see if the given URL can be parsed by this route. * * If the route can be parsed an array of parameters will be returned; if not * false will be returned. String URLs are parsed if they match a routes regular expression. * * @param string $url The URL to attempt to parse. * @return mixed Boolean false on failure, otherwise an array or parameters */ public function parse($url) { if (!$this->compiled()) { $this->compile(); } if (!preg_match($this->_compiledRoute, urldecode($url), $route)) { return false; } foreach ($this->defaults as $key => $val) { $key = (string)$key; if ($key[0] === '[' && preg_match('/^\[(\w+)\]$/', $key, $header)) { if (isset($this->_headerMap[$header[1]])) { $header = $this->_headerMap[$header[1]]; } else { $header = 'http_' . $header[1]; } $header = strtoupper($header); $val = (array)$val; $h = false; foreach ($val as $v) { if (env($header) === $v) { $h = true; } } if (!$h) { return false; } } } array_shift($route); $count = count($this->keys); for ($i = 0; $i <= $count; $i++) { unset($route[$i]); } $route['pass'] = $route['named'] = array(); // Assign defaults, set passed args to pass foreach ($this->defaults as $key => $value) { if (isset($route[$key])) { continue; } if (is_int($key)) { $route['pass'][] = $value; continue; } $route[$key] = $value; } if (isset($route['_args_'])) { list($pass, $named) = $this->_parseArgs($route['_args_'], $route); $route['pass'] = array_merge($route['pass'], $pass); $route['named'] = $named; unset($route['_args_']); } if (isset($route['_trailing_'])) { $route['pass'][] = $route['_trailing_']; unset($route['_trailing_']); } // restructure 'pass' key route params if (isset($this->options['pass'])) { $j = count($this->options['pass']); while ($j--) { if (isset($route[$this->options['pass'][$j]])) { array_unshift($route['pass'], $route[$this->options['pass'][$j]]); } } } return $route; } /** * Parse passed and Named parameters into a list of passed args, and a hash of named parameters. * The local and global configuration for named parameters will be used. * * @param string $args A string with the passed & named params. eg. /1/page:2 * @param string $context The current route context, which should contain controller/action keys. * @return array Array of ($pass, $named) */ protected function _parseArgs($args, $context) { $pass = $named = array(); $args = explode('/', $args); $namedConfig = Router::namedConfig(); $greedy = $namedConfig['greedyNamed']; $rules = $namedConfig['rules']; if (!empty($this->options['named'])) { $greedy = isset($this->options['greedyNamed']) && $this->options['greedyNamed'] === true; foreach ((array)$this->options['named'] as $key => $val) { if (is_numeric($key)) { $rules[$val] = true; continue; } $rules[$key] = $val; } } foreach ($args as $param) { if (empty($param) && $param !== '0' && $param !== 0) { continue; } $separatorIsPresent = strpos($param, $namedConfig['separator']) !== false; if ((!isset($this->options['named']) || !empty($this->options['named'])) && $separatorIsPresent) { list($key, $val) = explode($namedConfig['separator'], $param, 2); $hasRule = isset($rules[$key]); $passIt = (!$hasRule && !$greedy) || ($hasRule && !$this->_matchNamed($val, $rules[$key], $context)); if ($passIt) { $pass[] = $param; } else { if (preg_match_all('/\[([A-Za-z0-9_-]+)?\]/', $key, $matches, PREG_SET_ORDER)) { $matches = array_reverse($matches); $parts = explode('[', $key); $key = array_shift($parts); $arr = $val; foreach ($matches as $match) { if (empty($match[1])) { $arr = array($arr); } else { $arr = array( $match[1] => $arr ); } } $val = $arr; } $named = array_merge_recursive($named, array($key => $val)); } } else { $pass[] = $param; } } return array($pass, $named); } /** * Check if a named parameter matches the current rules. * * Return true if a given named $param's $val matches a given $rule depending on $context. * Currently implemented rule types are controller, action and match that can be combined with each other. * * @param string $val The value of the named parameter * @param array $rule The rule(s) to apply, can also be a match string * @param string $context An array with additional context information (controller / action) * @return bool */ protected function _matchNamed($val, $rule, $context) { if ($rule === true || $rule === false) { return $rule; } if (is_string($rule)) { $rule = array('match' => $rule); } if (!is_array($rule)) { return false; } $controllerMatches = ( !isset($rule['controller'], $context['controller']) || in_array($context['controller'], (array)$rule['controller']) ); if (!$controllerMatches) { return false; } $actionMatches = ( !isset($rule['action'], $context['action']) || in_array($context['action'], (array)$rule['action']) ); if (!$actionMatches) { return false; } return (!isset($rule['match']) || preg_match('/' . $rule['match'] . '/', $val)); } /** * Apply persistent parameters to a URL array. Persistent parameters are a special * key used during route creation to force route parameters to persist when omitted from * a URL array. * * @param array $url The array to apply persistent parameters to. * @param array $params An array of persistent values to replace persistent ones. * @return array An array with persistent parameters applied. */ public function persistParams($url, $params) { if (empty($this->options['persist']) || !is_array($this->options['persist'])) { return $url; } foreach ($this->options['persist'] as $persistKey) { if (array_key_exists($persistKey, $params) && !isset($url[$persistKey])) { $url[$persistKey] = $params[$persistKey]; } } return $url; } /** * Check if a URL array matches this route instance. * * If the URL matches the route parameters and settings, then * return a generated string URL. If the URL doesn't match the route parameters, false will be returned. * This method handles the reverse routing or conversion of URL arrays into string URLs. * * @param array $url An array of parameters to check matching with. * @return mixed Either a string URL for the parameters if they match or false. */ public function match($url) { if (!$this->compiled()) { $this->compile(); } $defaults = $this->defaults; if (isset($defaults['prefix'])) { $url['prefix'] = $defaults['prefix']; } //check that all the key names are in the url $keyNames = array_flip($this->keys); if (array_intersect_key($keyNames, $url) !== $keyNames) { return false; } // Missing defaults is a fail. if (array_diff_key($defaults, $url) !== array()) { return false; } $namedConfig = Router::namedConfig(); $prefixes = Router::prefixes(); $greedyNamed = $namedConfig['greedyNamed']; $allowedNamedParams = $namedConfig['rules']; $named = $pass = array(); foreach ($url as $key => $value) { // keys that exist in the defaults and have different values is a match failure. $defaultExists = array_key_exists($key, $defaults); if ($defaultExists && $defaults[$key] != $value) { return false; } elseif ($defaultExists) { continue; } // If the key is a routed key, its not different yet. if (array_key_exists($key, $keyNames)) { continue; } // pull out passed args $numeric = is_numeric($key); if ($numeric && isset($defaults[$key]) && $defaults[$key] == $value) { continue; } elseif ($numeric) { $pass[] = $value; unset($url[$key]); continue; } // pull out named params if named params are greedy or a rule exists. if (($greedyNamed || isset($allowedNamedParams[$key])) && ($value !== false && $value !== null) && (!in_array($key, $prefixes)) ) { $named[$key] = $value; continue; } // keys that don't exist are different. if (!$defaultExists && !empty($value)) { return false; } } //if a not a greedy route, no extra params are allowed. if (!$this->_greedy && (!empty($pass) || !empty($named))) { return false; } //check patterns for routed params if (!empty($this->options)) { foreach ($this->options as $key => $pattern) { if (array_key_exists($key, $url) && !preg_match('#^' . $pattern . '$#', $url[$key])) { return false; } } } return $this->_writeUrl(array_merge($url, compact('pass', 'named'))); } /** * Converts a matching route array into a URL string. * * Composes the string URL using the template * used to create the route. * * @param array $params The params to convert to a string URL. * @return string Composed route string. */ protected function _writeUrl($params) { if (isset($params['prefix'])) { $prefixed = $params['prefix'] . '_'; } if (isset($prefixed, $params['action']) && strpos($params['action'], $prefixed) === 0) { $params['action'] = substr($params['action'], strlen($prefixed)); unset($params['prefix']); } if (is_array($params['pass'])) { $params['pass'] = implode('/', array_map('rawurlencode', $params['pass'])); } $namedConfig = Router::namedConfig(); $separator = $namedConfig['separator']; if (!empty($params['named']) && is_array($params['named'])) { $named = array(); foreach ($params['named'] as $key => $value) { if (is_array($value)) { $flat = Hash::flatten($value, '%5D%5B'); foreach ($flat as $namedKey => $namedValue) { $named[] = $key . "%5B{$namedKey}%5D" . $separator . rawurlencode($namedValue); } } else { $named[] = $key . $separator . rawurlencode($value); } } $params['pass'] = $params['pass'] . '/' . implode('/', $named); } $out = $this->template; if (!empty($this->keys)) { $search = $replace = array(); foreach ($this->keys as $key) { $string = null; if (isset($params[$key])) { $string = $params[$key]; } elseif (strpos($out, $key) != strlen($out) - strlen($key)) { $key .= '/'; } $search[] = ':' . $key; $replace[] = $string; } $out = str_replace($search, $replace, $out); } if (strpos($this->template, '**') !== false) { $out = str_replace('**', $params['pass'], $out); $out = str_replace('%2F', '/', $out); } elseif (strpos($this->template, '*') !== false) { $out = str_replace('*', $params['pass'], $out); } $out = str_replace('//', '/', $out); return $out; } /** * Set state magic method to support var_export * * This method helps for applications that want to implement * router caching. * * @param array $fields Key/Value of object attributes * @return CakeRoute A new instance of the route */ public static function __set_state($fields) { $class = function_exists('get_called_class') ? get_called_class() : __CLASS__; $obj = new $class(''); foreach ($fields as $field => $value) { $obj->$field = $value; } return $obj; } } cakephp-2.8.0/lib/Cake/Routing/Route/PluginShortRoute.php000066400000000000000000000034121265552240500233060ustar00rootroot00000000000000defaults['controller'] = $url['controller']; $result = parent::match($url); unset($this->defaults['controller']); return $result; } } cakephp-2.8.0/lib/Cake/Routing/Route/RedirectRoute.php000066400000000000000000000065221265552240500225760ustar00rootroot00000000000000redirect = (array)$defaults; } /** * Parses a string URL into an array. Parsed URLs will result in an automatic * redirection * * @param string $url The URL to parse * @return bool False on failure */ public function parse($url) { $params = parent::parse($url); if (!$params) { return false; } if (!$this->response) { $this->response = new CakeResponse(); } $redirect = $this->redirect; if (count($this->redirect) === 1 && !isset($this->redirect['controller'])) { $redirect = $this->redirect[0]; } if (isset($this->options['persist']) && is_array($redirect)) { $redirect += array('named' => $params['named'], 'pass' => $params['pass'], 'url' => array()); if (is_array($this->options['persist'])) { foreach ($this->options['persist'] as $elem) { if (isset($params[$elem])) { $redirect[$elem] = $params[$elem]; } } } $redirect = Router::reverse($redirect); } $status = 301; if (isset($this->options['status']) && ($this->options['status'] >= 300 && $this->options['status'] < 400)) { $status = $this->options['status']; } $this->response->header(array('Location' => Router::url($redirect, true))); $this->response->statusCode($status); $this->response->send(); $this->_stop(); } /** * There is no reverse routing redirection routes * * @param array $url Array of parameters to convert to a string. * @return mixed either false or a string URL. */ public function match($url) { return false; } /** * Stop execution of the current script. Wraps exit() making * testing easier. * * @param int|string $code See http://php.net/exit for values * @return void */ protected function _stop($code = 0) { if ($this->stop) { exit($code); } } } cakephp-2.8.0/lib/Cake/Routing/Router.php000066400000000000000000001144501265552240500202000ustar00rootroot00000000000000 Router::ACTION, 'Year' => Router::YEAR, 'Month' => Router::MONTH, 'Day' => Router::DAY, 'ID' => Router::ID, 'UUID' => Router::UUID ); /** * Stores all information necessary to decide what named arguments are parsed under what conditions. * * @var string */ protected static $_namedConfig = array( 'default' => array('page', 'fields', 'order', 'limit', 'recursive', 'sort', 'direction', 'step'), 'greedyNamed' => true, 'separator' => ':', 'rules' => false, ); /** * The route matching the URL of the current request * * @var array */ protected static $_currentRoute = array(); /** * Default HTTP request method => controller action map. * * @var array */ protected static $_resourceMap = array( array('action' => 'index', 'method' => 'GET', 'id' => false), array('action' => 'view', 'method' => 'GET', 'id' => true), array('action' => 'add', 'method' => 'POST', 'id' => false), array('action' => 'edit', 'method' => 'PUT', 'id' => true), array('action' => 'delete', 'method' => 'DELETE', 'id' => true), array('action' => 'edit', 'method' => 'POST', 'id' => true) ); /** * List of resource-mapped controllers * * @var array */ protected static $_resourceMapped = array(); /** * Maintains the request object stack for the current request. * This will contain more than one request object when requestAction is used. * * @var array */ protected static $_requests = array(); /** * Initial state is populated the first time reload() is called which is at the bottom * of this file. This is a cheat as get_class_vars() returns the value of static vars even if they * have changed. * * @var array */ protected static $_initialState = array(); /** * Default route class to use * * @var string */ protected static $_routeClass = 'CakeRoute'; /** * Set the default route class to use or return the current one * * @param string $routeClass The route class to set as default. * @return string|null The default route class. * @throws RouterException */ public static function defaultRouteClass($routeClass = null) { if ($routeClass === null) { return static::$_routeClass; } static::$_routeClass = static::_validateRouteClass($routeClass); } /** * Validates that the passed route class exists and is a subclass of CakeRoute * * @param string $routeClass Route class name * @return string * @throws RouterException */ protected static function _validateRouteClass($routeClass) { if ($routeClass !== 'CakeRoute' && (!class_exists($routeClass) || !is_subclass_of($routeClass, 'CakeRoute')) ) { throw new RouterException(__d('cake_dev', 'Route class not found, or route class is not a subclass of CakeRoute')); } return $routeClass; } /** * Sets the Routing prefixes. * * @return void */ protected static function _setPrefixes() { $routing = Configure::read('Routing'); if (!empty($routing['prefixes'])) { static::$_prefixes = array_merge(static::$_prefixes, (array)$routing['prefixes']); } } /** * Gets the named route elements for use in app/Config/routes.php * * @return array Named route elements * @see Router::$_namedExpressions */ public static function getNamedExpressions() { return static::$_namedExpressions; } /** * Resource map getter & setter. * * @param array $resourceMap Resource map * @return mixed * @see Router::$_resourceMap */ public static function resourceMap($resourceMap = null) { if ($resourceMap === null) { return static::$_resourceMap; } static::$_resourceMap = $resourceMap; } /** * Connects a new Route in the router. * * Routes are a way of connecting request URLs to objects in your application. At their core routes * are a set of regular expressions that are used to match requests to destinations. * * Examples: * * `Router::connect('/:controller/:action/*');` * * The first token ':controller' will be used as a controller name while the second is used as the action name. * the '/*' syntax makes this route greedy in that it will match requests like `/posts/index` as well as requests * like `/posts/edit/1/foo/bar`. * * `Router::connect('/home-page', array('controller' => 'pages', 'action' => 'display', 'home'));` * * The above shows the use of route parameter defaults, and providing routing parameters for a static route. * * ``` * Router::connect( * '/:lang/:controller/:action/:id', * array(), * array('id' => '[0-9]+', 'lang' => '[a-z]{3}') * ); * ``` * * Shows connecting a route with custom route parameters as well as providing patterns for those parameters. * Patterns for routing parameters do not need capturing groups, as one will be added for each route params. * * $defaults is merged with the results of parsing the request URL to form the final routing destination and its * parameters. This destination is expressed as an associative array by Router. See the output of {@link parse()}. * * $options offers four 'special' keys. `pass`, `named`, `persist` and `routeClass` * have special meaning in the $options array. * * - `pass` is used to define which of the routed parameters should be shifted into the pass array. Adding a * parameter to pass will remove it from the regular route array. Ex. `'pass' => array('slug')` * - `persist` is used to define which route parameters should be automatically included when generating * new URLs. You can override persistent parameters by redefining them in a URL or remove them by * setting the parameter to `false`. Ex. `'persist' => array('lang')` * - `routeClass` is used to extend and change how individual routes parse requests and handle reverse routing, * via a custom routing class. Ex. `'routeClass' => 'SlugRoute'` * - `named` is used to configure named parameters at the route level. This key uses the same options * as Router::connectNamed() * * You can also add additional conditions for matching routes to the $defaults array. * The following conditions can be used: * * - `[type]` Only match requests for specific content types. * - `[method]` Only match requests with specific HTTP verbs. * - `[server]` Only match when $_SERVER['SERVER_NAME'] matches the given value. * * Example of using the `[method]` condition: * * `Router::connect('/tasks', array('controller' => 'tasks', 'action' => 'index', '[method]' => 'GET'));` * * The above route will only be matched for GET requests. POST requests will fail to match this route. * * @param string $route A string describing the template of the route * @param array $defaults An array describing the default route parameters. These parameters will be used by default * and can supply routing parameters that are not dynamic. See above. * @param array $options An array matching the named elements in the route to regular expressions which that * element should match. Also contains additional parameters such as which routed parameters should be * shifted into the passed arguments, supplying patterns for routing parameters and supplying the name of a * custom routing class. * @see routes * @see parse(). * @return array Array of routes * @throws RouterException */ public static function connect($route, $defaults = array(), $options = array()) { static::$initialized = true; foreach (static::$_prefixes as $prefix) { if (isset($defaults[$prefix])) { if ($defaults[$prefix]) { $defaults['prefix'] = $prefix; } else { unset($defaults[$prefix]); } break; } } if (isset($defaults['prefix']) && !in_array($defaults['prefix'], static::$_prefixes)) { static::$_prefixes[] = $defaults['prefix']; } $defaults += array('plugin' => null); if (empty($options['action'])) { $defaults += array('action' => 'index'); } $routeClass = static::$_routeClass; if (isset($options['routeClass'])) { if (strpos($options['routeClass'], '.') === false) { $routeClass = $options['routeClass']; } else { list(, $routeClass) = pluginSplit($options['routeClass'], true); } $routeClass = static::_validateRouteClass($routeClass); unset($options['routeClass']); } if ($routeClass === 'RedirectRoute' && isset($defaults['redirect'])) { $defaults = $defaults['redirect']; } static::$routes[] = new $routeClass($route, $defaults, $options); return static::$routes; } /** * Connects a new redirection Route in the router. * * Redirection routes are different from normal routes as they perform an actual * header redirection if a match is found. The redirection can occur within your * application or redirect to an outside location. * * Examples: * * `Router::redirect('/home/*', array('controller' => 'posts', 'action' => 'view'), array('persist' => true));` * * Redirects /home/* to /posts/view and passes the parameters to /posts/view. Using an array as the * redirect destination allows you to use other routes to define where a URL string should be redirected to. * * `Router::redirect('/posts/*', 'http://google.com', array('status' => 302));` * * Redirects /posts/* to http://google.com with a HTTP status of 302 * * ### Options: * * - `status` Sets the HTTP status (default 301) * - `persist` Passes the params to the redirected route, if it can. This is useful with greedy routes, * routes that end in `*` are greedy. As you can remap URLs and not loose any passed/named args. * * @param string $route A string describing the template of the route * @param array $url A URL to redirect to. Can be a string or a CakePHP array-based URL * @param array $options An array matching the named elements in the route to regular expressions which that * element should match. Also contains additional parameters such as which routed parameters should be * shifted into the passed arguments. As well as supplying patterns for routing parameters. * @see routes * @return array Array of routes */ public static function redirect($route, $url, $options = array()) { App::uses('RedirectRoute', 'Routing/Route'); $options['routeClass'] = 'RedirectRoute'; if (is_string($url)) { $url = array('redirect' => $url); } return static::connect($route, $url, $options); } /** * Specifies what named parameters CakePHP should be parsing out of incoming URLs. By default * CakePHP will parse every named parameter out of incoming URLs. However, if you want to take more * control over how named parameters are parsed you can use one of the following setups: * * Do not parse any named parameters: * * ``` Router::connectNamed(false); ``` * * Parse only default parameters used for CakePHP's pagination: * * ``` Router::connectNamed(false, array('default' => true)); ``` * * Parse only the page parameter if its value is a number: * * ``` Router::connectNamed(array('page' => '[\d]+'), array('default' => false, 'greedy' => false)); ``` * * Parse only the page parameter no matter what. * * ``` Router::connectNamed(array('page'), array('default' => false, 'greedy' => false)); ``` * * Parse only the page parameter if the current action is 'index'. * * ``` * Router::connectNamed( * array('page' => array('action' => 'index')), * array('default' => false, 'greedy' => false) * ); * ``` * * Parse only the page parameter if the current action is 'index' and the controller is 'pages'. * * ``` * Router::connectNamed( * array('page' => array('action' => 'index', 'controller' => 'pages')), * array('default' => false, 'greedy' => false) * ); * ``` * * ### Options * * - `greedy` Setting this to true will make Router parse all named params. Setting it to false will * parse only the connected named params. * - `default` Set this to true to merge in the default set of named parameters. * - `reset` Set to true to clear existing rules and start fresh. * - `separator` Change the string used to separate the key & value in a named parameter. Defaults to `:` * * @param array $named A list of named parameters. Key value pairs are accepted where values are * either regex strings to match, or arrays as seen above. * @param array $options Allows to control all settings: separator, greedy, reset, default * @return array */ public static function connectNamed($named, $options = array()) { if (isset($options['separator'])) { static::$_namedConfig['separator'] = $options['separator']; unset($options['separator']); } if ($named === true || $named === false) { $options += array('default' => $named, 'reset' => true, 'greedy' => $named); $named = array(); } else { $options += array('default' => false, 'reset' => false, 'greedy' => true); } if ($options['reset'] || static::$_namedConfig['rules'] === false) { static::$_namedConfig['rules'] = array(); } if ($options['default']) { $named = array_merge($named, static::$_namedConfig['default']); } foreach ($named as $key => $val) { if (is_numeric($key)) { static::$_namedConfig['rules'][$val] = true; } else { static::$_namedConfig['rules'][$key] = $val; } } static::$_namedConfig['greedyNamed'] = $options['greedy']; return static::$_namedConfig; } /** * Gets the current named parameter configuration values. * * @return array * @see Router::$_namedConfig */ public static function namedConfig() { return static::$_namedConfig; } /** * Creates REST resource routes for the given controller(s). When creating resource routes * for a plugin, by default the prefix will be changed to the lower_underscore version of the plugin * name. By providing a prefix you can override this behavior. * * ### Options: * * - 'id' - The regular expression fragment to use when matching IDs. By default, matches * integer values and UUIDs. * - 'prefix' - URL prefix to use for the generated routes. Defaults to '/'. * * @param string|array $controller A controller name or array of controller names (i.e. "Posts" or "ListItems") * @param array $options Options to use when generating REST routes * @return array Array of mapped resources */ public static function mapResources($controller, $options = array()) { $hasPrefix = isset($options['prefix']); $options += array( 'connectOptions' => array(), 'prefix' => '/', 'id' => static::ID . '|' . static::UUID ); $prefix = $options['prefix']; $connectOptions = $options['connectOptions']; unset($options['connectOptions']); if (strpos($prefix, '/') !== 0) { $prefix = '/' . $prefix; } if (substr($prefix, -1) !== '/') { $prefix .= '/'; } foreach ((array)$controller as $name) { list($plugin, $name) = pluginSplit($name); $urlName = Inflector::underscore($name); $plugin = Inflector::underscore($plugin); if ($plugin && !$hasPrefix) { $prefix = '/' . $plugin . '/'; } foreach (static::$_resourceMap as $params) { $url = $prefix . $urlName . (($params['id']) ? '/:id' : ''); Router::connect($url, array( 'plugin' => $plugin, 'controller' => $urlName, 'action' => $params['action'], '[method]' => $params['method'] ), array_merge( array('id' => $options['id'], 'pass' => array('id')), $connectOptions ) ); } static::$_resourceMapped[] = $urlName; } return static::$_resourceMapped; } /** * Returns the list of prefixes used in connected routes * * @return array A list of prefixes used in connected routes */ public static function prefixes() { return static::$_prefixes; } /** * Parses given URL string. Returns 'routing' parameters for that URL. * * @param string $url URL to be parsed * @return array Parsed elements from URL */ public static function parse($url) { if (!static::$initialized) { static::_loadRoutes(); } $ext = null; $out = array(); if (strlen($url) && strpos($url, '/') !== 0) { $url = '/' . $url; } if (strpos($url, '?') !== false) { list($url, $queryParameters) = explode('?', $url, 2); parse_str($queryParameters, $queryParameters); } extract(static::_parseExtension($url)); foreach (static::$routes as $route) { if (($r = $route->parse($url)) !== false) { static::$_currentRoute[] = $route; $out = $r; break; } } if (isset($out['prefix'])) { $out['action'] = $out['prefix'] . '_' . $out['action']; } if (!empty($ext) && !isset($out['ext'])) { $out['ext'] = $ext; } if (!empty($queryParameters) && !isset($out['?'])) { $out['?'] = $queryParameters; } return $out; } /** * Parses a file extension out of a URL, if Router::parseExtensions() is enabled. * * @param string $url URL. * @return array Returns an array containing the altered URL and the parsed extension. */ protected static function _parseExtension($url) { $ext = null; if (static::$_parseExtensions) { if (preg_match('/\.[0-9a-zA-Z]*$/', $url, $match) === 1) { $match = substr($match[0], 1); if (empty(static::$_validExtensions)) { $url = substr($url, 0, strpos($url, '.' . $match)); $ext = $match; } else { foreach (static::$_validExtensions as $name) { if (strcasecmp($name, $match) === 0) { $url = substr($url, 0, strpos($url, '.' . $name)); $ext = $match; break; } } } } } return compact('ext', 'url'); } /** * Takes parameter and path information back from the Dispatcher, sets these * parameters as the current request parameters that are merged with URL arrays * created later in the request. * * Nested requests will create a stack of requests. You can remove requests using * Router::popRequest(). This is done automatically when using Object::requestAction(). * * Will accept either a CakeRequest object or an array of arrays. Support for * accepting arrays may be removed in the future. * * @param CakeRequest|array $request Parameters and path information or a CakeRequest object. * @return void */ public static function setRequestInfo($request) { if ($request instanceof CakeRequest) { static::$_requests[] = $request; } else { $requestObj = new CakeRequest(); $request += array(array(), array()); $request[0] += array('controller' => false, 'action' => false, 'plugin' => null); $requestObj->addParams($request[0])->addPaths($request[1]); static::$_requests[] = $requestObj; } } /** * Pops a request off of the request stack. Used when doing requestAction * * @return CakeRequest The request removed from the stack. * @see Router::setRequestInfo() * @see Object::requestAction() */ public static function popRequest() { return array_pop(static::$_requests); } /** * Gets the current request object, or the first one. * * @param bool $current True to get the current request object, or false to get the first one. * @return CakeRequest|null Null if stack is empty. */ public static function getRequest($current = false) { if ($current) { $i = count(static::$_requests) - 1; return isset(static::$_requests[$i]) ? static::$_requests[$i] : null; } return isset(static::$_requests[0]) ? static::$_requests[0] : null; } /** * Gets parameter information * * @param bool $current Get current request parameter, useful when using requestAction * @return array Parameter information */ public static function getParams($current = false) { if ($current && static::$_requests) { return static::$_requests[count(static::$_requests) - 1]->params; } if (isset(static::$_requests[0])) { return static::$_requests[0]->params; } return array(); } /** * Gets URL parameter by name * * @param string $name Parameter name * @param bool $current Current parameter, useful when using requestAction * @return string|null Parameter value */ public static function getParam($name = 'controller', $current = false) { $params = Router::getParams($current); if (isset($params[$name])) { return $params[$name]; } return null; } /** * Gets path information * * @param bool $current Current parameter, useful when using requestAction * @return array */ public static function getPaths($current = false) { if ($current) { return static::$_requests[count(static::$_requests) - 1]; } if (!isset(static::$_requests[0])) { return array('base' => null); } return array('base' => static::$_requests[0]->base); } /** * Reloads default Router settings. Resets all class variables and * removes all connected routes. * * @return void */ public static function reload() { if (empty(static::$_initialState)) { static::$_initialState = get_class_vars('Router'); static::_setPrefixes(); return; } foreach (static::$_initialState as $key => $val) { if ($key !== '_initialState') { static::${$key} = $val; } } static::_setPrefixes(); } /** * Promote a route (by default, the last one added) to the beginning of the list * * @param int $which A zero-based array index representing the route to move. For example, * if 3 routes have been added, the last route would be 2. * @return bool Returns false if no route exists at the position specified by $which. */ public static function promote($which = null) { if ($which === null) { $which = count(static::$routes) - 1; } if (!isset(static::$routes[$which])) { return false; } $route =& static::$routes[$which]; unset(static::$routes[$which]); array_unshift(static::$routes, $route); return true; } /** * Finds URL for specified action. * * Returns a URL pointing to a combination of controller and action. Param * $url can be: * * - Empty - the method will find address to actual controller/action. * - '/' - the method will find base URL of application. * - A combination of controller/action - the method will find URL for it. * * There are a few 'special' parameters that can change the final URL string that is generated * * - `base` - Set to false to remove the base path from the generated URL. If your application * is not in the root directory, this can be used to generate URLs that are 'cake relative'. * cake relative URLs are required when using requestAction. * - `?` - Takes an array of query string parameters * - `#` - Allows you to set URL hash fragments. * - `full_base` - If true the `Router::fullBaseUrl()` value will be prepended to generated URLs. * * @param string|array $url Cake-relative URL, like "/products/edit/92" or "/presidents/elect/4" * or an array specifying any of the following: 'controller', 'action', * and/or 'plugin', in addition to named arguments (keyed array elements), * and standard URL arguments (indexed array elements) * @param bool|array $full If (bool) true, the full base URL will be prepended to the result. * If an array accepts the following keys * - escape - used when making URLs embedded in html escapes query string '&' * - full - if true the full base URL will be prepended. * @return string Full translated URL with base path. */ public static function url($url = null, $full = false) { if (!static::$initialized) { static::_loadRoutes(); } $params = array('plugin' => null, 'controller' => null, 'action' => 'index'); if (is_bool($full)) { $escape = false; } else { extract($full + array('escape' => false, 'full' => false)); } $path = array('base' => null); if (!empty(static::$_requests)) { $request = static::$_requests[count(static::$_requests) - 1]; $params = $request->params; $path = array('base' => $request->base, 'here' => $request->here); } if (empty($path['base'])) { $path['base'] = Configure::read('App.base'); } $base = $path['base']; $extension = $output = $q = $frag = null; if (empty($url)) { $output = isset($path['here']) ? $path['here'] : '/'; if ($full) { $output = static::fullBaseUrl() . $output; } return $output; } elseif (is_array($url)) { if (isset($url['base']) && $url['base'] === false) { $base = null; unset($url['base']); } if (isset($url['full_base']) && $url['full_base'] === true) { $full = true; unset($url['full_base']); } if (isset($url['?'])) { $q = $url['?']; unset($url['?']); } if (isset($url['#'])) { $frag = '#' . $url['#']; unset($url['#']); } if (isset($url['ext'])) { $extension = '.' . $url['ext']; unset($url['ext']); } if (empty($url['action'])) { if (empty($url['controller']) || $params['controller'] === $url['controller']) { $url['action'] = $params['action']; } else { $url['action'] = 'index'; } } $prefixExists = (array_intersect_key($url, array_flip(static::$_prefixes))); foreach (static::$_prefixes as $prefix) { if (!empty($params[$prefix]) && !$prefixExists) { $url[$prefix] = true; } elseif (isset($url[$prefix]) && !$url[$prefix]) { unset($url[$prefix]); } if (isset($url[$prefix]) && strpos($url['action'], $prefix . '_') === 0) { $url['action'] = substr($url['action'], strlen($prefix) + 1); } } $url += array('controller' => $params['controller'], 'plugin' => $params['plugin']); $match = false; foreach (static::$routes as $route) { $originalUrl = $url; $url = $route->persistParams($url, $params); if ($match = $route->match($url)) { $output = trim($match, '/'); break; } $url = $originalUrl; } if ($match === false) { $output = static::_handleNoRoute($url); } } else { if (preg_match('/^([a-z][a-z0-9.+\-]+:|:?\/\/|[#?])/i', $url)) { return $url; } if (substr($url, 0, 1) === '/') { $output = substr($url, 1); } else { foreach (static::$_prefixes as $prefix) { if (isset($params[$prefix])) { $output .= $prefix . '/'; break; } } if (!empty($params['plugin']) && $params['plugin'] !== $params['controller']) { $output .= Inflector::underscore($params['plugin']) . '/'; } $output .= Inflector::underscore($params['controller']) . '/' . $url; } } $protocol = preg_match('#^[a-z][a-z0-9+\-.]*\://#i', $output); if ($protocol === 0) { $output = str_replace('//', '/', $base . '/' . $output); if ($full) { $output = static::fullBaseUrl() . $output; } if (!empty($extension)) { $output = rtrim($output, '/'); } } return $output . $extension . static::queryString($q, array(), $escape) . $frag; } /** * Sets the full base URL that will be used as a prefix for generating * fully qualified URLs for this application. If no parameters are passed, * the currently configured value is returned. * * ## Note: * * If you change the configuration value ``App.fullBaseUrl`` during runtime * and expect the router to produce links using the new setting, you are * required to call this method passing such value again. * * @param string $base the prefix for URLs generated containing the domain. * For example: ``http://example.com`` * @return string */ public static function fullBaseUrl($base = null) { if ($base !== null) { static::$_fullBaseUrl = $base; Configure::write('App.fullBaseUrl', $base); } if (empty(static::$_fullBaseUrl)) { static::$_fullBaseUrl = Configure::read('App.fullBaseUrl'); } return static::$_fullBaseUrl; } /** * A special fallback method that handles URL arrays that cannot match * any defined routes. * * @param array $url A URL that didn't match any routes * @return string A generated URL for the array * @see Router::url() */ protected static function _handleNoRoute($url) { $named = $args = array(); $skip = array_merge( array('bare', 'action', 'controller', 'plugin', 'prefix'), static::$_prefixes ); $keys = array_values(array_diff(array_keys($url), $skip)); // Remove this once parsed URL parameters can be inserted into 'pass' foreach ($keys as $key) { if (is_numeric($key)) { $args[] = $url[$key]; } else { $named[$key] = $url[$key]; } } list($args, $named) = array(Hash::filter($args), Hash::filter($named)); foreach (static::$_prefixes as $prefix) { $prefixed = $prefix . '_'; if (!empty($url[$prefix]) && strpos($url['action'], $prefixed) === 0) { $url['action'] = substr($url['action'], strlen($prefixed) * -1); break; } } if (empty($named) && empty($args) && (!isset($url['action']) || $url['action'] === 'index')) { $url['action'] = null; } $urlOut = array_filter(array($url['controller'], $url['action'])); if (isset($url['plugin'])) { array_unshift($urlOut, $url['plugin']); } foreach (static::$_prefixes as $prefix) { if (isset($url[$prefix])) { array_unshift($urlOut, $prefix); break; } } $output = implode('/', $urlOut); if (!empty($args)) { $output .= '/' . implode('/', array_map('rawurlencode', $args)); } if (!empty($named)) { foreach ($named as $name => $value) { if (is_array($value)) { $flattend = Hash::flatten($value, '%5D%5B'); foreach ($flattend as $namedKey => $namedValue) { $output .= '/' . $name . "%5B{$namedKey}%5D" . static::$_namedConfig['separator'] . rawurlencode($namedValue); } } else { $output .= '/' . $name . static::$_namedConfig['separator'] . rawurlencode($value); } } } return $output; } /** * Generates a well-formed querystring from $q * * @param string|array $q Query string Either a string of already compiled query string arguments or * an array of arguments to convert into a query string. * @param array $extra Extra querystring parameters. * @param bool $escape Whether or not to use escaped & * @return array */ public static function queryString($q, $extra = array(), $escape = false) { if (empty($q) && empty($extra)) { return null; } $join = '&'; if ($escape === true) { $join = '&'; } $out = ''; if (is_array($q)) { $q = array_merge($q, $extra); } else { $out = $q; $q = $extra; } $addition = http_build_query($q, null, $join); if ($out && $addition && substr($out, strlen($join) * -1, strlen($join)) !== $join) { $out .= $join; } $out .= $addition; if (isset($out[0]) && $out[0] !== '?') { $out = '?' . $out; } return $out; } /** * Reverses a parsed parameter array into a string. * * Works similarly to Router::url(), but since parsed URL's contain additional * 'pass' and 'named' as well as 'url.url' keys. Those keys need to be specially * handled in order to reverse a params array into a string URL. * * This will strip out 'autoRender', 'bare', 'requested', and 'return' param names as those * are used for CakePHP internals and should not normally be part of an output URL. * * @param CakeRequest|array $params The params array or CakeRequest object that needs to be reversed. * @param bool $full Set to true to include the full URL including the protocol when reversing * the URL. * @return string The string that is the reversed result of the array */ public static function reverse($params, $full = false) { if ($params instanceof CakeRequest) { $url = $params->query; $params = $params->params; } else { $url = $params['url']; } $pass = isset($params['pass']) ? $params['pass'] : array(); $named = isset($params['named']) ? $params['named'] : array(); unset( $params['pass'], $params['named'], $params['paging'], $params['models'], $params['url'], $url['url'], $params['autoRender'], $params['bare'], $params['requested'], $params['return'], $params['_Token'] ); $params = array_merge($params, $pass, $named); if (!empty($url)) { $params['?'] = $url; } return Router::url($params, $full); } /** * Normalizes a URL for purposes of comparison. * * Will strip the base path off and replace any double /'s. * It will not unify the casing and underscoring of the input value. * * @param array|string $url URL to normalize Either an array or a string URL. * @return string Normalized URL */ public static function normalize($url = '/') { if (is_array($url)) { $url = Router::url($url); } if (preg_match('/^[a-z\-]+:\/\//', $url)) { return $url; } $request = Router::getRequest(); if (!empty($request->base) && stristr($url, $request->base)) { $url = preg_replace('/^' . preg_quote($request->base, '/') . '/', '', $url, 1); } $url = '/' . $url; while (strpos($url, '//') !== false) { $url = str_replace('//', '/', $url); } $url = preg_replace('/(?:(\/$))/', '', $url); if (empty($url)) { return '/'; } return $url; } /** * Returns the route matching the current request URL. * * @return CakeRoute Matching route object. */ public static function requestRoute() { return static::$_currentRoute[0]; } /** * Returns the route matching the current request (useful for requestAction traces) * * @return CakeRoute Matching route object. */ public static function currentRoute() { $count = count(static::$_currentRoute) - 1; return ($count >= 0) ? static::$_currentRoute[$count] : false; } /** * Removes the plugin name from the base URL. * * @param string $base Base URL * @param string $plugin Plugin name * @return string base URL with plugin name removed if present */ public static function stripPlugin($base, $plugin = null) { if ($plugin) { $base = preg_replace('/(?:' . $plugin . ')/', '', $base); $base = str_replace('//', '', $base); $pos1 = strrpos($base, '/'); $char = strlen($base) - 1; if ($pos1 === $char) { $base = substr($base, 0, $char); } } return $base; } /** * Instructs the router to parse out file extensions from the URL. * * For example, http://example.com/posts.rss would yield a file extension of "rss". * The file extension itself is made available in the controller as * `$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. 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() { static::$_parseExtensions = true; if (func_num_args() > 0) { static::setExtensions(func_get_args(), false); } } /** * Get the list of extensions that can be parsed by Router. * * To initially set extensions use `Router::parseExtensions()` * To add more see `setExtensions()` * * @return array Array of extensions Router is configured to parse. */ public static function extensions() { if (!static::$initialized) { static::_loadRoutes(); } return static::$_validExtensions; } /** * Set/add valid extensions. * * To have the extensions parsed you still need to call `Router::parseExtensions()` * * @param array $extensions List of extensions to be added as valid extension * @param bool $merge Default true will merge extensions. Set to false to override current extensions * @return array */ public static function setExtensions($extensions, $merge = true) { if (!is_array($extensions)) { return static::$_validExtensions; } if (!$merge) { return static::$_validExtensions = $extensions; } return static::$_validExtensions = array_merge(static::$_validExtensions, $extensions); } /** * Loads route configuration * * @return void */ protected static function _loadRoutes() { static::$initialized = true; include APP . 'Config' . DS . 'routes.php'; } } //Save the initial state Router::reload(); cakephp-2.8.0/lib/Cake/Test/000077500000000000000000000000001265552240500154725ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/000077500000000000000000000000001265552240500163455ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/AllBehaviorsTest.php000066400000000000000000000023511265552240500222720ustar00rootroot00000000000000addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'BehaviorCollectionTest.php'); $suite->addTestDirectory($path); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllCacheTest.php000066400000000000000000000022151265552240500213520ustar00rootroot00000000000000addTestDirectory(CORE_TEST_CASES . DS . 'Cache'); $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Cache' . DS . 'Engine'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllComponentsTest.php000066400000000000000000000024501265552240500224750ustar00rootroot00000000000000addTestFile(CORE_TEST_CASES . DS . 'Controller' . DS . 'ComponentTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Controller' . DS . 'ComponentCollectionTest.php'); $suite->addTestDirectoryRecursive(CORE_TEST_CASES . DS . 'Controller' . DS . 'Component'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllConfigureTest.php000066400000000000000000000021151265552240500222670ustar00rootroot00000000000000addTestDirectory(CORE_TEST_CASES . DS . 'Configure'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllConsoleTest.php000066400000000000000000000023251265552240500217530ustar00rootroot00000000000000addTestFile($path . 'AllConsoleLibsTest.php'); $suite->addTestFile($path . 'AllTasksTest.php'); $suite->addTestFile($path . 'AllShellsTest.php'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllControllerTest.php000066400000000000000000000027461265552240500225030ustar00rootroot00000000000000addTestFile(CORE_TEST_CASES . DS . 'Controller' . DS . 'ControllerTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Controller' . DS . 'ScaffoldTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Controller' . DS . 'PagesControllerTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Controller' . DS . 'ComponentTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Controller' . DS . 'ControllerMergeVarsTest.php'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllCoreTest.php000066400000000000000000000020661265552240500212430ustar00rootroot00000000000000addTestDirectory(CORE_TEST_CASES . DS . 'Core'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllDatabaseTest.php000066400000000000000000000032361265552240500220570ustar00rootroot00000000000000addTestFile($path . $task . 'Test.php'); } return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllDbRelatedTest.php000066400000000000000000000032541265552240500222010ustar00rootroot00000000000000addTestFile($path . 'AllBehaviorsTest.php'); $suite->addTestFile($path . 'Controller' . DS . 'Component' . DS . 'PaginatorComponentTest.php'); $suite->addTestFile($path . 'AllDatabaseTest.php'); $suite->addTestFile($path . 'Model' . DS . 'ModelTest.php'); $suite->addTestFile($path . 'View' . DS . 'ViewTest.php'); $suite->addTestFile($path . 'View' . DS . 'ScaffoldViewTest.php'); $suite->addTestFile($path . 'View' . DS . 'HelperTest.php'); $suite->addTestFile($path . 'View' . DS . 'Helper' . DS . 'FormHelperTest.php'); $suite->addTestFile($path . 'View' . DS . 'Helper' . DS . 'PaginatorHelperTest.php'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllErrorTest.php000066400000000000000000000021311265552240500214350ustar00rootroot00000000000000addTestDirectory($libs . 'Error'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllEventTest.php000066400000000000000000000020721265552240500214310ustar00rootroot00000000000000addTestDirectory(CORE_TEST_CASES . DS . 'Event'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllHelpersTest.php000066400000000000000000000023571265552240500217600ustar00rootroot00000000000000addTestFile(CORE_TEST_CASES . DS . 'View' . DS . 'HelperTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'View' . DS . 'HelperCollectionTest.php'); $suite->addTestDirectory(CORE_TEST_CASES . DS . 'View' . DS . 'Helper' . DS); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllI18nTest.php000066400000000000000000000021211265552240500210620ustar00rootroot00000000000000addTestDirectory(CORE_TEST_CASES . DS . 'I18n'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllLogTest.php000066400000000000000000000021741265552240500210740ustar00rootroot00000000000000addTestDirectory(CORE_TEST_CASES . DS . 'Log'); $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Log' . DS . 'Engine'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllNetworkTest.php000066400000000000000000000023441265552240500220030ustar00rootroot00000000000000addTestDirectory(CORE_TEST_CASES . DS . 'Network'); $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Network' . DS . 'Email'); $suite->addTestDirectory(CORE_TEST_CASES . DS . 'Network' . DS . 'Http'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllRoutingTest.php000066400000000000000000000023221265552240500217750ustar00rootroot00000000000000addTestDirectory($libs . 'Routing'); $suite->addTestDirectory($libs . 'Routing' . DS . 'Route'); $suite->addTestDirectory($libs . 'Routing' . DS . 'Filter'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllTestSuiteTest.php000066400000000000000000000021231265552240500222760ustar00rootroot00000000000000addTestDirectory(CORE_TEST_CASES . DS . 'TestSuite'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllTestsTest.php000066400000000000000000000040521265552240500214520ustar00rootroot00000000000000addTestFile($path . 'BasicsTest.php'); $suite->addTestFile($path . 'AllConsoleTest.php'); $suite->addTestFile($path . 'AllBehaviorsTest.php'); $suite->addTestFile($path . 'AllCacheTest.php'); $suite->addTestFile($path . 'AllComponentsTest.php'); $suite->addTestFile($path . 'AllConfigureTest.php'); $suite->addTestFile($path . 'AllCoreTest.php'); $suite->addTestFile($path . 'AllControllerTest.php'); $suite->addTestFile($path . 'AllDatabaseTest.php'); $suite->addTestFile($path . 'AllErrorTest.php'); $suite->addTestFile($path . 'AllEventTest.php'); $suite->addTestFile($path . 'AllHelpersTest.php'); $suite->addTestFile($path . 'AllLogTest.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; } } cakephp-2.8.0/lib/Cake/Test/Case/AllUtilityTest.php000066400000000000000000000021231265552240500220100ustar00rootroot00000000000000addTestDirectory(CORE_TEST_CASES . DS . 'Utility'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/AllViewTest.php000066400000000000000000000021001265552240500212520ustar00rootroot00000000000000addTestDirectory(CORE_TEST_CASES . DS . 'View'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/BasicsTest.php000066400000000000000000001057311265552240500211310ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ require_once CAKE . 'basics.php'; App::uses('Folder', 'Utility'); App::uses('CakeResponse', 'Network'); App::uses('Debugger', 'Utility'); /** * BasicsTest class * * @package Cake.Test.Case */ class BasicsTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); App::build(array( 'Locale' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Locale' . DS) )); } /** * test the array_diff_key compatibility function. * * @return void */ public function testArrayDiffKey() { $one = array('one' => 1, 'two' => 2, 'three' => 3); $two = array('one' => 'one', 'two' => 'two'); $result = array_diff_key($one, $two); $expected = array('three' => 3); $this->assertEquals($expected, $result); $one = array('one' => array('value', 'value-two'), 'two' => 2, 'three' => 3); $two = array('two' => 'two'); $result = array_diff_key($one, $two); $expected = array('one' => array('value', 'value-two'), 'three' => 3); $this->assertEquals($expected, $result); $one = array('one' => null, 'two' => 2, 'three' => '', 'four' => 0); $two = array('two' => 'two'); $result = array_diff_key($one, $two); $expected = array('one' => null, 'three' => '', 'four' => 0); $this->assertEquals($expected, $result); $one = array('minYear' => null, 'maxYear' => null, 'separator' => '-', 'interval' => 1, 'monthNames' => true); $two = array('minYear' => null, 'maxYear' => null, 'separator' => '-', 'interval' => 1, 'monthNames' => true); $result = array_diff_key($one, $two); $this->assertSame(array(), $result); } /** * testHttpBase method * * @return void */ public function testEnv() { $this->skipIf(!function_exists('ini_get') || ini_get('safe_mode') === '1', 'Safe mode is on.'); $server = $_SERVER; $env = $_ENV; $_SERVER['HTTP_HOST'] = 'localhost'; $this->assertEquals(env('HTTP_BASE'), '.localhost'); $_SERVER['HTTP_HOST'] = 'com.ar'; $this->assertEquals(env('HTTP_BASE'), '.com.ar'); $_SERVER['HTTP_HOST'] = 'example.ar'; $this->assertEquals(env('HTTP_BASE'), '.example.ar'); $_SERVER['HTTP_HOST'] = 'example.com'; $this->assertEquals(env('HTTP_BASE'), '.example.com'); $_SERVER['HTTP_HOST'] = 'www.example.com'; $this->assertEquals(env('HTTP_BASE'), '.example.com'); $_SERVER['HTTP_HOST'] = 'subdomain.example.com'; $this->assertEquals(env('HTTP_BASE'), '.example.com'); $_SERVER['HTTP_HOST'] = 'example.com.ar'; $this->assertEquals(env('HTTP_BASE'), '.example.com.ar'); $_SERVER['HTTP_HOST'] = 'www.example.com.ar'; $this->assertEquals(env('HTTP_BASE'), '.example.com.ar'); $_SERVER['HTTP_HOST'] = 'subdomain.example.com.ar'; $this->assertEquals(env('HTTP_BASE'), '.example.com.ar'); $_SERVER['HTTP_HOST'] = 'double.subdomain.example.com'; $this->assertEquals(env('HTTP_BASE'), '.subdomain.example.com'); $_SERVER['HTTP_HOST'] = 'double.subdomain.example.com.ar'; $this->assertEquals(env('HTTP_BASE'), '.subdomain.example.com.ar'); $_SERVER = $_ENV = array(); $_SERVER['SCRIPT_NAME'] = '/a/test/test.php'; $this->assertEquals(env('SCRIPT_NAME'), '/a/test/test.php'); $_SERVER = $_ENV = array(); $_ENV['CGI_MODE'] = 'BINARY'; $_ENV['SCRIPT_URL'] = '/a/test/test.php'; $this->assertEquals(env('SCRIPT_NAME'), '/a/test/test.php'); $_SERVER = $_ENV = array(); $this->assertFalse(env('HTTPS')); $_SERVER['HTTPS'] = 'on'; $this->assertTrue(env('HTTPS')); $_SERVER['HTTPS'] = '1'; $this->assertTrue(env('HTTPS')); $_SERVER['HTTPS'] = 'I am not empty'; $this->assertTrue(env('HTTPS')); $_SERVER['HTTPS'] = 1; $this->assertTrue(env('HTTPS')); $_SERVER['HTTPS'] = 'off'; $this->assertFalse(env('HTTPS')); $_SERVER['HTTPS'] = false; $this->assertFalse(env('HTTPS')); $_SERVER['HTTPS'] = ''; $this->assertFalse(env('HTTPS')); $_SERVER = array(); $_ENV['SCRIPT_URI'] = 'https://domain.test/a/test.php'; $this->assertTrue(env('HTTPS')); $_ENV['SCRIPT_URI'] = 'http://domain.test/a/test.php'; $this->assertFalse(env('HTTPS')); $_SERVER = $_ENV = array(); $this->assertNull(env('TEST_ME')); $_ENV['TEST_ME'] = 'a'; $this->assertEquals(env('TEST_ME'), 'a'); $_SERVER['TEST_ME'] = 'b'; $this->assertEquals(env('TEST_ME'), 'b'); unset($_ENV['TEST_ME']); $this->assertEquals(env('TEST_ME'), 'b'); $_SERVER = $server; $_ENV = $env; } /** * Test h() * * @return void */ public function testH() { $string = ''; $result = h($string); $this->assertEquals('<foo>', $result); $in = array('this & that', '

Which one

'); $result = h($in); $expected = array('this & that', '<p>Which one</p>'); $this->assertEquals($expected, $result); $string = ' &  '; $result = h($string); $this->assertEquals('<foo> & &nbsp;', $result); $string = ' &  '; $result = h($string, false); $this->assertEquals('<foo> &  ', $result); $string = ' &  '; $result = h($string, 'UTF-8'); $this->assertEquals('<foo> & &nbsp;', $result); $arr = array('', ' '); $result = h($arr); $expected = array( '<foo>', '&nbsp;' ); $this->assertEquals($expected, $result); $arr = array('', ' '); $result = h($arr, false); $expected = array( '<foo>', ' ' ); $this->assertEquals($expected, $result); $arr = array('f' => '', 'n' => ' '); $result = h($arr, false); $expected = array( 'f' => '<foo>', 'n' => ' ' ); $this->assertEquals($expected, $result); // Test that boolean values are not converted to strings $result = h(false); $this->assertFalse($result); $arr = array('foo' => false, 'bar' => true); $result = h($arr); $this->assertFalse($result['foo']); $this->assertTrue($result['bar']); $obj = new stdClass(); $result = h($obj); $this->assertEquals('(object)stdClass', $result); $obj = new CakeResponse(array('body' => 'Body content')); $result = h($obj); $this->assertEquals('Body content', $result); } /** * Test am() * * @return void */ public function testAm() { $result = am(array('one', 'two'), 2, 3, 4); $expected = array('one', 'two', 2, 3, 4); $this->assertEquals($expected, $result); $result = am(array('one' => array(2, 3), 'two' => array('foo')), array('one' => array(4, 5))); $expected = array('one' => array(4, 5), 'two' => array('foo')); $this->assertEquals($expected, $result); } /** * test cache() * * @return void */ public function testCache() { $_cacheDisable = Configure::read('Cache.disable'); $this->skipIf($_cacheDisable, 'Cache is disabled, skipping cache() tests.'); Configure::write('Cache.disable', true); $result = cache('basics_test', 'simple cache write'); $this->assertNull($result); $result = cache('basics_test'); $this->assertNull($result); Configure::write('Cache.disable', false); $result = cache('basics_test', 'simple cache write'); $this->assertTrue((bool)$result); $this->assertTrue(file_exists(CACHE . 'basics_test')); $result = cache('basics_test'); $this->assertEquals('simple cache write', $result); if (file_exists(CACHE . 'basics_test')) { unlink(CACHE . 'basics_test'); } cache('basics_test', 'expired', '+1 second'); sleep(2); $result = cache('basics_test', null, '+1 second'); $this->assertNull($result); Configure::write('Cache.disable', $_cacheDisable); } /** * test clearCache() * * @return void */ public function testClearCache() { $cacheOff = Configure::read('Cache.disable'); $this->skipIf($cacheOff, 'Cache is disabled, skipping clearCache() tests.'); cache('views' . DS . 'basics_test.cache', 'simple cache write'); $this->assertTrue(file_exists(CACHE . 'views' . DS . 'basics_test.cache')); cache('views' . DS . 'basics_test_2.cache', 'simple cache write 2'); $this->assertTrue(file_exists(CACHE . 'views' . DS . 'basics_test_2.cache')); cache('views' . DS . 'basics_test_3.cache', 'simple cache write 3'); $this->assertTrue(file_exists(CACHE . 'views' . DS . 'basics_test_3.cache')); $result = clearCache(array('basics_test', 'basics_test_2'), 'views', '.cache'); $this->assertTrue($result); $this->assertFalse(file_exists(CACHE . 'views' . DS . 'basics_test.cache')); $this->assertFalse(file_exists(CACHE . 'views' . DS . 'basics_test.cache')); $this->assertTrue(file_exists(CACHE . 'views' . DS . 'basics_test_3.cache')); $result = clearCache(null, 'views', '.cache'); $this->assertTrue($result); $this->assertFalse(file_exists(CACHE . 'views' . DS . 'basics_test_3.cache')); // Different path from views and with prefix cache('models' . DS . 'basics_test.cache', 'simple cache write'); $this->assertTrue(file_exists(CACHE . 'models' . DS . 'basics_test.cache')); cache('models' . DS . 'basics_test_2.cache', 'simple cache write 2'); $this->assertTrue(file_exists(CACHE . 'models' . DS . 'basics_test_2.cache')); cache('models' . DS . 'basics_test_3.cache', 'simple cache write 3'); $this->assertTrue(file_exists(CACHE . 'models' . DS . 'basics_test_3.cache')); $result = clearCache('basics', 'models', '.cache'); $this->assertTrue($result); $this->assertFalse(file_exists(CACHE . 'models' . DS . 'basics_test.cache')); $this->assertFalse(file_exists(CACHE . 'models' . DS . 'basics_test_2.cache')); $this->assertFalse(file_exists(CACHE . 'models' . DS . 'basics_test_3.cache')); // checking if empty files were not removed $emptyExists = file_exists(CACHE . 'views' . DS . 'empty'); if (!$emptyExists) { cache('views' . DS . 'empty', ''); } cache('views' . DS . 'basics_test.php', 'simple cache write'); $this->assertTrue(file_exists(CACHE . 'views' . DS . 'basics_test.php')); $this->assertTrue(file_exists(CACHE . 'views' . DS . 'empty')); $result = clearCache(); $this->assertTrue($result); $this->assertTrue(file_exists(CACHE . 'views' . DS . 'empty')); $this->assertFalse(file_exists(CACHE . 'views' . DS . 'basics_test.php')); if (!$emptyExists) { unlink(CACHE . 'views' . DS . 'empty'); } } /** * test __() * * @return void */ public function testTranslate() { Configure::write('Config.language', 'rule_1_po'); $result = __('Plural Rule 1'); $expected = 'Plural Rule 1 (translated)'; $this->assertEquals($expected, $result); $result = __('Plural Rule 1 (from core)'); $expected = 'Plural Rule 1 (from core translated)'; $this->assertEquals($expected, $result); $result = __('Some string with %s', 'arguments'); $expected = 'Some string with arguments'; $this->assertEquals($expected, $result); $result = __('Some string with %s %s', 'multiple', 'arguments'); $expected = 'Some string with multiple arguments'; $this->assertEquals($expected, $result); $result = __('Some string with %s and a null argument', null); $expected = 'Some string with %s and a null argument'; $this->assertEquals($expected, $result); $result = __('Some string with multiple %s%s, first being null', null, 'arguments'); $expected = 'Some string with multiple arguments, first being null'; $this->assertEquals($expected, $result); $result = __('Some string with %s %s', array('multiple', 'arguments')); $expected = 'Some string with multiple arguments'; $this->assertEquals($expected, $result); $result = __('Testing %2$s %1$s', 'order', 'different'); $expected = 'Testing different order'; $this->assertEquals($expected, $result); $result = __('Testing %2$s %1$s', array('order', 'different')); $expected = 'Testing different order'; $this->assertEquals($expected, $result); $result = __('Testing %.2f number', 1.2345); $expected = 'Testing 1.23 number'; $this->assertEquals($expected, $result); } /** * testTranslatePercent * * @return void */ public function testTranslatePercent() { $result = __('%s are 100% real fruit', 'Apples'); $expected = 'Apples are 100% real fruit'; $this->assertEquals($expected, $result, 'Percent sign at end of word should be considered literal'); $result = __('%s are %d% real fruit', 'Apples', 100); $expected = 'Apples are 100% real fruit'; $this->assertEquals($expected, $result, 'A digit marker should not be misinterpreted'); $result = __('%s are %s% real fruit', 'Apples', 100); $expected = 'Apples are 100% real fruit'; $this->assertEquals($expected, $result, 'A string marker should not be misinterpreted'); $result = __('%nonsense %s', 'Apples'); $expected = '%nonsense Apples'; $this->assertEquals($expected, $result, 'A percent sign at the start of the string should be considered literal'); $result = __('%s are awesome%', 'Apples'); $expected = 'Apples are awesome%'; $this->assertEquals($expected, $result, 'A percent sign at the end of the string should be considered literal'); $result = __('%2$d %1$s entered the bowl', 'Apples', 2); $expected = '2 Apples entered the bowl'; $this->assertEquals($expected, $result, 'Positional replacement markers should not be misinterpreted'); $result = __('%.2f% of all %s agree', 99.44444, 'Cats'); $expected = '99.44% of all Cats agree'; $this->assertEquals($expected, $result, 'significant-digit placeholder should not be misinterpreted'); } /** * testTranslateWithFormatSpecifiers * * @return void */ public function testTranslateWithFormatSpecifiers() { $expected = 'Check, one, two, three'; $result = __('Check, %+10s, three', 'one, two'); $this->assertEquals($expected, $result); $expected = 'Check, +1, two, three'; $result = __('Check, %+5d, two, three', 1); $this->assertEquals($expected, $result); $expected = 'Check, @@one, two, three'; $result = __('Check, %\'@+10s, three', 'one, two'); $this->assertEquals($expected, $result); $expected = 'Check, one, two , three'; $result = __('Check, %-10s, three', 'one, two'); $this->assertEquals($expected, $result); $expected = 'Check, one, two##, three'; $result = __('Check, %\'#-10s, three', 'one, two'); $this->assertEquals($expected, $result); $expected = 'Check, one, two, three'; $result = __d('default', 'Check, %+10s, three', 'one, two'); $this->assertEquals($expected, $result); $expected = 'Check, @@one, two, three'; $result = __d('default', 'Check, %\'@+10s, three', 'one, two'); $this->assertEquals($expected, $result); $expected = 'Check, one, two , three'; $result = __d('default', 'Check, %-10s, three', 'one, two'); $this->assertEquals($expected, $result); $expected = 'Check, one, two##, three'; $result = __d('default', 'Check, %\'#-10s, three', 'one, two'); $this->assertEquals($expected, $result); } /** * testTranslateDomainPluralWithFormatSpecifiers * * @return void */ public function testTranslateDomainPluralWithFormatSpecifiers() { $result = __dn('core', '%+5d item.', '%+5d items.', 1, 1); $expected = ' +1 item.'; $this->assertEquals($expected, $result); $result = __dn('core', '%-5d item.', '%-5d items.', 10, 10); $expected = '10 items.'; $this->assertEquals($expected, $result); $result = __dn('core', '%\'#+5d item.', '%\'*+5d items.', 1, 1); $expected = '###+1 item.'; $this->assertEquals($expected, $result); $result = __dn('core', '%\'#+5d item.', '%\'*+5d items.', 90, 90); $expected = '**+90 items.'; $this->assertEquals($expected, $result); $result = __dn('core', '%\'#+5d item.', '%\'*+5d items.', 9000, 9000); $expected = '+9000 items.'; $this->assertEquals($expected, $result); } /** * test testTranslatePluralWithFormatSpecifiers * * @return void */ public function testTranslatePluralWithFormatSpecifiers() { Configure::write('Config.language', 'rule_1_po'); $result = __n('%-5d = 1', '%-5d = 0 or > 1', 10); $expected = '%-5d = 0 or > 1 (translated)'; $this->assertEquals($expected, $result); } /** * test testTranslateDomainCategoryWithFormatSpecifiers * * @return void */ public function testTranslateDomainCategoryWithFormatSpecifiers() { Configure::write('Config.language', 'rule_1_po'); $result = __dc('default', '%+10s world', 6, 'hello'); $expected = ' hello world'; $this->assertEquals($expected, $result); $result = __dc('default', '%-10s world', 6, 'hello'); $expected = 'hello world'; $this->assertEquals($expected, $result); $result = __dc('default', '%\'@-10s world', 6, 'hello'); $expected = 'hello@@@@@ world'; $this->assertEquals($expected, $result); } /** * test testTranslateDomainCategoryPluralWithFormatSpecifiers * * @return void */ public function testTranslateDomainCategoryPluralWithFormatSpecifiers() { Configure::write('Config.language', 'rule_1_po'); $result = __dcn('default', '%-5d = 1', '%-5d = 0 or > 1', 0, 6); $expected = '%-5d = 0 or > 1 (translated)'; $this->assertEquals($expected, $result); $result = __dcn('default', '%-5d = 1', '%-5d = 0 or > 1', 1, 6); $expected = '%-5d = 1 (translated)'; $this->assertEquals($expected, $result); } /** * test testTranslateCategoryWithFormatSpecifiers * * @return void */ public function testTranslateCategoryWithFormatSpecifiers() { $result = __c('Some string with %+10s', 6, 'arguments'); $expected = 'Some string with arguments'; $this->assertEquals($expected, $result); $result = __c('Some string with %-10s: args', 6, 'arguments'); $expected = 'Some string with arguments : args'; $this->assertEquals($expected, $result); $result = __c('Some string with %\'*-10s: args', 6, 'arguments'); $expected = 'Some string with arguments*: args'; $this->assertEquals($expected, $result); } /** * test __n() * * @return void */ public function testTranslatePlural() { Configure::write('Config.language', 'rule_1_po'); $result = __n('%d = 1', '%d = 0 or > 1', 0); $expected = '%d = 0 or > 1 (translated)'; $this->assertEquals($expected, $result); $result = __n('%d = 1', '%d = 0 or > 1', 1); $expected = '%d = 1 (translated)'; $this->assertEquals($expected, $result); $result = __n('%d = 1 (from core)', '%d = 0 or > 1 (from core)', 2); $expected = '%d = 0 or > 1 (from core translated)'; $this->assertEquals($expected, $result); $result = __n('%d item.', '%d items.', 1, 1); $expected = '1 item.'; $this->assertEquals($expected, $result); $result = __n('%d item for id %s', '%d items for id %s', 2, 2, '1234'); $expected = '2 items for id 1234'; $this->assertEquals($expected, $result); $result = __n('%d item for id %s', '%d items for id %s', 2, array(2, '1234')); $expected = '2 items for id 1234'; $this->assertEquals($expected, $result); } /** * test __d() * * @return void */ public function testTranslateDomain() { Configure::write('Config.language', 'rule_1_po'); $result = __d('default', 'Plural Rule 1'); $expected = 'Plural Rule 1 (translated)'; $this->assertEquals($expected, $result); $result = __d('core', 'Plural Rule 1'); $expected = 'Plural Rule 1'; $this->assertEquals($expected, $result); $result = __d('core', 'Plural Rule 1 (from core)'); $expected = 'Plural Rule 1 (from core translated)'; $this->assertEquals($expected, $result); $result = __d('core', 'Some string with %s', 'arguments'); $expected = 'Some string with arguments'; $this->assertEquals($expected, $result); $result = __d('core', 'Some string with %s %s', 'multiple', 'arguments'); $expected = 'Some string with multiple arguments'; $this->assertEquals($expected, $result); $result = __d('core', 'Some string with %s %s', array('multiple', 'arguments')); $expected = 'Some string with multiple arguments'; $this->assertEquals($expected, $result); } /** * test __dn() * * @return void */ public function testTranslateDomainPlural() { Configure::write('Config.language', 'rule_1_po'); $result = __dn('default', '%d = 1', '%d = 0 or > 1', 0); $expected = '%d = 0 or > 1 (translated)'; $this->assertEquals($expected, $result); $result = __dn('core', '%d = 1', '%d = 0 or > 1', 0); $expected = '%d = 0 or > 1'; $this->assertEquals($expected, $result); $result = __dn('core', '%d = 1 (from core)', '%d = 0 or > 1 (from core)', 0); $expected = '%d = 0 or > 1 (from core translated)'; $this->assertEquals($expected, $result); $result = __dn('default', '%d = 1', '%d = 0 or > 1', 1); $expected = '%d = 1 (translated)'; $this->assertEquals($expected, $result); $result = __dn('core', '%d item.', '%d items.', 1, 1); $expected = '1 item.'; $this->assertEquals($expected, $result); $result = __dn('core', '%d item for id %s', '%d items for id %s', 2, 2, '1234'); $expected = '2 items for id 1234'; $this->assertEquals($expected, $result); $result = __dn('core', '%d item for id %s', '%d items for id %s', 2, array(2, '1234')); $expected = '2 items for id 1234'; $this->assertEquals($expected, $result); } /** * test __c() * * @return void */ public function testTranslateCategory() { Configure::write('Config.language', 'rule_1_po'); $result = __c('Plural Rule 1', 6); $expected = 'Plural Rule 1 (translated)'; $this->assertEquals($expected, $result); $result = __c('Plural Rule 1 (from core)', 6); $expected = 'Plural Rule 1 (from core translated)'; $this->assertEquals($expected, $result); $result = __c('Some string with %s', 6, 'arguments'); $expected = 'Some string with arguments'; $this->assertEquals($expected, $result); $result = __c('Some string with %s %s', 6, 'multiple', 'arguments'); $expected = 'Some string with multiple arguments'; $this->assertEquals($expected, $result); $result = __c('Some string with %s %s', 6, array('multiple', 'arguments')); $expected = 'Some string with multiple arguments'; $this->assertEquals($expected, $result); } /** * test __dc() * * @return void */ public function testTranslateDomainCategory() { Configure::write('Config.language', 'rule_1_po'); $result = __dc('default', 'Plural Rule 1', 6); $expected = 'Plural Rule 1 (translated)'; $this->assertEquals($expected, $result); $result = __dc('default', 'Plural Rule 1 (from core)', 6); $expected = 'Plural Rule 1 (from core translated)'; $this->assertEquals($expected, $result); $result = __dc('core', 'Plural Rule 1', 6); $expected = 'Plural Rule 1'; $this->assertEquals($expected, $result); $result = __dc('core', 'Plural Rule 1 (from core)', 6); $expected = 'Plural Rule 1 (from core translated)'; $this->assertEquals($expected, $result); $result = __dc('core', 'Some string with %s', 6, 'arguments'); $expected = 'Some string with arguments'; $this->assertEquals($expected, $result); $result = __dc('core', 'Some string with %s %s', 6, 'multiple', 'arguments'); $expected = 'Some string with multiple arguments'; $this->assertEquals($expected, $result); $result = __dc('core', 'Some string with %s %s', 6, array('multiple', 'arguments')); $expected = 'Some string with multiple arguments'; $this->assertEquals($expected, $result); } /** * test __dcn() * * @return void */ public function testTranslateDomainCategoryPlural() { Configure::write('Config.language', 'rule_1_po'); $result = __dcn('default', '%d = 1', '%d = 0 or > 1', 0, 6); $expected = '%d = 0 or > 1 (translated)'; $this->assertEquals($expected, $result); $result = __dcn('default', '%d = 1 (from core)', '%d = 0 or > 1 (from core)', 1, 6); $expected = '%d = 1 (from core translated)'; $this->assertEquals($expected, $result); $result = __dcn('core', '%d = 1', '%d = 0 or > 1', 0, 6); $expected = '%d = 0 or > 1'; $this->assertEquals($expected, $result); $result = __dcn('core', '%d item.', '%d items.', 1, 6, 1); $expected = '1 item.'; $this->assertEquals($expected, $result); $result = __dcn('core', '%d item for id %s', '%d items for id %s', 2, 6, 2, '1234'); $expected = '2 items for id 1234'; $this->assertEquals($expected, $result); $result = __dcn('core', '%d item for id %s', '%d items for id %s', 2, 6, array(2, '1234')); $expected = '2 items for id 1234'; $this->assertEquals($expected, $result); } /** * test LogError() * * @return void */ public function testLogError() { if (file_exists(LOGS . 'error.log')) { unlink(LOGS . 'error.log'); } // disable stderr output for this test if (CakeLog::stream('stderr')) { CakeLog::disable('stderr'); } LogError('Testing LogError() basic function'); LogError("Testing with\nmulti-line\nstring"); if (CakeLog::stream('stderr')) { CakeLog::enable('stderr'); } $result = file_get_contents(LOGS . 'error.log'); $this->assertRegExp('/Error: Testing LogError\(\) basic function/', $result); $this->assertNotRegExp("/Error: Testing with\nmulti-line\nstring/", $result); $this->assertRegExp('/Error: Testing with multi-line string/', $result); } /** * test fileExistsInPath() * * @return void */ public function testFileExistsInPath() { if (!function_exists('ini_set')) { $this->markTestSkipped('%s ini_set function not available'); } $_includePath = ini_get('include_path'); $path = TMP . 'basics_test'; $folder1 = $path . DS . 'folder1'; $folder2 = $path . DS . 'folder2'; $file1 = $path . DS . 'file1.php'; $file2 = $folder1 . DS . 'file2.php'; $file3 = $folder1 . DS . 'file3.php'; $file4 = $folder2 . DS . 'file4.php'; new Folder($path, true); new Folder($folder1, true); new Folder($folder2, true); touch($file1); touch($file2); touch($file3); touch($file4); ini_set('include_path', $path . PATH_SEPARATOR . $folder1); $this->assertEquals(fileExistsInPath('file1.php'), $file1); $this->assertEquals(fileExistsInPath('file2.php'), $file2); $this->assertEquals(fileExistsInPath('folder1' . DS . 'file2.php'), $file2); $this->assertEquals(fileExistsInPath($file2), $file2); $this->assertEquals(fileExistsInPath('file3.php'), $file3); $this->assertEquals(fileExistsInPath($file4), $file4); $this->assertFalse(fileExistsInPath('file1')); $this->assertFalse(fileExistsInPath('file4.php')); $Folder = new Folder($path); $Folder->delete(); ini_set('include_path', $_includePath); } /** * test convertSlash() * * @return void */ public function testConvertSlash() { $result = convertSlash('\path\to\location\\'); $expected = '\path\to\location\\'; $this->assertEquals($expected, $result); $result = convertSlash('/path/to/location/'); $expected = 'path_to_location'; $this->assertEquals($expected, $result); } /** * test debug() * * @return void */ public function testDebug() { ob_start(); debug('this-is-a-test', false); $result = ob_get_clean(); $expectedText = <<assertEquals($expected, $result); ob_start(); debug('
this-is-a-test
', true); $result = ob_get_clean(); $expectedHtml = << %s (line %d)
'<div>this-is-a-test</div>'
EXPECTED; $expected = sprintf($expectedHtml, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 10); $this->assertEquals($expected, $result); ob_start(); debug('
this-is-a-test
', true, true); $result = ob_get_clean(); $expected = << %s (line %d)
'<div>this-is-a-test</div>'
EXPECTED; $expected = sprintf($expected, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 10); $this->assertEquals($expected, $result); ob_start(); debug('
this-is-a-test
', true, false); $result = ob_get_clean(); $expected = <<
'<div>this-is-a-test</div>'
EXPECTED; $expected = sprintf($expected, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 10); $this->assertEquals($expected, $result); ob_start(); debug('
this-is-a-test
', null); $result = ob_get_clean(); $expectedHtml = << %s (line %d)
'<div>this-is-a-test</div>'
EXPECTED; $expectedText = <<this-is-a-test' ########################### EXPECTED; if (PHP_SAPI === 'cli') { $expected = sprintf($expectedText, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 18); } else { $expected = sprintf($expectedHtml, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 20); } $this->assertEquals($expected, $result); ob_start(); debug('
this-is-a-test
', null, false); $result = ob_get_clean(); $expectedHtml = <<
'<div>this-is-a-test</div>'
EXPECTED; $expectedText = <<this-is-a-test' ########################### EXPECTED; if (PHP_SAPI === 'cli') { $expected = sprintf($expectedText, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 18); } else { $expected = sprintf($expectedHtml, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 19); } $this->assertEquals($expected, $result); ob_start(); debug('
this-is-a-test
', false); $result = ob_get_clean(); $expected = <<this-is-a-test' ########################### EXPECTED; $expected = sprintf($expected, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 9); $this->assertEquals($expected, $result); ob_start(); debug('
this-is-a-test
', false, true); $result = ob_get_clean(); $expected = <<this-is-a-test' ########################### EXPECTED; $expected = sprintf($expected, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 9); $this->assertEquals($expected, $result); ob_start(); debug('
this-is-a-test
', false, false); $result = ob_get_clean(); $expected = <<this-is-a-test' ########################### EXPECTED; $expected = sprintf($expected, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 9); $this->assertEquals($expected, $result); ob_start(); debug(false, false, false); $result = ob_get_clean(); $expected = <<assertEquals($expected, $result); } /** * test pr() * * @return void */ public function testPr() { $this->skipIf(PHP_SAPI === 'cli', 'Skipping web test in cli mode'); ob_start(); pr('this is a test'); $result = ob_get_clean(); $expected = "
this is a test
"; $this->assertEquals($expected, $result); ob_start(); pr(array('this' => 'is', 'a' => 'test')); $result = ob_get_clean(); $expected = "
Array\n(\n    [this] => is\n    [a] => test\n)\n
"; $this->assertEquals($expected, $result); } /** * test pr() * * @return void */ public function testPrCli() { $this->skipIf(PHP_SAPI !== 'cli', 'Skipping cli test in web mode'); ob_start(); pr('this is a test'); $result = ob_get_clean(); $expected = "\nthis is a test\n"; $this->assertEquals($expected, $result); ob_start(); pr(array('this' => 'is', 'a' => 'test')); $result = ob_get_clean(); $expected = "\nArray\n(\n [this] => is\n [a] => test\n)\n\n"; $this->assertEquals($expected, $result); } /** * test stripslashes_deep() * * @return void */ public function testStripslashesDeep() { $this->skipIf(ini_get('magic_quotes_sybase') === '1', 'magic_quotes_sybase is on.'); $this->assertEquals(stripslashes_deep("tes\'t"), "tes't"); $this->assertEquals(stripslashes_deep('tes\\' . chr(0) . 't'), 'tes' . chr(0) . 't'); $this->assertEquals(stripslashes_deep('tes\"t'), 'tes"t'); $this->assertEquals(stripslashes_deep("tes\'t"), "tes't"); $this->assertEquals(stripslashes_deep('te\\st'), 'test'); $nested = array( 'a' => "tes\'t", 'b' => 'tes\\' . chr(0) . 't', 'c' => array( 'd' => 'tes\"t', 'e' => "te\'s\'t", array('f' => "tes\'t") ), 'g' => 'te\\st' ); $expected = array( 'a' => "tes't", 'b' => 'tes' . chr(0) . 't', 'c' => array( 'd' => 'tes"t', 'e' => "te's't", array('f' => "tes't") ), 'g' => 'test' ); $this->assertEquals($expected, stripslashes_deep($nested)); } /** * test stripslashes_deep() with magic_quotes_sybase on * * @return void */ public function testStripslashesDeepSybase() { if (!(ini_get('magic_quotes_sybase') === '1')) { $this->markTestSkipped('magic_quotes_sybase is off'); } $this->assertEquals(stripslashes_deep("tes\'t"), "tes\'t"); $nested = array( 'a' => "tes't", 'b' => "tes''t", 'c' => array( 'd' => "tes'''t", 'e' => "tes''''t", array('f' => "tes''t") ), 'g' => "te'''''st" ); $expected = array( 'a' => "tes't", 'b' => "tes't", 'c' => array( 'd' => "tes''t", 'e' => "tes''t", array('f' => "tes't") ), 'g' => "te'''st" ); $this->assertEquals($expected, stripslashes_deep($nested)); } /** * Tests that the stackTrace() method is a shortcut for Debugger::trace() * * @return void */ public function testStackTrace() { ob_start(); list(, $expected) = array(stackTrace(), Debugger::trace()); $result = ob_get_clean(); $this->assertEquals($expected, $result); $opts = array('args' => true); ob_start(); list(, $expected) = array(stackTrace($opts), Debugger::trace($opts)); $result = ob_get_clean(); $this->assertEquals($expected, $result); } /** * test pluginSplit * * @return void */ public function testPluginSplit() { $result = pluginSplit('Something.else'); $this->assertEquals(array('Something', 'else'), $result); $result = pluginSplit('Something.else.more.dots'); $this->assertEquals(array('Something', 'else.more.dots'), $result); $result = pluginSplit('Somethingelse'); $this->assertEquals(array(null, 'Somethingelse'), $result); $result = pluginSplit('Something.else', true); $this->assertEquals(array('Something.', 'else'), $result); $result = pluginSplit('Something.else.more.dots', true); $this->assertEquals(array('Something.', 'else.more.dots'), $result); $result = pluginSplit('Post', false, 'Blog'); $this->assertEquals(array('Blog', 'Post'), $result); $result = pluginSplit('Blog.Post', false, 'Ultimate'); $this->assertEquals(array('Blog', 'Post'), $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Cache/000077500000000000000000000000001265552240500173505ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Cache/CacheTest.php000066400000000000000000000345701265552240500217350ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Cache * @since CakePHP(tm) v 1.2.0.5432 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Cache', 'Cache'); /** * CacheTest class * * @package Cake.Test.Case.Cache */ class CacheTest extends CakeTestCase { protected $_count = 0; /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->_cacheDisable = Configure::read('Cache.disable'); Configure::write('Cache.disable', false); $this->_defaultCacheConfig = Cache::config('default'); Cache::config('default', array('engine' => 'File', 'path' => TMP . 'tests')); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); Cache::drop('latest'); Cache::drop('page'); Cache::drop('archive'); Configure::write('Cache.disable', $this->_cacheDisable); Cache::config('default', $this->_defaultCacheConfig['settings']); } /** * testConfig method * * @return void */ public function testConfig() { $settings = array('engine' => 'File', 'path' => TMP . 'tests', 'prefix' => 'cake_test_'); $results = Cache::config('new', $settings); $this->assertEquals(Cache::config('new'), $results); $this->assertTrue(isset($results['engine'])); $this->assertTrue(isset($results['settings'])); } /** * testConfigInvalidEngine method * * @expectedException CacheException * @return void */ public function testConfigInvalidEngine() { $settings = array('engine' => 'Imaginary'); Cache::config('imaginary', $settings); } /** * Check that no fatal errors are issued doing normal things when Cache.disable is true. * * @return void */ public function testNonFatalErrorsWithCachedisable() { Configure::write('Cache.disable', true); Cache::config('test', array('engine' => 'File', 'path' => TMP, 'prefix' => 'error_test_')); Cache::write('no_save', 'Noooo!', 'test'); Cache::read('no_save', 'test'); Cache::delete('no_save', 'test'); Cache::set('duration', '+10 minutes'); Configure::write('Cache.disable', false); } /** * test configuring CacheEngines in App/libs * * @return void */ public function testConfigWithLibAndPluginEngines() { App::build(array( 'Lib' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Lib' . DS), 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); $settings = array('engine' => 'TestAppCache', 'path' => TMP, 'prefix' => 'cake_test_'); $result = Cache::config('libEngine', $settings); $this->assertEquals(Cache::config('libEngine'), $result); $settings = array('engine' => 'TestPlugin.TestPluginCache', 'path' => TMP, 'prefix' => 'cake_test_'); $result = Cache::config('pluginLibEngine', $settings); $this->assertEquals(Cache::config('pluginLibEngine'), $result); Cache::drop('libEngine'); Cache::drop('pluginLibEngine'); App::build(); CakePlugin::unload(); } /** * testInvalidConfig method * * Test that the cache class doesn't cause fatal errors with a partial path * * @expectedException PHPUnit_Framework_Error_Warning * @return void */ public function testInvalidConfig() { // In debug mode it would auto create the folder. $debug = Configure::read('debug'); Configure::write('debug', 0); Cache::config('invalid', array( 'engine' => 'File', 'duration' => '+1 year', 'prefix' => 'testing_invalid_', 'path' => 'data/', 'serialize' => true, 'random' => 'wii' )); Cache::read('Test', 'invalid'); Configure::write('debug', $debug); } /** * Test reading from a config that is undefined. * * @return void */ public function testReadNonExistingConfig() { $this->assertFalse(Cache::read('key', 'totally fake')); $this->assertFalse(Cache::write('key', 'value', 'totally fake')); $this->assertFalse(Cache::increment('key', 1, 'totally fake')); $this->assertFalse(Cache::decrement('key', 1, 'totally fake')); } /** * test that trying to configure classes that don't extend CacheEngine fail. * * @expectedException CacheException * @return void */ public function testAttemptingToConfigureANonCacheEngineClass() { $this->getMock('StdClass', array(), array(), 'RubbishEngine'); Cache::config('Garbage', array( 'engine' => 'Rubbish' )); } /** * testConfigChange method * * @return void */ public function testConfigChange() { $_cacheConfigSessions = Cache::config('sessions'); $_cacheConfigTests = Cache::config('tests'); $result = Cache::config('sessions', array('engine' => 'File', 'path' => TMP . 'sessions')); $this->assertEquals(Cache::settings('sessions'), $result['settings']); $result = Cache::config('tests', array('engine' => 'File', 'path' => TMP . 'tests')); $this->assertEquals(Cache::settings('tests'), $result['settings']); Cache::config('sessions', $_cacheConfigSessions['settings']); Cache::config('tests', $_cacheConfigTests['settings']); } /** * test that calling config() sets the 'default' configuration up. * * @return void */ public function testConfigSettingDefaultConfigKey() { Cache::config('test_name', array('engine' => 'File', 'prefix' => 'test_name_')); Cache::write('value_one', 'I am cached', 'test_name'); $result = Cache::read('value_one', 'test_name'); $this->assertEquals('I am cached', $result); $result = Cache::read('value_one'); $this->assertEquals(null, $result); Cache::write('value_one', 'I am in default config!'); $result = Cache::read('value_one'); $this->assertEquals('I am in default config!', $result); $result = Cache::read('value_one', 'test_name'); $this->assertEquals('I am cached', $result); Cache::delete('value_one', 'test_name'); Cache::delete('value_one', 'default'); } /** * testWritingWithConfig method * * @return void */ public function testWritingWithConfig() { $_cacheConfigSessions = Cache::config('sessions'); Cache::write('test_something', 'this is the test data', 'tests'); $expected = array( 'path' => TMP . 'sessions' . DS, 'prefix' => 'cake_', 'lock' => true, 'serialize' => true, 'duration' => 3600, 'probability' => 100, 'engine' => 'File', 'isWindows' => DIRECTORY_SEPARATOR === '\\', 'mask' => 0664, 'groups' => array() ); $this->assertEquals($expected, Cache::settings('sessions')); Cache::config('sessions', $_cacheConfigSessions['settings']); } /** * testGroupConfigs method * * @return void */ public function testGroupConfigs() { Cache::config('latest', array( 'duration' => 300, 'engine' => 'File', 'groups' => array( 'posts', 'comments', ), )); $expected = array( 'posts' => array('latest'), 'comments' => array('latest'), ); $result = Cache::groupConfigs(); $this->assertEquals($expected, $result); $result = Cache::groupConfigs('posts'); $this->assertEquals(array('posts' => array('latest')), $result); Cache::config('page', array( 'duration' => 86400, 'engine' => 'File', 'groups' => array( 'posts', 'archive' ), )); $result = Cache::groupConfigs(); $expected = array( 'posts' => array('latest', 'page'), 'comments' => array('latest'), 'archive' => array('page'), ); $this->assertEquals($expected, $result); $result = Cache::groupConfigs('archive'); $this->assertEquals(array('archive' => array('page')), $result); Cache::config('archive', array( 'duration' => 86400 * 30, 'engine' => 'File', 'groups' => array( 'posts', 'archive', 'comments', ), )); $result = Cache::groupConfigs('archive'); $this->assertEquals(array('archive' => array('archive', 'page')), $result); } /** * testGroupConfigsThrowsException method * * @expectedException CacheException * @return void */ public function testGroupConfigsThrowsException() { Cache::groupConfigs('bogus'); } /** * test that configured returns an array of the currently configured cache * settings * * @return void */ public function testConfigured() { $result = Cache::configured(); $this->assertTrue(in_array('_cake_core_', $result)); $this->assertTrue(in_array('default', $result)); } /** * testInitSettings method * * @return void */ public function testInitSettings() { $initial = Cache::settings(); $override = array('engine' => 'File', 'path' => TMP . 'tests'); Cache::config('for_test', $override); $settings = Cache::settings(); $expecting = $override + $initial; $this->assertEquals($settings, $expecting); } /** * test that drop removes cache configs, and that further attempts to use that config * do not work. * * @return void */ public function testDrop() { App::build(array( 'Lib' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Lib' . DS), 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); $result = Cache::drop('some_config_that_does_not_exist'); $this->assertFalse($result); $_testsConfig = Cache::config('tests'); $result = Cache::drop('tests'); $this->assertTrue($result); Cache::config('unconfigTest', array( 'engine' => 'TestAppCache' )); $this->assertTrue(Cache::isInitialized('unconfigTest')); $this->assertTrue(Cache::drop('unconfigTest')); $this->assertFalse(Cache::isInitialized('TestAppCache')); Cache::config('tests', $_testsConfig); App::build(); } /** * testWriteEmptyValues method * * @return void */ public function testWriteEmptyValues() { Cache::write('App.falseTest', false); $this->assertFalse(Cache::read('App.falseTest')); Cache::write('App.trueTest', true); $this->assertTrue(Cache::read('App.trueTest')); Cache::write('App.nullTest', null); $this->assertNull(Cache::read('App.nullTest')); Cache::write('App.zeroTest', 0); $this->assertSame(Cache::read('App.zeroTest'), 0); Cache::write('App.zeroTest2', '0'); $this->assertSame(Cache::read('App.zeroTest2'), '0'); } /** * Test that failed writes cause errors to be triggered. * * @return void */ public function testWriteTriggerError() { App::build(array( 'Lib' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Lib' . DS), 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); Cache::config('test_trigger', array('engine' => 'TestAppCache', 'prefix' => '')); try { Cache::write('fail', 'value', 'test_trigger'); $this->fail('No exception thrown'); } catch (PHPUnit_Framework_Error $e) { $this->assertTrue(true); } Cache::drop('test_trigger'); App::build(); } /** * testCacheDisable method * * Check that the "Cache.disable" configuration and a change to it * (even after a cache config has been setup) is taken into account. * * @return void */ public function testCacheDisable() { Configure::write('Cache.disable', false); Cache::config('test_cache_disable_1', array('engine' => 'File', 'path' => TMP . 'tests')); $this->assertTrue(Cache::write('key_1', 'hello', 'test_cache_disable_1')); $this->assertSame(Cache::read('key_1', 'test_cache_disable_1'), 'hello'); Configure::write('Cache.disable', true); $this->assertFalse(Cache::write('key_2', 'hello', 'test_cache_disable_1')); $this->assertFalse(Cache::read('key_2', 'test_cache_disable_1')); Configure::write('Cache.disable', false); $this->assertTrue(Cache::write('key_3', 'hello', 'test_cache_disable_1')); $this->assertSame(Cache::read('key_3', 'test_cache_disable_1'), 'hello'); Configure::write('Cache.disable', true); Cache::config('test_cache_disable_2', array('engine' => 'File', 'path' => TMP . 'tests')); $this->assertFalse(Cache::write('key_4', 'hello', 'test_cache_disable_2')); $this->assertFalse(Cache::read('key_4', 'test_cache_disable_2')); Configure::write('Cache.disable', false); $this->assertTrue(Cache::write('key_5', 'hello', 'test_cache_disable_2')); $this->assertSame(Cache::read('key_5', 'test_cache_disable_2'), 'hello'); Configure::write('Cache.disable', true); $this->assertFalse(Cache::write('key_6', 'hello', 'test_cache_disable_2')); $this->assertFalse(Cache::read('key_6', 'test_cache_disable_2')); } /** * testSet method * * @return void */ public function testSet() { $_cacheSet = Cache::set(); Cache::set(array('duration' => '+1 year')); $data = Cache::read('test_cache'); $this->assertFalse($data); $data = 'this is just a simple test of the cache system'; $write = Cache::write('test_cache', $data); $this->assertTrue($write); Cache::set(array('duration' => '+1 year')); $data = Cache::read('test_cache'); $this->assertEquals('this is just a simple test of the cache system', $data); Cache::delete('test_cache'); Cache::settings(); Cache::set($_cacheSet); } /** * test set() parameter handling for user cache configs. * * @return void */ public function testSetOnAlternateConfigs() { Cache::config('file_config', array('engine' => 'File', 'prefix' => 'test_file_')); Cache::set(array('duration' => '+1 year'), 'file_config'); $settings = Cache::settings('file_config'); $this->assertEquals('test_file_', $settings['prefix']); $this->assertEquals(strtotime('+1 year') - time(), $settings['duration']); } /** * test remember method. * * @return void */ public function testRemember() { $expected = 'This is some data 0'; $result = Cache::remember('test_key', array($this, 'cacher'), 'default'); $this->assertEquals($expected, $result); $this->_count = 1; $result = Cache::remember('test_key', array($this, 'cacher'), 'default'); $this->assertEquals($expected, $result); } /** * Method for testing Cache::remember() * * @return string */ public function cacher() { return 'This is some data ' . $this->_count; } /** * Test add method. * * @return void */ public function testAdd() { Cache::delete('test_add_key', 'default'); $result = Cache::add('test_add_key', 'test data', 'default'); $this->assertTrue($result); $expected = 'test data'; $result = Cache::read('test_add_key', 'default'); $this->assertEquals($expected, $result); $result = Cache::add('test_add_key', 'test data 2', 'default'); $this->assertFalse($result); } } cakephp-2.8.0/lib/Cake/Test/Case/Cache/Engine/000077500000000000000000000000001265552240500205555ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Cache/Engine/ApcEngineTest.php000066400000000000000000000175001265552240500237620ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Cache.Engine * @since CakePHP(tm) v 1.2.0.5434 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Cache', 'Cache'); /** * ApcEngineTest class * * @package Cake.Test.Case.Cache.Engine */ class ApcEngineTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->skipIf(!function_exists('apc_store'), 'Apc is not installed or configured properly.'); if (PHP_SAPI === 'cli') { $this->skipIf(!ini_get('apc.enable_cli'), 'APC is not enabled for the CLI.'); } $this->_cacheDisable = Configure::read('Cache.disable'); Configure::write('Cache.disable', false); Cache::config('apc', array('engine' => 'Apc', 'prefix' => 'cake_')); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); Configure::write('Cache.disable', $this->_cacheDisable); Cache::drop('apc'); Cache::drop('apc_groups'); Cache::config('default'); } /** * testReadAndWriteCache method * * @return void */ public function testReadAndWriteCache() { Cache::set(array('duration' => 1), 'apc'); $result = Cache::read('test', 'apc'); $expecting = ''; $this->assertEquals($expecting, $result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('test', $data, 'apc'); $this->assertTrue($result); $result = Cache::read('test', 'apc'); $expecting = $data; $this->assertEquals($expecting, $result); Cache::delete('test', 'apc'); } /** * Writing cache entries with duration = 0 (forever) should work. * * @return void */ public function testReadWriteDurationZero() { Cache::config('apc', array('engine' => 'Apc', 'duration' => 0, 'prefix' => 'cake_')); Cache::write('zero', 'Should save', 'apc'); sleep(1); $result = Cache::read('zero', 'apc'); $this->assertEquals('Should save', $result); } /** * testExpiry method * * @return void */ public function testExpiry() { Cache::set(array('duration' => 1), 'apc'); $result = Cache::read('test', 'apc'); $this->assertFalse($result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data, 'apc'); $this->assertTrue($result); sleep(2); $result = Cache::read('other_test', 'apc'); $this->assertFalse($result); Cache::set(array('duration' => 1), 'apc'); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data, 'apc'); $this->assertTrue($result); sleep(2); $result = Cache::read('other_test', 'apc'); $this->assertFalse($result); sleep(2); $result = Cache::read('other_test', 'apc'); $this->assertFalse($result); } /** * testDeleteCache method * * @return void */ public function testDeleteCache() { $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('delete_test', $data, 'apc'); $this->assertTrue($result); $result = Cache::delete('delete_test', 'apc'); $this->assertTrue($result); } /** * testDecrement method * * @return void */ public function testDecrement() { $this->skipIf(!function_exists('apc_dec'), 'No apc_dec() function, cannot test decrement().'); $result = Cache::write('test_decrement', 5, 'apc'); $this->assertTrue($result); $result = Cache::decrement('test_decrement', 1, 'apc'); $this->assertEquals(4, $result); $result = Cache::read('test_decrement', 'apc'); $this->assertEquals(4, $result); $result = Cache::decrement('test_decrement', 2, 'apc'); $this->assertEquals(2, $result); $result = Cache::read('test_decrement', 'apc'); $this->assertEquals(2, $result); } /** * testIncrement method * * @return void */ public function testIncrement() { $this->skipIf(!function_exists('apc_inc'), 'No apc_inc() function, cannot test increment().'); $result = Cache::write('test_increment', 5, 'apc'); $this->assertTrue($result); $result = Cache::increment('test_increment', 1, 'apc'); $this->assertEquals(6, $result); $result = Cache::read('test_increment', 'apc'); $this->assertEquals(6, $result); $result = Cache::increment('test_increment', 2, 'apc'); $this->assertEquals(8, $result); $result = Cache::read('test_increment', 'apc'); $this->assertEquals(8, $result); } /** * test the clearing of cache keys * * @return void */ public function testClear() { apc_store('not_cake', 'survive'); Cache::write('some_value', 'value', 'apc'); $result = Cache::clear(false, 'apc'); $this->assertTrue($result); $this->assertFalse(Cache::read('some_value', 'apc')); $this->assertEquals('survive', apc_fetch('not_cake')); apc_delete('not_cake'); } /** * Tests that configuring groups for stored keys return the correct values when read/written * Shows that altering the group value is equivalent to deleting all keys under the same * group * * @return void */ public function testGroupsReadWrite() { Cache::config('apc_groups', array( 'engine' => 'Apc', 'duration' => 0, 'groups' => array('group_a', 'group_b'), 'prefix' => 'test_' )); $this->assertTrue(Cache::write('test_groups', 'value', 'apc_groups')); $this->assertEquals('value', Cache::read('test_groups', 'apc_groups')); apc_inc('test_group_a'); $this->assertFalse(Cache::read('test_groups', 'apc_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'apc_groups')); $this->assertEquals('value2', Cache::read('test_groups', 'apc_groups')); apc_inc('test_group_b'); $this->assertFalse(Cache::read('test_groups', 'apc_groups')); $this->assertTrue(Cache::write('test_groups', 'value3', 'apc_groups')); $this->assertEquals('value3', Cache::read('test_groups', 'apc_groups')); } /** * Tests that deleteing from a groups-enabled config is possible * * @return void */ public function testGroupDelete() { Cache::config('apc_groups', array( 'engine' => 'Apc', 'duration' => 0, 'groups' => array('group_a', 'group_b'), 'prefix' => 'test_' )); $this->assertTrue(Cache::write('test_groups', 'value', 'apc_groups')); $this->assertEquals('value', Cache::read('test_groups', 'apc_groups')); $this->assertTrue(Cache::delete('test_groups', 'apc_groups')); $this->assertFalse(Cache::read('test_groups', 'apc_groups')); } /** * Test clearing a cache group * * @return void */ public function testGroupClear() { Cache::config('apc_groups', array( 'engine' => 'Apc', 'duration' => 0, 'groups' => array('group_a', 'group_b'), 'prefix' => 'test_' )); $this->assertTrue(Cache::write('test_groups', 'value', 'apc_groups')); $this->assertTrue(Cache::clearGroup('group_a', 'apc_groups')); $this->assertFalse(Cache::read('test_groups', 'apc_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'apc_groups')); $this->assertTrue(Cache::clearGroup('group_b', 'apc_groups')); $this->assertFalse(Cache::read('test_groups', 'apc_groups')); } /** * Test add method. * * @return void */ public function testAdd() { Cache::delete('test_add_key', 'apc'); $result = Cache::add('test_add_key', 'test data', 'apc'); $this->assertTrue($result); $expected = 'test data'; $result = Cache::read('test_add_key', 'apc'); $this->assertEquals($expected, $result); $result = Cache::add('test_add_key', 'test data 2', 'apc'); $this->assertFalse($result); } } cakephp-2.8.0/lib/Cake/Test/Case/Cache/Engine/FileEngineTest.php000066400000000000000000000465671265552240500241550ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Cache.Engine * @since CakePHP(tm) v 1.2.0.5434 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Cache', 'Cache'); /** * FileEngineTest class * * @package Cake.Test.Case.Cache.Engine */ class FileEngineTest extends CakeTestCase { /** * config property * * @var array */ public $config = array(); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); Configure::write('Cache.disable', false); Cache::config('file_test', array('engine' => 'File', 'path' => CACHE)); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); // Cache::clear(false, 'file_test'); Cache::drop('file_test'); Cache::drop('file_groups'); Cache::drop('file_groups2'); Cache::drop('file_groups3'); } /** * testCacheDirChange method * * @return void */ public function testCacheDirChange() { $result = Cache::config('sessions', array('engine' => 'File', 'path' => TMP . 'sessions')); $this->assertEquals(Cache::settings('sessions'), $result['settings']); $result = Cache::config('sessions', array('engine' => 'File', 'path' => TMP . 'tests')); $this->assertEquals(Cache::settings('sessions'), $result['settings']); $this->assertNotEquals(Cache::settings('default'), $result['settings']); } /** * testReadAndWriteCache method * * @return void */ public function testReadAndWriteCache() { Cache::config('default'); $result = Cache::write(null, 'here', 'file_test'); $this->assertFalse($result); Cache::set(array('duration' => 1), 'file_test'); $result = Cache::read('test', 'file_test'); $expecting = ''; $this->assertEquals($expecting, $result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('test', $data, 'file_test'); $this->assertTrue(file_exists(CACHE . 'cake_test')); $result = Cache::read('test', 'file_test'); $expecting = $data; $this->assertEquals($expecting, $result); Cache::delete('test', 'file_test'); } /** * Test read/write on the same cache key. Ensures file handles are re-wound. * * @return void */ public function testConsecutiveReadWrite() { Cache::write('rw', 'first write', 'file_test'); $result = Cache::read('rw', 'file_test'); Cache::write('rw', 'second write', 'file_test'); $resultB = Cache::read('rw', 'file_test'); Cache::delete('rw', 'file_test'); $this->assertEquals('first write', $result); $this->assertEquals('second write', $resultB); } /** * testExpiry method * * @return void */ public function testExpiry() { Cache::set(array('duration' => 1), 'file_test'); $result = Cache::read('test', 'file_test'); $this->assertFalse($result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data, 'file_test'); $this->assertTrue($result); sleep(2); $result = Cache::read('other_test', 'file_test'); $this->assertFalse($result); Cache::set(array('duration' => "+1 second"), 'file_test'); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data, 'file_test'); $this->assertTrue($result); sleep(2); $result = Cache::read('other_test', 'file_test'); $this->assertFalse($result); } /** * testDeleteCache method * * @return void */ public function testDeleteCache() { $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('delete_test', $data, 'file_test'); $this->assertTrue($result); $result = Cache::delete('delete_test', 'file_test'); $this->assertTrue($result); $this->assertFalse(file_exists(TMP . 'tests' . DS . 'delete_test')); $result = Cache::delete('delete_test', 'file_test'); $this->assertFalse($result); } /** * testSerialize method * * @return void */ public function testSerialize() { Cache::config('file_test', array('engine' => 'File', 'serialize' => true)); $data = 'this is a test of the emergency broadcasting system'; $write = Cache::write('serialize_test', $data, 'file_test'); $this->assertTrue($write); Cache::config('file_test', array('serialize' => false)); $read = Cache::read('serialize_test', 'file_test'); $newread = Cache::read('serialize_test', 'file_test'); Cache::delete('serialize_test', 'file_test'); $this->assertSame($read, serialize($data)); $this->assertSame(unserialize($newread), $data); } /** * testClear method * * @return void */ public function testClear() { Cache::config('file_test', array('engine' => 'File', 'duration' => 1)); $data = 'this is a test of the emergency broadcasting system'; Cache::write('serialize_test1', $data, 'file_test'); Cache::write('serialize_test2', $data, 'file_test'); Cache::write('serialize_test3', $data, 'file_test'); $this->assertTrue(file_exists(CACHE . 'cake_serialize_test1')); $this->assertTrue(file_exists(CACHE . 'cake_serialize_test2')); $this->assertTrue(file_exists(CACHE . 'cake_serialize_test3')); sleep(2); $result = Cache::clear(true, 'file_test'); $this->assertTrue($result); $this->assertFalse(file_exists(CACHE . 'cake_serialize_test1')); $this->assertFalse(file_exists(CACHE . 'cake_serialize_test2')); $this->assertFalse(file_exists(CACHE . 'cake_serialize_test3')); $data = 'this is a test of the emergency broadcasting system'; Cache::write('serialize_test1', $data, 'file_test'); Cache::write('serialize_test2', $data, 'file_test'); Cache::write('serialize_test3', $data, 'file_test'); $this->assertTrue(file_exists(CACHE . 'cake_serialize_test1')); $this->assertTrue(file_exists(CACHE . 'cake_serialize_test2')); $this->assertTrue(file_exists(CACHE . 'cake_serialize_test3')); $result = Cache::clear(false, 'file_test'); $this->assertTrue($result); $this->assertFalse(file_exists(CACHE . 'cake_serialize_test1')); $this->assertFalse(file_exists(CACHE . 'cake_serialize_test2')); $this->assertFalse(file_exists(CACHE . 'cake_serialize_test3')); } /** * test that clear() doesn't wipe files not in the current engine's prefix. * * @return void */ public function testClearWithPrefixes() { $FileOne = new FileEngine(); $FileOne->init(array( 'prefix' => 'prefix_one_', 'duration' => DAY )); $FileTwo = new FileEngine(); $FileTwo->init(array( 'prefix' => 'prefix_two_', 'duration' => DAY )); $dataOne = $dataTwo = $expected = 'content to cache'; $FileOne->write('prefix_one_key_one', $dataOne, DAY); $FileTwo->write('prefix_two_key_two', $dataTwo, DAY); $this->assertEquals($expected, $FileOne->read('prefix_one_key_one')); $this->assertEquals($expected, $FileTwo->read('prefix_two_key_two')); $FileOne->clear(false); $this->assertEquals($expected, $FileTwo->read('prefix_two_key_two'), 'secondary config was cleared by accident.'); $FileTwo->clear(false); } /** * Test that clear() also removes files with group tags. * * @return void */ public function testClearWithGroups() { $engine = new FileEngine(); $engine->init(array( 'prefix' => 'cake_test_', 'duration' => DAY, 'groups' => array('short', 'round') )); $key = 'cake_test_test_key'; $engine->write($key, 'it works', DAY); $engine->clear(false); $this->assertFalse($engine->read($key), 'Key should have been removed'); } /** * Test that clear() also removes files with group tags. * * @return void */ public function testClearWithNoKeys() { $engine = new FileEngine(); $engine->init(array( 'prefix' => 'cake_test_', 'duration' => DAY, 'groups' => array('one', 'two') )); $key = 'cake_test_test_key'; $engine->clear(false); $this->assertFalse($engine->read($key), 'No errors should be found'); } /** * testKeyPath method * * @return void */ public function testKeyPath() { $result = Cache::write('views.countries.something', 'here', 'file_test'); $this->assertTrue($result); $this->assertTrue(file_exists(CACHE . 'cake_views_countries_something')); $result = Cache::read('views.countries.something', 'file_test'); $this->assertEquals('here', $result); $result = Cache::clear(false, 'file_test'); $this->assertTrue($result); $result = Cache::write('domain.test.com:8080', 'here', 'file_test'); $this->assertTrue($result); $this->assertTrue(file_exists(CACHE . 'cake_domain_test_com_8080')); $result = Cache::write('command>dir|more', 'here', 'file_test'); $this->assertTrue($result); $this->assertTrue(file_exists(CACHE . 'cake_command_dir_more')); } /** * testRemoveWindowsSlashesFromCache method * * @return void */ public function testRemoveWindowsSlashesFromCache() { Cache::config('windows_test', array('engine' => 'File', 'isWindows' => true, 'prefix' => null, 'path' => TMP)); $expected = array( 'C:\dev\prj2\sites\cake\libs' => array( 0 => 'C:\dev\prj2\sites\cake\libs', 1 => 'C:\dev\prj2\sites\cake\libs\view', 2 => 'C:\dev\prj2\sites\cake\libs\view\scaffolds', 3 => 'C:\dev\prj2\sites\cake\libs\view\pages', 4 => 'C:\dev\prj2\sites\cake\libs\view\layouts', 5 => 'C:\dev\prj2\sites\cake\libs\view\layouts\xml', 6 => 'C:\dev\prj2\sites\cake\libs\view\layouts\rss', 7 => 'C:\dev\prj2\sites\cake\libs\view\layouts\js', 8 => 'C:\dev\prj2\sites\cake\libs\view\layouts\email', 9 => 'C:\dev\prj2\sites\cake\libs\view\layouts\email\text', 10 => 'C:\dev\prj2\sites\cake\libs\view\layouts\email\html', 11 => 'C:\dev\prj2\sites\cake\libs\view\helpers', 12 => 'C:\dev\prj2\sites\cake\libs\view\errors', 13 => 'C:\dev\prj2\sites\cake\libs\view\elements', 14 => 'C:\dev\prj2\sites\cake\libs\view\elements\email', 15 => 'C:\dev\prj2\sites\cake\libs\view\elements\email\text', 16 => 'C:\dev\prj2\sites\cake\libs\view\elements\email\html', 17 => 'C:\dev\prj2\sites\cake\libs\model', 18 => 'C:\dev\prj2\sites\cake\libs\model\datasources', 19 => 'C:\dev\prj2\sites\cake\libs\model\datasources\dbo', 20 => 'C:\dev\prj2\sites\cake\libs\model\behaviors', 21 => 'C:\dev\prj2\sites\cake\libs\controller', 22 => 'C:\dev\prj2\sites\cake\libs\controller\components', 23 => 'C:\dev\prj2\sites\cake\libs\cache'), 'C:\dev\prj2\sites\main_site\vendors' => array( 0 => 'C:\dev\prj2\sites\main_site\vendors', 1 => 'C:\dev\prj2\sites\main_site\vendors\shells', 2 => 'C:\dev\prj2\sites\main_site\vendors\shells\templates', 3 => 'C:\dev\prj2\sites\main_site\vendors\shells\templates\cdc_project', 4 => 'C:\dev\prj2\sites\main_site\vendors\shells\tasks', 5 => 'C:\dev\prj2\sites\main_site\vendors\js', 6 => 'C:\dev\prj2\sites\main_site\vendors\css'), 'C:\dev\prj2\sites\vendors' => array( 0 => 'C:\dev\prj2\sites\vendors', 1 => 'C:\dev\prj2\sites\vendors\simpletest', 2 => 'C:\dev\prj2\sites\vendors\simpletest\test', 3 => 'C:\dev\prj2\sites\vendors\simpletest\test\support', 4 => 'C:\dev\prj2\sites\vendors\simpletest\test\support\collector', 5 => 'C:\dev\prj2\sites\vendors\simpletest\extensions', 6 => 'C:\dev\prj2\sites\vendors\simpletest\extensions\testdox', 7 => 'C:\dev\prj2\sites\vendors\simpletest\docs', 8 => 'C:\dev\prj2\sites\vendors\simpletest\docs\fr', 9 => 'C:\dev\prj2\sites\vendors\simpletest\docs\en'), 'C:\dev\prj2\sites\main_site\views\helpers' => array( 0 => 'C:\dev\prj2\sites\main_site\views\helpers') ); Cache::write('test_dir_map', $expected, 'windows_test'); $data = Cache::read('test_dir_map', 'windows_test'); Cache::delete('test_dir_map', 'windows_test'); $this->assertEquals($expected, $data); Cache::drop('windows_test'); } /** * testWriteQuotedString method * * @return void */ public function testWriteQuotedString() { Cache::config('file_test', array('engine' => 'File', 'path' => TMP . 'tests')); Cache::write('App.doubleQuoteTest', '"this is a quoted string"', 'file_test'); $this->assertSame(Cache::read('App.doubleQuoteTest', 'file_test'), '"this is a quoted string"'); Cache::write('App.singleQuoteTest', "'this is a quoted string'", 'file_test'); $this->assertSame(Cache::read('App.singleQuoteTest', 'file_test'), "'this is a quoted string'"); Cache::config('file_test', array('isWindows' => true, 'path' => TMP . 'tests')); $this->assertSame(Cache::read('App.doubleQuoteTest', 'file_test'), '"this is a quoted string"'); Cache::write('App.singleQuoteTest', "'this is a quoted string'", 'file_test'); $this->assertSame(Cache::read('App.singleQuoteTest', 'file_test'), "'this is a quoted string'"); Cache::delete('App.singleQuoteTest', 'file_test'); Cache::delete('App.doubleQuoteTest', 'file_test'); } /** * check that FileEngine does not generate an error when a configured Path does not exist in debug mode. * * @return void */ public function testPathDoesNotExist() { $this->skipIf(is_dir(TMP . 'tests' . DS . 'autocreate'), 'Cannot run if test directory exists.'); Cache::config('autocreate', array( 'engine' => 'File', 'path' => TMP . 'tests' . DS . 'autocreate' )); Cache::drop('autocreate'); } /** * Testing the mask setting in FileEngine * * @return void */ public function testMaskSetting() { if (DS === '\\') { $this->markTestSkipped('File permission testing does not work on Windows.'); } Cache::config('mask_test', array('engine' => 'File', 'path' => TMP . 'tests')); $data = 'This is some test content'; $write = Cache::write('masking_test', $data, 'mask_test'); $result = substr(sprintf('%o', fileperms(TMP . 'tests' . DS . 'cake_masking_test')), -4); $expected = '0664'; $this->assertEquals($expected, $result); Cache::delete('masking_test', 'mask_test'); Cache::drop('mask_test'); Cache::config('mask_test', array('engine' => 'File', 'mask' => 0666, 'path' => TMP . 'tests')); Cache::write('masking_test', $data, 'mask_test'); $result = substr(sprintf('%o', fileperms(TMP . 'tests' . DS . 'cake_masking_test')), -4); $expected = '0666'; $this->assertEquals($expected, $result); Cache::delete('masking_test', 'mask_test'); Cache::drop('mask_test'); Cache::config('mask_test', array('engine' => 'File', 'mask' => 0644, 'path' => TMP . 'tests')); Cache::write('masking_test', $data, 'mask_test'); $result = substr(sprintf('%o', fileperms(TMP . 'tests' . DS . 'cake_masking_test')), -4); $expected = '0644'; $this->assertEquals($expected, $result); Cache::delete('masking_test', 'mask_test'); Cache::drop('mask_test'); Cache::config('mask_test', array('engine' => 'File', 'mask' => 0640, 'path' => TMP . 'tests')); Cache::write('masking_test', $data, 'mask_test'); $result = substr(sprintf('%o', fileperms(TMP . 'tests' . DS . 'cake_masking_test')), -4); $expected = '0640'; $this->assertEquals($expected, $result); Cache::delete('masking_test', 'mask_test'); Cache::drop('mask_test'); } /** * Tests that configuring groups for stored keys return the correct values when read/written * * @return void */ public function testGroupsReadWrite() { Cache::config('file_groups', array('engine' => 'File', 'duration' => 3600, 'groups' => array('group_a', 'group_b'))); $this->assertTrue(Cache::write('test_groups', 'value', 'file_groups')); $this->assertEquals('value', Cache::read('test_groups', 'file_groups')); $this->assertTrue(Cache::write('test_groups2', 'value2', 'file_groups')); $this->assertTrue(Cache::write('test_groups3', 'value3', 'file_groups')); } /** * Test that clearing with repeat writes works properly * * @return void */ public function testClearingWithRepeatWrites() { Cache::config('repeat', array( 'engine' => 'File', 'groups' => array('users') )); $this->assertTrue(Cache::write('user', 'rchavik', 'repeat')); $this->assertEquals('rchavik', Cache::read('user', 'repeat')); Cache::delete('user', 'repeat'); $this->assertEquals(false, Cache::read('user', 'repeat')); $this->assertTrue(Cache::write('user', 'ADmad', 'repeat')); $this->assertEquals('ADmad', Cache::read('user', 'repeat')); Cache::clearGroup('users', 'repeat'); $this->assertEquals(false, Cache::read('user', 'repeat')); $this->assertTrue(Cache::write('user', 'markstory', 'repeat')); $this->assertEquals('markstory', Cache::read('user', 'repeat')); Cache::drop('repeat'); } /** * Tests that deleting from a groups-enabled config is possible * * @return void */ public function testGroupDelete() { Cache::config('file_groups', array( 'engine' => 'File', 'duration' => 3600, 'groups' => array('group_a', 'group_b') )); $this->assertTrue(Cache::write('test_groups', 'value', 'file_groups')); $this->assertEquals('value', Cache::read('test_groups', 'file_groups')); $this->assertTrue(Cache::delete('test_groups', 'file_groups')); $this->assertFalse(Cache::read('test_groups', 'file_groups')); } /** * Test clearing a cache group * * @return void */ public function testGroupClear() { Cache::config('file_groups', array('engine' => 'File', 'duration' => 3600, 'groups' => array('group_a', 'group_b'))); Cache::config('file_groups2', array('engine' => 'File', 'duration' => 3600, 'groups' => array('group_b'))); Cache::config('file_groups3', array( 'engine' => 'File', 'duration' => 3600, 'groups' => array('group_b'), 'prefix' => 'leading_', )); $this->assertTrue(Cache::write('test_groups', 'value', 'file_groups')); $this->assertTrue(Cache::write('test_groups2', 'value 2', 'file_groups2')); $this->assertTrue(Cache::write('test_groups3', 'value 3', 'file_groups3')); $this->assertTrue(Cache::clearGroup('group_b', 'file_groups')); $this->assertFalse(Cache::read('test_groups', 'file_groups')); $this->assertFalse(Cache::read('test_groups2', 'file_groups2')); $this->assertEquals('value 3', Cache::read('test_groups3', 'file_groups3')); $this->assertTrue(Cache::write('test_groups4', 'value', 'file_groups')); $this->assertTrue(Cache::write('test_groups5', 'value 2', 'file_groups2')); $this->assertTrue(Cache::write('test_groups6', 'value 3', 'file_groups3')); $this->assertTrue(Cache::clearGroup('group_b', 'file_groups')); $this->assertFalse(Cache::read('test_groups4', 'file_groups')); $this->assertFalse(Cache::read('test_groups5', 'file_groups2')); $this->assertEquals('value 3', Cache::read('test_groups6', 'file_groups3')); } /** * Test that clearGroup works with no prefix. * * @return void */ public function testGroupClearNoPrefix() { Cache::config('file_groups', array( 'engine' => 'File', 'duration' => 3600, 'prefix' => '', 'groups' => array('group_a', 'group_b') )); Cache::write('key_1', 'value', 'file_groups'); Cache::write('key_2', 'value', 'file_groups'); Cache::clearGroup('group_a', 'file_groups'); $this->assertFalse(Cache::read('key_1', 'file_groups'), 'Did not delete'); $this->assertFalse(Cache::read('key_2', 'file_groups'), 'Did not delete'); } /** * Test add method. * * @return void */ public function testAdd() { Cache::delete('test_add_key', 'file_test'); $result = Cache::add('test_add_key', 'test data', 'file_test'); $this->assertTrue($result); $expected = 'test data'; $result = Cache::read('test_add_key', 'file_test'); $this->assertEquals($expected, $result); $result = Cache::add('test_add_key', 'test data 2', 'file_test'); $this->assertFalse($result); } } cakephp-2.8.0/lib/Cake/Test/Case/Cache/Engine/MemcacheEngineTest.php000066400000000000000000000332671265552240500247710ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Cache.Engine * @since CakePHP(tm) v 1.2.0.5434 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Cache', 'Cache'); App::uses('MemcacheEngine', 'Cache/Engine'); /** * Class TestMemcacheEngine * * @package Cake.Test.Case.Cache.Engine */ class TestMemcacheEngine extends MemcacheEngine { /** * public accessor to _parseServerString * * @param string $server * @return array */ public function parseServerString($server) { return $this->_parseServerString($server); } public function setMemcache($memcache) { $this->_Memcache = $memcache; } } /** * MemcacheEngineTest class * * @package Cake.Test.Case.Cache.Engine */ class MemcacheEngineTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->skipIf(!class_exists('Memcache'), 'Memcache is not installed or configured properly.'); $this->_cacheDisable = Configure::read('Cache.disable'); Configure::write('Cache.disable', false); Cache::config('memcache', array( 'engine' => 'Memcache', 'prefix' => 'cake_', 'duration' => 3600 )); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); Configure::write('Cache.disable', $this->_cacheDisable); Cache::drop('memcache'); Cache::drop('memcache_groups'); Cache::drop('memcache_helper'); Cache::config('default'); } /** * testSettings method * * @return void */ public function testSettings() { $settings = Cache::settings('memcache'); unset($settings['serialize'], $settings['path']); $expecting = array( 'prefix' => 'cake_', 'duration' => 3600, 'probability' => 100, 'servers' => array('127.0.0.1'), 'persistent' => true, 'compress' => false, 'engine' => 'Memcache', 'groups' => array() ); $this->assertEquals($expecting, $settings); } /** * testSettings method * * @return void */ public function testMultipleServers() { $servers = array('127.0.0.1:11211', '127.0.0.1:11222'); $available = true; $Memcache = new Memcache(); foreach ($servers as $server) { list($host, $port) = explode(':', $server); //@codingStandardsIgnoreStart if (!@$Memcache->connect($host, $port)) { $available = false; } //@codingStandardsIgnoreEnd } $this->skipIf(!$available, 'Need memcache servers at ' . implode(', ', $servers) . ' to run this test.'); $Memcache = new MemcacheEngine(); $Memcache->init(array('engine' => 'Memcache', 'servers' => $servers)); $settings = $Memcache->settings(); $this->assertEquals($settings['servers'], $servers); Cache::drop('dual_server'); } /** * testConnect method * * @return void */ public function testConnect() { $Memcache = new MemcacheEngine(); $Memcache->init(Cache::settings('memcache')); $result = $Memcache->connect('127.0.0.1'); $this->assertTrue($result); } /** * test connecting to an ipv6 server. * * @return void */ public function testConnectIpv6() { $Memcache = new MemcacheEngine(); $result = $Memcache->init(array( 'prefix' => 'cake_', 'duration' => 200, 'engine' => 'Memcache', 'servers' => array( '[::1]:11211' ) )); $this->assertTrue($result); } /** * test domain starts with u * * @return void */ public function testParseServerStringWithU() { $Memcached = new TestMemcachedEngine(); $result = $Memcached->parseServerString('udomain.net:13211'); $this->assertEquals(array('udomain.net', '13211'), $result); } /** * test non latin domains. * * @return void */ public function testParseServerStringNonLatin() { $Memcache = new TestMemcacheEngine(); $result = $Memcache->parseServerString('schรผlervz.net:13211'); $this->assertEquals(array('schรผlervz.net', '13211'), $result); $result = $Memcache->parseServerString('sรผlรผl:1111'); $this->assertEquals(array('sรผlรผl', '1111'), $result); } /** * test unix sockets. * * @return void */ public function testParseServerStringUnix() { $Memcache = new TestMemcacheEngine(); $result = $Memcache->parseServerString('unix:///path/to/memcached.sock'); $this->assertEquals(array('unix:///path/to/memcached.sock', 0), $result); } /** * testReadAndWriteCache method * * @return void */ public function testReadAndWriteCache() { Cache::set(array('duration' => 1), null, 'memcache'); $result = Cache::read('test', 'memcache'); $expecting = ''; $this->assertEquals($expecting, $result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('test', $data, 'memcache'); $this->assertTrue($result); $result = Cache::read('test', 'memcache'); $expecting = $data; $this->assertEquals($expecting, $result); Cache::delete('test', 'memcache'); } /** * testExpiry method * * @return void */ public function testExpiry() { Cache::set(array('duration' => 1), 'memcache'); $result = Cache::read('test', 'memcache'); $this->assertFalse($result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data, 'memcache'); $this->assertTrue($result); sleep(2); $result = Cache::read('other_test', 'memcache'); $this->assertFalse($result); Cache::set(array('duration' => "+1 second"), 'memcache'); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data, 'memcache'); $this->assertTrue($result); sleep(3); $result = Cache::read('other_test', 'memcache'); $this->assertFalse($result); Cache::config('memcache', array('duration' => '+1 second')); $result = Cache::read('other_test', 'memcache'); $this->assertFalse($result); Cache::config('memcache', array('duration' => '+29 days')); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('long_expiry_test', $data, 'memcache'); $this->assertTrue($result); sleep(2); $result = Cache::read('long_expiry_test', 'memcache'); $expecting = $data; $this->assertEquals($expecting, $result); Cache::config('memcache', array('duration' => 3600)); } /** * testDeleteCache method * * @return void */ public function testDeleteCache() { $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('delete_test', $data, 'memcache'); $this->assertTrue($result); $result = Cache::delete('delete_test', 'memcache'); $this->assertTrue($result); } /** * testDecrement method * * @return void */ public function testDecrement() { $result = Cache::write('test_decrement', 5, 'memcache'); $this->assertTrue($result); $result = Cache::decrement('test_decrement', 1, 'memcache'); $this->assertEquals(4, $result); $result = Cache::read('test_decrement', 'memcache'); $this->assertEquals(4, $result); $result = Cache::decrement('test_decrement', 2, 'memcache'); $this->assertEquals(2, $result); $result = Cache::read('test_decrement', 'memcache'); $this->assertEquals(2, $result); } /** * testIncrement method * * @return void */ public function testIncrement() { $result = Cache::write('test_increment', 5, 'memcache'); $this->assertTrue($result); $result = Cache::increment('test_increment', 1, 'memcache'); $this->assertEquals(6, $result); $result = Cache::read('test_increment', 'memcache'); $this->assertEquals(6, $result); $result = Cache::increment('test_increment', 2, 'memcache'); $this->assertEquals(8, $result); $result = Cache::read('test_increment', 'memcache'); $this->assertEquals(8, $result); } /** * test that configurations don't conflict, when a file engine is declared after a memcache one. * * @return void */ public function testConfigurationConflict() { Cache::config('long_memcache', array( 'engine' => 'Memcache', 'duration' => '+2 seconds', 'servers' => array('127.0.0.1:11211'), )); Cache::config('short_memcache', array( 'engine' => 'Memcache', 'duration' => '+1 seconds', 'servers' => array('127.0.0.1:11211'), )); Cache::config('some_file', array('engine' => 'File')); $this->assertTrue(Cache::write('duration_test', 'yay', 'long_memcache')); $this->assertTrue(Cache::write('short_duration_test', 'boo', 'short_memcache')); $this->assertEquals('yay', Cache::read('duration_test', 'long_memcache'), 'Value was not read %s'); $this->assertEquals('boo', Cache::read('short_duration_test', 'short_memcache'), 'Value was not read %s'); sleep(1); $this->assertEquals('yay', Cache::read('duration_test', 'long_memcache'), 'Value was not read %s'); sleep(2); $this->assertFalse(Cache::read('short_duration_test', 'short_memcache'), 'Cache was not invalidated %s'); $this->assertFalse(Cache::read('duration_test', 'long_memcache'), 'Value did not expire %s'); Cache::delete('duration_test', 'long_memcache'); Cache::delete('short_duration_test', 'short_memcache'); } /** * test clearing memcache. * * @return void */ public function testClear() { Cache::config('memcache2', array( 'engine' => 'Memcache', 'prefix' => 'cake2_', 'duration' => 3600 )); Cache::write('some_value', 'cache1', 'memcache'); $result = Cache::clear(true, 'memcache'); $this->assertTrue($result); $this->assertEquals('cache1', Cache::read('some_value', 'memcache')); Cache::write('some_value', 'cache2', 'memcache2'); $result = Cache::clear(false, 'memcache'); $this->assertTrue($result); $this->assertFalse(Cache::read('some_value', 'memcache')); $this->assertEquals('cache2', Cache::read('some_value', 'memcache2')); Cache::clear(false, 'memcache2'); } /** * test that a 0 duration can successfully write. * * @return void */ public function testZeroDuration() { Cache::config('memcache', array('duration' => 0)); $result = Cache::write('test_key', 'written!', 'memcache'); $this->assertTrue($result); $result = Cache::read('test_key', 'memcache'); $this->assertEquals('written!', $result); } /** * test that durations greater than 30 days never expire * * @return void */ public function testLongDurationEqualToZero() { $memcache = new TestMemcacheEngine(); $memcache->settings['compress'] = false; $mock = $this->getMock('Memcache'); $memcache->setMemcache($mock); $mock->expects($this->once()) ->method('set') ->with('key', 'value', false, 0); $value = 'value'; $memcache->write('key', $value, 50 * DAY); } /** * Tests that configuring groups for stored keys return the correct values when read/written * Shows that altering the group value is equivalent to deleting all keys under the same * group * * @return void */ public function testGroupReadWrite() { Cache::config('memcache_groups', array( 'engine' => 'Memcache', 'duration' => 3600, 'groups' => array('group_a', 'group_b'), 'prefix' => 'test_' )); Cache::config('memcache_helper', array( 'engine' => 'Memcache', 'duration' => 3600, 'prefix' => 'test_' )); $this->assertTrue(Cache::write('test_groups', 'value', 'memcache_groups')); $this->assertEquals('value', Cache::read('test_groups', 'memcache_groups')); Cache::increment('group_a', 1, 'memcache_helper'); $this->assertFalse(Cache::read('test_groups', 'memcache_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'memcache_groups')); $this->assertEquals('value2', Cache::read('test_groups', 'memcache_groups')); Cache::increment('group_b', 1, 'memcache_helper'); $this->assertFalse(Cache::read('test_groups', 'memcache_groups')); $this->assertTrue(Cache::write('test_groups', 'value3', 'memcache_groups')); $this->assertEquals('value3', Cache::read('test_groups', 'memcache_groups')); } /** * Tests that deleteing from a groups-enabled config is possible * * @return void */ public function testGroupDelete() { Cache::config('memcache_groups', array( 'engine' => 'Memcache', 'duration' => 3600, 'groups' => array('group_a', 'group_b') )); $this->assertTrue(Cache::write('test_groups', 'value', 'memcache_groups')); $this->assertEquals('value', Cache::read('test_groups', 'memcache_groups')); $this->assertTrue(Cache::delete('test_groups', 'memcache_groups')); $this->assertFalse(Cache::read('test_groups', 'memcache_groups')); } /** * Test clearing a cache group * * @return void */ public function testGroupClear() { Cache::config('memcache_groups', array( 'engine' => 'Memcache', 'duration' => 3600, 'groups' => array('group_a', 'group_b') )); $this->assertTrue(Cache::write('test_groups', 'value', 'memcache_groups')); $this->assertTrue(Cache::clearGroup('group_a', 'memcache_groups')); $this->assertFalse(Cache::read('test_groups', 'memcache_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'memcache_groups')); $this->assertTrue(Cache::clearGroup('group_b', 'memcache_groups')); $this->assertFalse(Cache::read('test_groups', 'memcache_groups')); } /** * Test that failed add write return false. * * @return void */ public function testAdd() { Cache::delete('test_add_key', 'memcache'); $result = Cache::add('test_add_key', 'test data', 'memcache'); $this->assertTrue($result); $expected = 'test data'; $result = Cache::read('test_add_key', 'memcache'); $this->assertEquals($expected, $result); $result = Cache::add('test_add_key', 'test data 2', 'memcache'); $this->assertFalse($result); } } cakephp-2.8.0/lib/Cake/Test/Case/Cache/Engine/MemcachedEngineTest.php000066400000000000000000000525221265552240500251300ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Cache.Engine * @since CakePHP(tm) v 2.5.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Cache', 'Cache'); App::uses('MemcachedEngine', 'Cache/Engine'); /** * Class TestMemcachedEngine * * @package Cake.Test.Case.Cache.Engine */ class TestMemcachedEngine extends MemcachedEngine { /** * public accessor to _parseServerString * * @param string $server * @return array */ public function parseServerString($server) { return $this->_parseServerString($server); } public function setMemcached($memcached) { $this->_Memcached = $memcached; } public function getMemcached() { return $this->_Memcached; } } /** * MemcachedEngineTest class * * @package Cake.Test.Case.Cache.Engine */ class MemcachedEngineTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->skipIf(!class_exists('Memcached'), 'Memcached is not installed or configured properly.'); Cache::config('memcached', array( 'engine' => 'Memcached', 'prefix' => 'cake_', 'duration' => 3600 )); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); Cache::drop('memcached'); Cache::drop('memcached_groups'); Cache::drop('memcached_helper'); Cache::config('default'); } /** * testSettings method * * @return void */ public function testSettings() { $settings = Cache::settings('memcached'); unset($settings['path']); $expecting = array( 'prefix' => 'cake_', 'duration' => 3600, 'probability' => 100, 'servers' => array('127.0.0.1'), 'persistent' => false, 'compress' => false, 'engine' => 'Memcached', 'login' => null, 'password' => null, 'groups' => array(), 'serialize' => 'php', 'options' => array() ); $this->assertEquals($expecting, $settings); } /** * testCompressionSetting method * * @return void */ public function testCompressionSetting() { $Memcached = new TestMemcachedEngine(); $Memcached->init(array( 'engine' => 'Memcached', 'servers' => array('127.0.0.1:11211'), 'compress' => false )); $this->assertFalse($Memcached->getMemcached()->getOption(Memcached::OPT_COMPRESSION)); $MemcachedCompressed = new TestMemcachedEngine(); $MemcachedCompressed->init(array( 'engine' => 'Memcached', 'servers' => array('127.0.0.1:11211'), 'compress' => true )); $this->assertTrue($MemcachedCompressed->getMemcached()->getOption(Memcached::OPT_COMPRESSION)); } /** * test setting options * * @return void */ public function testOptionsSetting() { $memcached = new TestMemcachedEngine(); $memcached->init(array( 'engine' => 'Memcached', 'servers' => array('127.0.0.1:11211'), 'options' => array( Memcached::OPT_BINARY_PROTOCOL => true ) )); $this->assertEquals(1, $memcached->getMemcached()->getOption(Memcached::OPT_BINARY_PROTOCOL)); } /** * test accepts only valid serializer engine * * @return void */ public function testInvalidSerializerSetting() { $Memcached = new TestMemcachedEngine(); $settings = array( 'engine' => 'Memcached', 'servers' => array('127.0.0.1:11211'), 'persistent' => false, 'serialize' => 'invalid_serializer' ); $this->setExpectedException( 'CacheException', 'invalid_serializer is not a valid serializer engine for Memcached' ); $Memcached->init($settings); } /** * testPhpSerializerSetting method * * @return void */ public function testPhpSerializerSetting() { $Memcached = new TestMemcachedEngine(); $settings = array( 'engine' => 'Memcached', 'servers' => array('127.0.0.1:11211'), 'persistent' => false, 'serialize' => 'php' ); $Memcached->init($settings); $this->assertEquals(Memcached::SERIALIZER_PHP, $Memcached->getMemcached()->getOption(Memcached::OPT_SERIALIZER)); } /** * testJsonSerializerSetting method * * @return void */ public function testJsonSerializerSetting() { $this->skipIf( !Memcached::HAVE_JSON, 'Memcached extension is not compiled with json support' ); $Memcached = new TestMemcachedEngine(); $settings = array( 'engine' => 'Memcached', 'servers' => array('127.0.0.1:11211'), 'persistent' => false, 'serialize' => 'json' ); $Memcached->init($settings); $this->assertEquals(Memcached::SERIALIZER_JSON, $Memcached->getMemcached()->getOption(Memcached::OPT_SERIALIZER)); } /** * testIgbinarySerializerSetting method * * @return void */ public function testIgbinarySerializerSetting() { $this->skipIf( !Memcached::HAVE_IGBINARY, 'Memcached extension is not compiled with igbinary support' ); $Memcached = new TestMemcachedEngine(); $settings = array( 'engine' => 'Memcached', 'servers' => array('127.0.0.1:11211'), 'persistent' => false, 'serialize' => 'igbinary' ); $Memcached->init($settings); $this->assertEquals(Memcached::SERIALIZER_IGBINARY, $Memcached->getMemcached()->getOption(Memcached::OPT_SERIALIZER)); } /** * testMsgpackSerializerSetting method * * @return void */ public function testMsgpackSerializerSetting() { $this->skipIf( !defined('Memcached::HAVE_MSGPACK') || !Memcached::HAVE_MSGPACK, 'Memcached extension is not compiled with msgpack support' ); $Memcached = new TestMemcachedEngine(); $settings = array( 'engine' => 'Memcached', 'servers' => array('127.0.0.1:11211'), 'persistent' => false, 'serialize' => 'msgpack' ); $Memcached->init($settings); $this->assertEquals(Memcached::SERIALIZER_MSGPACK, $Memcached->getMemcached()->getOption(Memcached::OPT_SERIALIZER)); } /** * testJsonSerializerThrowException method * * @return void */ public function testJsonSerializerThrowException() { $this->skipIf( Memcached::HAVE_JSON, 'Memcached extension is compiled with json support' ); $Memcached = new TestMemcachedEngine(); $settings = array( 'engine' => 'Memcached', 'servers' => array('127.0.0.1:11211'), 'persistent' => false, 'serialize' => 'json' ); $this->setExpectedException( 'CacheException', 'Memcached extension is not compiled with json support' ); $Memcached->init($settings); } /** * testMsgpackSerializerThrowException method * * @return void */ public function testMsgpackSerializerThrowException() { $this->skipIf( defined('Memcached::HAVE_MSGPACK') && Memcached::HAVE_MSGPACK, 'Memcached extension is compiled with msgpack support' ); $Memcached = new TestMemcachedEngine(); $settings = array( 'engine' => 'Memcached', 'servers' => array('127.0.0.1:11211'), 'persistent' => false, 'serialize' => 'msgpack' ); $this->setExpectedException( 'CacheException', 'msgpack is not a valid serializer engine for Memcached' ); $Memcached->init($settings); } /** * testIgbinarySerializerThrowException method * * @return void */ public function testIgbinarySerializerThrowException() { $this->skipIf( Memcached::HAVE_IGBINARY, 'Memcached extension is compiled with igbinary support' ); $Memcached = new TestMemcachedEngine(); $settings = array( 'engine' => 'Memcached', 'servers' => array('127.0.0.1:11211'), 'persistent' => false, 'serialize' => 'igbinary' ); $this->setExpectedException( 'CacheException', 'Memcached extension is not compiled with igbinary support' ); $Memcached->init($settings); } /** * test using authentication without memcached installed with SASL support * throw an exception * * @return void */ public function testSaslAuthException() { $Memcached = new TestMemcachedEngine(); $settings = array( 'engine' => 'Memcached', 'servers' => array('127.0.0.1:11211'), 'persistent' => false, 'login' => 'test', 'password' => 'password' ); $this->setExpectedException('PHPUnit_Framework_Error_Warning'); $Memcached->init($settings); } /** * testSettings method * * @return void */ public function testMultipleServers() { $servers = array('127.0.0.1:11211', '127.0.0.1:11222'); $available = true; $Memcached = new Memcached(); foreach ($servers as $server) { list($host, $port) = explode(':', $server); //@codingStandardsIgnoreStart if (!$Memcached->addServer($host, $port)) { $available = false; } //@codingStandardsIgnoreEnd } $this->skipIf(!$available, 'Need memcached servers at ' . implode(', ', $servers) . ' to run this test.'); $Memcached = new MemcachedEngine(); $Memcached->init(array('engine' => 'Memcached', 'servers' => $servers)); $settings = $Memcached->settings(); $this->assertEquals($settings['servers'], $servers); Cache::drop('dual_server'); } /** * test connecting to an ipv6 server. * * @return void */ public function testConnectIpv6() { $Memcached = new MemcachedEngine(); $result = $Memcached->init(array( 'prefix' => 'cake_', 'duration' => 200, 'engine' => 'Memcached', 'servers' => array( '[::1]:11211' ) )); $this->assertTrue($result); } /** * test domain starts with u * * @return void */ public function testParseServerStringWithU() { $Memcached = new TestMemcachedEngine(); $result = $Memcached->parseServerString('udomain.net:13211'); $this->assertEquals(array('udomain.net', '13211'), $result); } /** * test non latin domains. * * @return void */ public function testParseServerStringNonLatin() { $Memcached = new TestMemcachedEngine(); $result = $Memcached->parseServerString('schรผlervz.net:13211'); $this->assertEquals(array('schรผlervz.net', '13211'), $result); $result = $Memcached->parseServerString('sรผlรผl:1111'); $this->assertEquals(array('sรผlรผl', '1111'), $result); } /** * test unix sockets. * * @return void */ public function testParseServerStringUnix() { $Memcached = new TestMemcachedEngine(); $result = $Memcached->parseServerString('unix:///path/to/memcachedd.sock'); $this->assertEquals(array('/path/to/memcachedd.sock', 0), $result); } /** * testReadAndWriteCache method * * @return void */ public function testReadAndWriteCache() { Cache::set(array('duration' => 1), null, 'memcached'); $result = Cache::read('test', 'memcached'); $expecting = ''; $this->assertEquals($expecting, $result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('test', $data, 'memcached'); $this->assertTrue($result); $result = Cache::read('test', 'memcached'); $expecting = $data; $this->assertEquals($expecting, $result); Cache::delete('test', 'memcached'); } /** * testExpiry method * * @return void */ public function testExpiry() { Cache::set(array('duration' => 1), 'memcached'); $result = Cache::read('test', 'memcached'); $this->assertFalse($result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data, 'memcached'); $this->assertTrue($result); sleep(2); $result = Cache::read('other_test', 'memcached'); $this->assertFalse($result); Cache::set(array('duration' => "+1 second"), 'memcached'); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data, 'memcached'); $this->assertTrue($result); sleep(3); $result = Cache::read('other_test', 'memcached'); $this->assertFalse($result); Cache::config('memcached', array('duration' => '+1 second')); $result = Cache::read('other_test', 'memcached'); $this->assertFalse($result); Cache::config('memcached', array('duration' => '+29 days')); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('long_expiry_test', $data, 'memcached'); $this->assertTrue($result); sleep(2); $result = Cache::read('long_expiry_test', 'memcached'); $expecting = $data; $this->assertEquals($expecting, $result); Cache::config('memcached', array('duration' => 3600)); } /** * testDeleteCache method * * @return void */ public function testDeleteCache() { $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('delete_test', $data, 'memcached'); $this->assertTrue($result); $result = Cache::delete('delete_test', 'memcached'); $this->assertTrue($result); } /** * testDecrement method * * @return void */ public function testDecrement() { $result = Cache::write('test_decrement', 5, 'memcached'); $this->assertTrue($result); $result = Cache::decrement('test_decrement', 1, 'memcached'); $this->assertEquals(4, $result); $result = Cache::read('test_decrement', 'memcached'); $this->assertEquals(4, $result); $result = Cache::decrement('test_decrement', 2, 'memcached'); $this->assertEquals(2, $result); $result = Cache::read('test_decrement', 'memcached'); $this->assertEquals(2, $result); Cache::delete('test_decrement', 'memcached'); } /** * test decrementing compressed keys * * @return void */ public function testDecrementCompressedKeys() { Cache::config('compressed_memcached', array( 'engine' => 'Memcached', 'duration' => '+2 seconds', 'servers' => array('127.0.0.1:11211'), 'compress' => true )); $result = Cache::write('test_decrement', 5, 'compressed_memcached'); $this->assertTrue($result); $result = Cache::decrement('test_decrement', 1, 'compressed_memcached'); $this->assertEquals(4, $result); $result = Cache::read('test_decrement', 'compressed_memcached'); $this->assertEquals(4, $result); $result = Cache::decrement('test_decrement', 2, 'compressed_memcached'); $this->assertEquals(2, $result); $result = Cache::read('test_decrement', 'compressed_memcached'); $this->assertEquals(2, $result); Cache::delete('test_decrement', 'compressed_memcached'); } /** * testIncrement method * * @return void */ public function testIncrement() { $result = Cache::write('test_increment', 5, 'memcached'); $this->assertTrue($result); $result = Cache::increment('test_increment', 1, 'memcached'); $this->assertEquals(6, $result); $result = Cache::read('test_increment', 'memcached'); $this->assertEquals(6, $result); $result = Cache::increment('test_increment', 2, 'memcached'); $this->assertEquals(8, $result); $result = Cache::read('test_increment', 'memcached'); $this->assertEquals(8, $result); Cache::delete('test_increment', 'memcached'); } /** * test incrementing compressed keys * * @return void */ public function testIncrementCompressedKeys() { Cache::config('compressed_memcached', array( 'engine' => 'Memcached', 'duration' => '+2 seconds', 'servers' => array('127.0.0.1:11211'), 'compress' => true )); $result = Cache::write('test_increment', 5, 'compressed_memcached'); $this->assertTrue($result); $result = Cache::increment('test_increment', 1, 'compressed_memcached'); $this->assertEquals(6, $result); $result = Cache::read('test_increment', 'compressed_memcached'); $this->assertEquals(6, $result); $result = Cache::increment('test_increment', 2, 'compressed_memcached'); $this->assertEquals(8, $result); $result = Cache::read('test_increment', 'compressed_memcached'); $this->assertEquals(8, $result); Cache::delete('test_increment', 'compressed_memcached'); } /** * test that configurations don't conflict, when a file engine is declared after a memcached one. * * @return void */ public function testConfigurationConflict() { Cache::config('long_memcached', array( 'engine' => 'Memcached', 'duration' => '+2 seconds', 'servers' => array('127.0.0.1:11211'), )); Cache::config('short_memcached', array( 'engine' => 'Memcached', 'duration' => '+1 seconds', 'servers' => array('127.0.0.1:11211'), )); Cache::config('some_file', array('engine' => 'File')); $this->assertTrue(Cache::write('duration_test', 'yay', 'long_memcached')); $this->assertTrue(Cache::write('short_duration_test', 'boo', 'short_memcached')); $this->assertEquals('yay', Cache::read('duration_test', 'long_memcached'), 'Value was not read %s'); $this->assertEquals('boo', Cache::read('short_duration_test', 'short_memcached'), 'Value was not read %s'); sleep(1); $this->assertEquals('yay', Cache::read('duration_test', 'long_memcached'), 'Value was not read %s'); sleep(2); $this->assertFalse(Cache::read('short_duration_test', 'short_memcached'), 'Cache was not invalidated %s'); $this->assertFalse(Cache::read('duration_test', 'long_memcached'), 'Value did not expire %s'); Cache::delete('duration_test', 'long_memcached'); Cache::delete('short_duration_test', 'short_memcached'); } /** * test clearing memcached. * * @return void */ public function testClear() { Cache::config('memcached2', array( 'engine' => 'Memcached', 'prefix' => 'cake2_', 'duration' => 3600 )); Cache::write('some_value', 'cache1', 'memcached'); $result = Cache::clear(true, 'memcached'); $this->assertTrue($result); $this->assertEquals('cache1', Cache::read('some_value', 'memcached')); Cache::write('some_value', 'cache2', 'memcached2'); $result = Cache::clear(false, 'memcached'); $this->assertTrue($result); $this->assertFalse(Cache::read('some_value', 'memcached')); $this->assertEquals('cache2', Cache::read('some_value', 'memcached2')); Cache::clear(false, 'memcached2'); } /** * test that a 0 duration can successfully write. * * @return void */ public function testZeroDuration() { Cache::config('memcached', array('duration' => 0)); $result = Cache::write('test_key', 'written!', 'memcached'); $this->assertTrue($result); $result = Cache::read('test_key', 'memcached'); $this->assertEquals('written!', $result); } /** * test that durations greater than 30 days never expire * * @return void */ public function testLongDurationEqualToZero() { $this->markTestSkipped('Cannot run as Memcached cannot be reflected'); $memcached = new TestMemcachedEngine(); $memcached->settings['compress'] = false; $mock = $this->getMock('Memcached'); $memcached->setMemcached($mock); $mock->expects($this->once()) ->method('set') ->with('key', 'value', 0); $value = 'value'; $memcached->write('key', $value, 50 * DAY); } /** * Tests that configuring groups for stored keys return the correct values when read/written * Shows that altering the group value is equivalent to deleting all keys under the same * group * * @return void */ public function testGroupReadWrite() { Cache::config('memcached_groups', array( 'engine' => 'Memcached', 'duration' => 3600, 'groups' => array('group_a', 'group_b'), 'prefix' => 'test_' )); Cache::config('memcached_helper', array( 'engine' => 'Memcached', 'duration' => 3600, 'prefix' => 'test_' )); $this->assertTrue(Cache::write('test_groups', 'value', 'memcached_groups')); $this->assertEquals('value', Cache::read('test_groups', 'memcached_groups')); Cache::increment('group_a', 1, 'memcached_helper'); $this->assertFalse(Cache::read('test_groups', 'memcached_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'memcached_groups')); $this->assertEquals('value2', Cache::read('test_groups', 'memcached_groups')); Cache::increment('group_b', 1, 'memcached_helper'); $this->assertFalse(Cache::read('test_groups', 'memcached_groups')); $this->assertTrue(Cache::write('test_groups', 'value3', 'memcached_groups')); $this->assertEquals('value3', Cache::read('test_groups', 'memcached_groups')); } /** * Tests that deleteing from a groups-enabled config is possible * * @return void */ public function testGroupDelete() { Cache::config('memcached_groups', array( 'engine' => 'Memcached', 'duration' => 3600, 'groups' => array('group_a', 'group_b') )); $this->assertTrue(Cache::write('test_groups', 'value', 'memcached_groups')); $this->assertEquals('value', Cache::read('test_groups', 'memcached_groups')); $this->assertTrue(Cache::delete('test_groups', 'memcached_groups')); $this->assertFalse(Cache::read('test_groups', 'memcached_groups')); } /** * Test clearing a cache group * * @return void */ public function testGroupClear() { Cache::config('memcached_groups', array( 'engine' => 'Memcached', 'duration' => 3600, 'groups' => array('group_a', 'group_b') )); $this->assertTrue(Cache::write('test_groups', 'value', 'memcached_groups')); $this->assertTrue(Cache::clearGroup('group_a', 'memcached_groups')); $this->assertFalse(Cache::read('test_groups', 'memcached_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'memcached_groups')); $this->assertTrue(Cache::clearGroup('group_b', 'memcached_groups')); $this->assertFalse(Cache::read('test_groups', 'memcached_groups')); } /** * Test add method. * * @return void */ public function testAdd() { Cache::set(array('duration' => 1), null, 'memcached'); Cache::delete('test_add_key', 'default'); $result = Cache::add('test_add_key', 'test data', 'default'); $this->assertTrue($result); $expected = 'test data'; $result = Cache::read('test_add_key', 'default'); $this->assertEquals($expected, $result); $result = Cache::add('test_add_key', 'test data 2', 'default'); $this->assertFalse($result); } } cakephp-2.8.0/lib/Cake/Test/Case/Cache/Engine/RedisEngineTest.php000066400000000000000000000246601265552240500243320ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests * @package Cake.Test.Case.Cache.Engine * @since CakePHP(tm) v 2.2 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Cache', 'Cache'); App::uses('RedisEngine', 'Cache/Engine'); /** * RedisEngineTest class * * @package Cake.Test.Case.Cache.Engine */ class RedisEngineTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->skipIf(!class_exists('Redis'), 'Redis is not installed or configured properly.'); $this->_cacheDisable = Configure::read('Cache.disable'); Configure::write('Cache.disable', false); Cache::config('redis', array( 'engine' => 'Redis', 'prefix' => 'cake_', 'duration' => 3600 )); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); Configure::write('Cache.disable', $this->_cacheDisable); Cache::drop(''); Cache::drop('redis_groups'); Cache::drop('redis_helper'); Cache::config('default'); } /** * testSettings method * * @return void */ public function testSettings() { $settings = Cache::settings('redis'); $expecting = array( 'prefix' => 'cake_', 'duration' => 3600, 'probability' => 100, 'groups' => array(), 'engine' => 'Redis', 'server' => '127.0.0.1', 'port' => 6379, 'timeout' => 0, 'persistent' => true, 'password' => false, 'database' => 0, 'unix_socket' => false, ); $this->assertEquals($expecting, $settings); } /** * testConnect method * * @return void */ public function testConnect() { $Redis = new RedisEngine(); $this->assertTrue($Redis->init(Cache::settings('redis'))); } /** * testMultiDatabaseOperations method * * @return void */ public function testMultiDatabaseOperations() { Cache::config('redisdb0', array( 'engine' => 'Redis', 'prefix' => 'cake2_', 'duration' => 3600, 'persistent' => false, )); Cache::config('redisdb1', array( 'engine' => 'Redis', 'database' => 1, 'prefix' => 'cake2_', 'duration' => 3600, 'persistent' => false, )); $result = Cache::write('save_in_0', true, 'redisdb0'); $exist = Cache::read('save_in_0', 'redisdb0'); $this->assertTrue($result); $this->assertTrue($exist); $result = Cache::write('save_in_1', true, 'redisdb1'); $this->assertTrue($result); $exist = Cache::read('save_in_0', 'redisdb1'); $this->assertFalse($exist); $exist = Cache::read('save_in_1', 'redisdb1'); $this->assertTrue($exist); Cache::delete('save_in_0', 'redisdb0'); $exist = Cache::read('save_in_0', 'redisdb0'); $this->assertFalse($exist); Cache::delete('save_in_1', 'redisdb1'); $exist = Cache::read('save_in_1', 'redisdb1'); $this->assertFalse($exist); Cache::drop('redisdb0'); Cache::drop('redisdb1'); } /** * testReadAndWriteCache method * * @return void */ public function testReadAndWriteCache() { Cache::set(array('duration' => 1), null, 'redis'); $result = Cache::read('test', 'redis'); $expecting = ''; $this->assertEquals($expecting, $result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('test', $data, 'redis'); $this->assertTrue($result); $result = Cache::read('test', 'redis'); $expecting = $data; $this->assertEquals($expecting, $result); $data = array(1, 2, 3); $this->assertTrue(Cache::write('array_data', $data, 'redis')); $this->assertEquals($data, Cache::read('array_data', 'redis')); Cache::delete('test', 'redis'); } /** * testExpiry method * * @return void */ public function testExpiry() { Cache::set(array('duration' => 1), 'redis'); $result = Cache::read('test', 'redis'); $this->assertFalse($result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data, 'redis'); $this->assertTrue($result); sleep(2); $result = Cache::read('other_test', 'redis'); $this->assertFalse($result); Cache::set(array('duration' => "+1 second"), 'redis'); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data, 'redis'); $this->assertTrue($result); sleep(2); $result = Cache::read('other_test', 'redis'); $this->assertFalse($result); Cache::config('redis', array('duration' => '+1 second')); sleep(2); $result = Cache::read('other_test', 'redis'); $this->assertFalse($result); Cache::config('redis', array('duration' => '+29 days')); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('long_expiry_test', $data, 'redis'); $this->assertTrue($result); sleep(2); $result = Cache::read('long_expiry_test', 'redis'); $expecting = $data; $this->assertEquals($expecting, $result); Cache::config('redis', array('duration' => 3600)); } /** * testDeleteCache method * * @return void */ public function testDeleteCache() { $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('delete_test', $data, 'redis'); $this->assertTrue($result); $result = Cache::delete('delete_test', 'redis'); $this->assertTrue($result); } /** * testDecrement method * * @return void */ public function testDecrement() { Cache::delete('test_decrement', 'redis'); $result = Cache::write('test_decrement', 5, 'redis'); $this->assertTrue($result); $result = Cache::decrement('test_decrement', 1, 'redis'); $this->assertEquals(4, $result); $result = Cache::read('test_decrement', 'redis'); $this->assertEquals(4, $result); $result = Cache::decrement('test_decrement', 2, 'redis'); $this->assertEquals(2, $result); $result = Cache::read('test_decrement', 'redis'); $this->assertEquals(2, $result); } /** * testIncrement method * * @return void */ public function testIncrement() { Cache::delete('test_increment', 'redis'); $result = Cache::increment('test_increment', 1, 'redis'); $this->assertEquals(1, $result); $result = Cache::read('test_increment', 'redis'); $this->assertEquals(1, $result); $result = Cache::increment('test_increment', 2, 'redis'); $this->assertEquals(3, $result); $result = Cache::read('test_increment', 'redis'); $this->assertEquals(3, $result); } /** * test clearing redis. * * @return void */ public function testClear() { Cache::config('redis2', array( 'engine' => 'Redis', 'prefix' => 'cake2_', 'duration' => 3600 )); Cache::write('some_value', 'cache1', 'redis'); $result = Cache::clear(true, 'redis'); $this->assertTrue($result); $this->assertEquals('cache1', Cache::read('some_value', 'redis')); Cache::write('some_value', 'cache2', 'redis2'); $result = Cache::clear(false, 'redis'); $this->assertTrue($result); $this->assertFalse(Cache::read('some_value', 'redis')); $this->assertEquals('cache2', Cache::read('some_value', 'redis2')); Cache::clear(false, 'redis2'); } /** * test that a 0 duration can successfully write. * * @return void */ public function testZeroDuration() { Cache::config('redis', array('duration' => 0)); $result = Cache::write('test_key', 'written!', 'redis'); $this->assertTrue($result); $result = Cache::read('test_key', 'redis'); $this->assertEquals('written!', $result); } /** * Tests that configuring groups for stored keys return the correct values when read/written * Shows that altering the group value is equivalent to deleting all keys under the same * group * * @return void */ public function testGroupReadWrite() { Cache::config('redis_groups', array( 'engine' => 'Redis', 'duration' => 3600, 'groups' => array('group_a', 'group_b'), 'prefix' => 'test_' )); Cache::config('redis_helper', array( 'engine' => 'Redis', 'duration' => 3600, 'prefix' => 'test_' )); $this->assertTrue(Cache::write('test_groups', 'value', 'redis_groups')); $this->assertEquals('value', Cache::read('test_groups', 'redis_groups')); Cache::increment('group_a', 1, 'redis_helper'); $this->assertFalse(Cache::read('test_groups', 'redis_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'redis_groups')); $this->assertEquals('value2', Cache::read('test_groups', 'redis_groups')); Cache::increment('group_b', 1, 'redis_helper'); $this->assertFalse(Cache::read('test_groups', 'redis_groups')); $this->assertTrue(Cache::write('test_groups', 'value3', 'redis_groups')); $this->assertEquals('value3', Cache::read('test_groups', 'redis_groups')); } /** * Tests that deleteing from a groups-enabled config is possible * * @return void */ public function testGroupDelete() { Cache::config('redis_groups', array( 'engine' => 'Redis', 'duration' => 3600, 'groups' => array('group_a', 'group_b') )); $this->assertTrue(Cache::write('test_groups', 'value', 'redis_groups')); $this->assertEquals('value', Cache::read('test_groups', 'redis_groups')); $this->assertTrue(Cache::delete('test_groups', 'redis_groups')); $this->assertFalse(Cache::read('test_groups', 'redis_groups')); } /** * Test clearing a cache group * * @return void */ public function testGroupClear() { Cache::config('redis_groups', array( 'engine' => 'Redis', 'duration' => 3600, 'groups' => array('group_a', 'group_b') )); $this->assertTrue(Cache::write('test_groups', 'value', 'redis_groups')); $this->assertTrue(Cache::clearGroup('group_a', 'redis_groups')); $this->assertFalse(Cache::read('test_groups', 'redis_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'redis_groups')); $this->assertTrue(Cache::clearGroup('group_b', 'redis_groups')); $this->assertFalse(Cache::read('test_groups', 'redis_groups')); } /** * Test add method. * * @return void */ public function testAdd() { Cache::delete('test_add_key', 'redis'); $result = Cache::add('test_add_key', 'test data', 'redis'); $this->assertTrue($result); $expected = 'test data'; $result = Cache::read('test_add_key', 'redis'); $this->assertEquals($expected, $result); $result = Cache::add('test_add_key', 'test data 2', 'redis'); $this->assertFalse($result); } } cakephp-2.8.0/lib/Cake/Test/Case/Cache/Engine/WincacheEngineTest.php000066400000000000000000000173761265552240500250130ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Cache.Engine * @since CakePHP(tm) v 1.2.0.5434 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Cache', 'Cache'); /** * WincacheEngineTest class * * @package Cake.Test.Case.Cache.Engine */ class WincacheEngineTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->skipIf(!function_exists('wincache_ucache_set'), 'Wincache is not installed or configured properly.'); $this->_cacheDisable = Configure::read('Cache.disable'); Configure::write('Cache.disable', false); Cache::config('wincache', array('engine' => 'Wincache', 'prefix' => 'cake_')); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); Configure::write('Cache.disable', $this->_cacheDisable); Cache::drop('wincache'); Cache::drop('wincache_groups'); Cache::config('default'); } /** * testReadAndWriteCache method * * @return void */ public function testReadAndWriteCache() { Cache::set(array('duration' => 1), 'wincache'); $result = Cache::read('test', 'wincache'); $expecting = ''; $this->assertEquals($expecting, $result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('test', $data, 'wincache'); $this->assertTrue($result); $result = Cache::read('test', 'wincache'); $expecting = $data; $this->assertEquals($expecting, $result); Cache::delete('test', 'wincache'); } /** * testExpiry method * * @return void */ public function testExpiry() { Cache::set(array('duration' => 1), 'wincache'); $result = Cache::read('test', 'wincache'); $this->assertFalse($result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data, 'wincache'); $this->assertTrue($result); sleep(2); $result = Cache::read('other_test', 'wincache'); $this->assertFalse($result); Cache::set(array('duration' => 1), 'wincache'); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data, 'wincache'); $this->assertTrue($result); sleep(2); $result = Cache::read('other_test', 'wincache'); $this->assertFalse($result); sleep(2); $result = Cache::read('other_test', 'wincache'); $this->assertFalse($result); } /** * testDeleteCache method * * @return void */ public function testDeleteCache() { $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('delete_test', $data, 'wincache'); $this->assertTrue($result); $result = Cache::delete('delete_test', 'wincache'); $this->assertTrue($result); } /** * testDecrement method * * @return void */ public function testDecrement() { $this->skipIf( !function_exists('wincache_ucache_dec'), 'No wincache_ucache_dec() function, cannot test decrement().' ); $result = Cache::write('test_decrement', 5, 'wincache'); $this->assertTrue($result); $result = Cache::decrement('test_decrement', 1, 'wincache'); $this->assertEquals(4, $result); $result = Cache::read('test_decrement', 'wincache'); $this->assertEquals(4, $result); $result = Cache::decrement('test_decrement', 2, 'wincache'); $this->assertEquals(2, $result); $result = Cache::read('test_decrement', 'wincache'); $this->assertEquals(2, $result); } /** * testIncrement method * * @return void */ public function testIncrement() { $this->skipIf( !function_exists('wincache_ucache_inc'), 'No wincache_inc() function, cannot test increment().' ); $result = Cache::write('test_increment', 5, 'wincache'); $this->assertTrue($result); $result = Cache::increment('test_increment', 1, 'wincache'); $this->assertEquals(6, $result); $result = Cache::read('test_increment', 'wincache'); $this->assertEquals(6, $result); $result = Cache::increment('test_increment', 2, 'wincache'); $this->assertEquals(8, $result); $result = Cache::read('test_increment', 'wincache'); $this->assertEquals(8, $result); } /** * test the clearing of cache keys * * @return void */ public function testClear() { wincache_ucache_set('not_cake', 'safe'); Cache::write('some_value', 'value', 'wincache'); $result = Cache::clear(false, 'wincache'); $this->assertTrue($result); $this->assertFalse(Cache::read('some_value', 'wincache')); $this->assertEquals('safe', wincache_ucache_get('not_cake')); } /** * Tests that configuring groups for stored keys return the correct values when read/written * Shows that altering the group value is equivalent to deleting all keys under the same * group * * @return void */ public function testGroupsReadWrite() { Cache::config('wincache_groups', array( 'engine' => 'Wincache', 'duration' => 0, 'groups' => array('group_a', 'group_b'), 'prefix' => 'test_' )); $this->assertTrue(Cache::write('test_groups', 'value', 'wincache_groups')); $this->assertEquals('value', Cache::read('test_groups', 'wincache_groups')); wincache_ucache_inc('test_group_a'); $this->assertFalse(Cache::read('test_groups', 'wincache_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'wincache_groups')); $this->assertEquals('value2', Cache::read('test_groups', 'wincache_groups')); wincache_ucache_inc('test_group_b'); $this->assertFalse(Cache::read('test_groups', 'wincache_groups')); $this->assertTrue(Cache::write('test_groups', 'value3', 'wincache_groups')); $this->assertEquals('value3', Cache::read('test_groups', 'wincache_groups')); } /** * Tests that deleteing from a groups-enabled config is possible * * @return void */ public function testGroupDelete() { Cache::config('wincache_groups', array( 'engine' => 'Wincache', 'duration' => 0, 'groups' => array('group_a', 'group_b'), 'prefix' => 'test_' )); $this->assertTrue(Cache::write('test_groups', 'value', 'wincache_groups')); $this->assertEquals('value', Cache::read('test_groups', 'wincache_groups')); $this->assertTrue(Cache::delete('test_groups', 'wincache_groups')); $this->assertFalse(Cache::read('test_groups', 'wincache_groups')); } /** * Test clearing a cache group * * @return void */ public function testGroupClear() { Cache::config('wincache_groups', array( 'engine' => 'Wincache', 'duration' => 0, 'groups' => array('group_a', 'group_b'), 'prefix' => 'test_' )); $this->assertTrue(Cache::write('test_groups', 'value', 'wincache_groups')); $this->assertTrue(Cache::clearGroup('group_a', 'wincache_groups')); $this->assertFalse(Cache::read('test_groups', 'wincache_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'wincache_groups')); $this->assertTrue(Cache::clearGroup('group_b', 'wincache_groups')); $this->assertFalse(Cache::read('test_groups', 'wincache_groups')); } /** * Test that failed add write return false. * * @return void */ public function testAdd() { Cache::delete('test_add_key', 'wincache'); $result = Cache::add('test_add_key', 'test data', 'wincache'); $this->assertTrue($result); $expected = 'test data'; $result = Cache::read('test_add_key', 'wincache'); $this->assertEquals($expected, $result); $result = Cache::add('test_add_key', 'test data 2', 'wincache'); $this->assertFalse($result); } } cakephp-2.8.0/lib/Cake/Test/Case/Cache/Engine/XcacheEngineTest.php000066400000000000000000000170511265552240500244530ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Cache.Engine * @since CakePHP(tm) v 1.2.0.5434 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Cache', 'Cache'); /** * XcacheEngineTest class * * @package Cake.Test.Case.Cache.Engine */ class XcacheEngineTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); if (!function_exists('xcache_set')) { $this->markTestSkipped('Xcache is not installed or configured properly'); } $this->_cacheDisable = Configure::read('Cache.disable'); Configure::write('Cache.disable', false); Cache::config('xcache', array('engine' => 'Xcache', 'prefix' => 'cake_')); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); Configure::write('Cache.disable', $this->_cacheDisable); Cache::drop('xcache'); Cache::drop('xcache_groups'); Cache::config('default'); } /** * testSettings method * * @return void */ public function testSettings() { $settings = Cache::settings(); $expecting = array( 'prefix' => 'cake_', 'duration' => 3600, 'probability' => 100, 'engine' => 'Xcache', ); $this->assertTrue(isset($settings['PHP_AUTH_USER'])); $this->assertTrue(isset($settings['PHP_AUTH_PW'])); unset($settings['PHP_AUTH_USER'], $settings['PHP_AUTH_PW']); $this->assertEquals($settings, $expecting); } /** * testReadAndWriteCache method * * @return void */ public function testReadAndWriteCache() { Cache::set(array('duration' => 1)); $result = Cache::read('test'); $expecting = ''; $this->assertEquals($expecting, $result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('test', $data); $this->assertTrue($result); $result = Cache::read('test'); $expecting = $data; $this->assertEquals($expecting, $result); Cache::delete('test'); } /** * testExpiry method * * @return void */ public function testExpiry() { Cache::set(array('duration' => 1)); $result = Cache::read('test'); $this->assertFalse($result); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data); $this->assertTrue($result); sleep(2); $result = Cache::read('other_test'); $this->assertFalse($result); Cache::set(array('duration' => "+1 second")); $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('other_test', $data); $this->assertTrue($result); sleep(2); $result = Cache::read('other_test'); $this->assertFalse($result); } /** * testDeleteCache method * * @return void */ public function testDeleteCache() { $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('delete_test', $data); $this->assertTrue($result); $result = Cache::delete('delete_test'); $this->assertTrue($result); } /** * testClearCache method * * @return void */ public function testClearCache() { $data = 'this is a test of the emergency broadcasting system'; $result = Cache::write('clear_test_1', $data); $this->assertTrue($result); $result = Cache::write('clear_test_2', $data); $this->assertTrue($result); $result = Cache::clear(); $this->assertTrue($result); } /** * testDecrement method * * @return void */ public function testDecrement() { $result = Cache::write('test_decrement', 5); $this->assertTrue($result); $result = Cache::decrement('test_decrement'); $this->assertEquals(4, $result); $result = Cache::read('test_decrement'); $this->assertEquals(4, $result); $result = Cache::decrement('test_decrement', 2); $this->assertEquals(2, $result); $result = Cache::read('test_decrement'); $this->assertEquals(2, $result); } /** * testIncrement method * * @return void */ public function testIncrement() { $result = Cache::write('test_increment', 5); $this->assertTrue($result); $result = Cache::increment('test_increment'); $this->assertEquals(6, $result); $result = Cache::read('test_increment'); $this->assertEquals(6, $result); $result = Cache::increment('test_increment', 2); $this->assertEquals(8, $result); $result = Cache::read('test_increment'); $this->assertEquals(8, $result); } /** * Tests that configuring groups for stored keys return the correct values when read/written * Shows that altering the group value is equivalent to deleting all keys under the same * group * * @return void */ public function testGroupsReadWrite() { Cache::config('xcache_groups', array( 'engine' => 'Xcache', 'duration' => 0, 'groups' => array('group_a', 'group_b'), 'prefix' => 'test_' )); $this->assertTrue(Cache::write('test_groups', 'value', 'xcache_groups')); $this->assertEquals('value', Cache::read('test_groups', 'xcache_groups')); xcache_inc('test_group_a', 1); $this->assertFalse(Cache::read('test_groups', 'xcache_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'xcache_groups')); $this->assertEquals('value2', Cache::read('test_groups', 'xcache_groups')); xcache_inc('test_group_b', 1); $this->assertFalse(Cache::read('test_groups', 'xcache_groups')); $this->assertTrue(Cache::write('test_groups', 'value3', 'xcache_groups')); $this->assertEquals('value3', Cache::read('test_groups', 'xcache_groups')); } /** * Tests that deleteing from a groups-enabled config is possible * * @return void */ public function testGroupDelete() { Cache::config('xcache_groups', array( 'engine' => 'Xcache', 'duration' => 0, 'groups' => array('group_a', 'group_b'), 'prefix' => 'test_' )); $this->assertTrue(Cache::write('test_groups', 'value', 'xcache_groups')); $this->assertEquals('value', Cache::read('test_groups', 'xcache_groups')); $this->assertTrue(Cache::delete('test_groups', 'xcache_groups')); $this->assertFalse(Cache::read('test_groups', 'xcache_groups')); } /** * Test clearing a cache group * * @return void */ public function testGroupClear() { Cache::config('xcache_groups', array( 'engine' => 'Xcache', 'duration' => 0, 'groups' => array('group_a', 'group_b'), 'prefix' => 'test_' )); $this->assertTrue(Cache::write('test_groups', 'value', 'xcache_groups')); $this->assertTrue(Cache::clearGroup('group_a', 'xcache_groups')); $this->assertFalse(Cache::read('test_groups', 'xcache_groups')); $this->assertTrue(Cache::write('test_groups', 'value2', 'xcache_groups')); $this->assertTrue(Cache::clearGroup('group_b', 'xcache_groups')); $this->assertFalse(Cache::read('test_groups', 'xcache_groups')); } /** * Test that failed add write return false. * * @return void */ public function testAdd() { Cache::set(array('duration' => 1), null); Cache::delete('test_add_key', 'default'); $result = Cache::add('test_add_key', 'test data', 'default'); $this->assertTrue($result); $expected = 'test data'; $result = Cache::read('test_add_key', 'default'); $this->assertEquals($expected, $result); $result = Cache::add('test_add_key', 'test data 2', 'default'); $this->assertFalse($result); } } cakephp-2.8.0/lib/Cake/Test/Case/Configure/000077500000000000000000000000001265552240500202665ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Configure/IniReaderTest.php000066400000000000000000000163051265552240500235060ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Configure * @since CakePHP(tm) v 2.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('IniReader', 'Configure'); /** * Class IniReaderTest * * @package Cake.Test.Case.Configure */ class IniReaderTest extends CakeTestCase { /** * Test data to serialize and unserialize. * * @var array */ public $testData = array( 'One' => array( 'two' => 'value', 'three' => array( 'four' => 'value four' ), 'is_null' => null, 'bool_false' => false, 'bool_true' => true, ), 'Asset' => array( 'timestamp' => 'force' ), ); /** * setup * * @return void */ public function setUp() { parent::setUp(); $this->path = CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS; } /** * test construct * * @return void */ public function testConstruct() { $reader = new IniReader($this->path); $config = $reader->read('acl.ini'); $this->assertTrue(isset($config['admin'])); $this->assertTrue(isset($config['paul']['groups'])); $this->assertEquals('ads', $config['admin']['deny']); } /** * Test reading files. * * @return void */ public function testRead() { $reader = new IniReader($this->path); $config = $reader->read('nested'); $this->assertTrue($config['bools']['test_on']); $config = $reader->read('nested.ini'); $this->assertTrue($config['bools']['test_on']); } /** * No other sections should exist. * * @return void */ public function testReadOnlyOneSection() { $reader = new IniReader($this->path, 'admin'); $config = $reader->read('acl.ini'); $this->assertTrue(isset($config['groups'])); $this->assertEquals('administrators', $config['groups']); } /** * Test reading acl.ini.php. * * @return void */ public function testReadSpecialAclIniPhp() { $reader = new IniReader($this->path); $config = $reader->read('acl.ini.php'); $this->assertTrue(isset($config['admin'])); $this->assertTrue(isset($config['paul']['groups'])); $this->assertEquals('ads', $config['admin']['deny']); } /** * Test without section. * * @return void */ public function testReadWithoutSection() { $reader = new IniReader($this->path); $config = $reader->read('no_section.ini'); $expected = array( 'some_key' => 'some_value', 'bool_key' => true ); $this->assertEquals($expected, $config); } /** * Test that names with .'s get exploded into arrays. * * @return void */ public function testReadValuesWithDots() { $reader = new IniReader($this->path); $config = $reader->read('nested.ini'); $this->assertTrue(isset($config['database']['db']['username'])); $this->assertEquals('mark', $config['database']['db']['username']); $this->assertEquals(3, $config['nesting']['one']['two']['three']); $this->assertFalse(isset($config['database.db.username'])); $this->assertFalse(isset($config['database']['db.username'])); } /** * Test boolean reading. * * @return void */ public function testBooleanReading() { $reader = new IniReader($this->path); $config = $reader->read('nested.ini'); $this->assertTrue($config['bools']['test_on']); $this->assertFalse($config['bools']['test_off']); $this->assertTrue($config['bools']['test_yes']); $this->assertFalse($config['bools']['test_no']); $this->assertTrue($config['bools']['test_true']); $this->assertFalse($config['bools']['test_false']); $this->assertFalse($config['bools']['test_null']); } /** * Test an exception is thrown by reading files that exist without .ini extension. * * @expectedException ConfigureException * @return void */ public function testReadWithExistentFileWithoutExtension() { $reader = new IniReader($this->path); $reader->read('no_ini_extension'); } /** * Test an exception is thrown by reading files that don't exist. * * @expectedException ConfigureException * @return void */ public function testReadWithNonExistentFile() { $reader = new IniReader($this->path); $reader->read('fake_values'); } /** * Test reading an empty file. * * @return void */ public function testReadEmptyFile() { $reader = new IniReader($this->path); $config = $reader->read('empty'); $this->assertEquals(array(), $config); } /** * Test reading keys with ../ doesn't work. * * @expectedException ConfigureException * @return void */ public function testReadWithDots() { $reader = new IniReader($this->path); $reader->read('../empty'); } /** * Test reading from plugins. * * @return void */ public function testReadPluginValue() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); $reader = new IniReader($this->path); $result = $reader->read('TestPlugin.nested'); $this->assertTrue(isset($result['database']['db']['username'])); $this->assertEquals('bar', $result['database']['db']['username']); $this->assertFalse(isset($result['database.db.username'])); $this->assertFalse(isset($result['database']['db.username'])); $result = $reader->read('TestPlugin.nested.ini'); $this->assertEquals('foo', $result['database']['db']['password']); CakePlugin::unload(); } /** * Test reading acl.ini.php from plugins. * * @return void */ public function testReadPluginSpecialAclIniPhpValue() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); $reader = new IniReader($this->path); $result = $reader->read('TestPlugin.acl.ini.php'); $this->assertTrue(isset($result['admin'])); $this->assertTrue(isset($result['paul']['groups'])); $this->assertEquals('ads', $result['admin']['deny']); CakePlugin::unload(); } /** * Test dump method. * * @return void */ public function testDump() { $reader = new IniReader(TMP); $result = $reader->dump('test.ini', $this->testData); $this->assertTrue($result > 0); $expected = <<assertTextEquals($expected, $result); $result = $reader->dump('test', $this->testData); $this->assertTrue($result > 0); $contents = file_get_contents($file); $this->assertTextEquals($expected, $contents); unlink($file); } /** * Test that dump() makes files read() can read. * * @return void */ public function testDumpRead() { $reader = new IniReader(TMP); $reader->dump('test.ini', $this->testData); $result = $reader->read('test.ini'); unlink(TMP . 'test.ini'); $expected = $this->testData; $expected['One']['is_null'] = false; $this->assertEquals($expected, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Configure/PhpReaderTest.php000066400000000000000000000104461265552240500235160ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Configure * @since CakePHP(tm) v 2.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('PhpReader', 'Configure'); /** * Class PhpReaderTest * * @package Cake.Test.Case.Configure */ class PhpReaderTest extends CakeTestCase { /** * Test data to serialize and unserialize. * * @var array */ public $testData = array( 'One' => array( 'two' => 'value', 'three' => array( 'four' => 'value four' ), 'is_null' => null, 'bool_false' => false, 'bool_true' => true, ), 'Asset' => array( 'timestamp' => 'force' ), ); /** * Setup. * * @return void */ public function setUp() { parent::setUp(); $this->path = CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS; } /** * Test reading files. * * @return void */ public function testRead() { $reader = new PhpReader($this->path); $values = $reader->read('var_test'); $this->assertEquals('value', $values['Read']); $this->assertEquals('buried', $values['Deep']['Deeper']['Deepest']); $values = $reader->read('var_test.php'); $this->assertEquals('value', $values['Read']); } /** * Test an exception is thrown by reading files that exist without .php extension. * * @expectedException ConfigureException * @return void */ public function testReadWithExistentFileWithoutExtension() { $reader = new PhpReader($this->path); $reader->read('no_php_extension'); } /** * Test an exception is thrown by reading files that don't exist. * * @expectedException ConfigureException * @return void */ public function testReadWithNonExistentFile() { $reader = new PhpReader($this->path); $reader->read('fake_values'); } /** * Test reading an empty file. * * @expectedException ConfigureException * @return void */ public function testReadEmptyFile() { $reader = new PhpReader($this->path); $reader->read('empty'); } /** * Test reading keys with ../ doesn't work. * * @expectedException ConfigureException * @return void */ public function testReadWithDots() { $reader = new PhpReader($this->path); $reader->read('../empty'); } /** * Test reading from plugins. * * @return void */ public function testReadPluginValue() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); $reader = new PhpReader($this->path); $result = $reader->read('TestPlugin.load'); $this->assertTrue(isset($result['plugin_load'])); $result = $reader->read('TestPlugin.load.php'); $this->assertTrue(isset($result['plugin_load'])); CakePlugin::unload(); } /** * Test dumping data to PHP format. * * @return void */ public function testDump() { $reader = new PhpReader(TMP); $result = $reader->dump('test.php', $this->testData); $this->assertTrue($result > 0); $expected = << array ( 'two' => 'value', 'three' => array ( 'four' => 'value four', ), 'is_null' => NULL, 'bool_false' => false, 'bool_true' => true, ), 'Asset' => array ( 'timestamp' => 'force', ), ); PHP; $file = TMP . 'test.php'; $contents = file_get_contents($file); unlink($file); $this->assertTextEquals($expected, $contents); $result = $reader->dump('test', $this->testData); $this->assertTrue($result > 0); $contents = file_get_contents($file); $this->assertTextEquals($expected, $contents); unlink($file); } /** * Test that dump() makes files read() can read. * * @return void */ public function testDumpRead() { $reader = new PhpReader(TMP); $reader->dump('test.php', $this->testData); $result = $reader->read('test.php'); unlink(TMP . 'test.php'); $this->assertEquals($this->testData, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/000077500000000000000000000000001265552240500177475ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Console/AllConsoleLibsTest.php000066400000000000000000000024731265552240500241730ustar00rootroot00000000000000isFile() || strpos($file, 'All') === 0) { continue; } $fileName = $file->getRealPath(); if (substr($fileName, -4) === '.php') { $suite->addTestFile($file->getRealPath()); } } return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/Console/AllConsoleTest.php000066400000000000000000000023451265552240500233570ustar00rootroot00000000000000addTestFile($path . 'AllConsoleLibsTest.php'); $suite->addTestFile($path . 'AllTasksTest.php'); $suite->addTestFile($path . 'AllShellsTest.php'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/Console/AllShellsTest.php000066400000000000000000000021741265552240500232070ustar00rootroot00000000000000addTestDirectory($path); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/Console/AllTasksTest.php000066400000000000000000000021731265552240500230410ustar00rootroot00000000000000addTestDirectory($path); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/000077500000000000000000000000001265552240500213255ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/AclShellTest.php000066400000000000000000000225701265552240500243730ustar00rootroot00000000000000getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock( 'AclShell', array('in', 'out', 'hr', 'createFile', 'error', 'err', 'clear', 'dispatchShell'), array($out, $out, $in) ); $collection = new ComponentCollection(); $this->Task->Acl = new AclComponent($collection); $this->Task->params['datasource'] = 'test'; } /** * test that model.foreign_key output works when looking at acl rows * * @return void */ public function testViewWithModelForeignKeyOutput() { $this->Task->command = 'view'; $this->Task->startup(); $data = array( 'parent_id' => null, 'model' => 'MyModel', 'foreign_key' => 2, ); $this->Task->Acl->Aro->create($data); $this->Task->Acl->Aro->save(); $this->Task->args[0] = 'aro'; $this->Task->expects($this->at(0))->method('out')->with('Aro tree:'); $this->Task->expects($this->at(2))->method('out') ->with($this->stringContains('[1] ROOT')); $this->Task->expects($this->at(4))->method('out') ->with($this->stringContains('[3] Gandalf')); $this->Task->expects($this->at(6))->method('out') ->with($this->stringContains('[5] MyModel.2')); $this->Task->view(); } /** * test view with an argument * * @return void */ public function testViewWithArgument() { $this->Task->args = array('aro', 'admins'); $this->Task->expects($this->at(0))->method('out')->with('Aro tree:'); $this->Task->expects($this->at(2))->method('out')->with(' [2] admins'); $this->Task->expects($this->at(3))->method('out')->with(' [3] Gandalf'); $this->Task->expects($this->at(4))->method('out')->with(' [4] Elrond'); $this->Task->view(); } /** * test the method that splits model.foreign key. and that it returns an array. * * @return void */ public function testParsingModelAndForeignKey() { $result = $this->Task->parseIdentifier('Model.foreignKey'); $expected = array('model' => 'Model', 'foreign_key' => 'foreignKey'); $this->assertEquals($expected, $result); $result = $this->Task->parseIdentifier('mySuperUser'); $this->assertEquals('mySuperUser', $result); $result = $this->Task->parseIdentifier('111234'); $this->assertEquals('111234', $result); } /** * test creating aro/aco nodes * * @return void */ public function testCreate() { $this->Task->args = array('aro', 'root', 'User.1'); $this->Task->expects($this->at(0))->method('out')->with("New Aro 'User.1' created.", 2); $this->Task->expects($this->at(1))->method('out')->with("New Aro 'User.3' created.", 2); $this->Task->expects($this->at(2))->method('out')->with("New Aro 'somealias' created.", 2); $this->Task->create(); $Aro = ClassRegistry::init('Aro'); $Aro->cacheQueries = false; $result = $Aro->read(); $this->assertEquals('User', $result['Aro']['model']); $this->assertEquals(1, $result['Aro']['foreign_key']); $this->assertEquals(null, $result['Aro']['parent_id']); $id = $result['Aro']['id']; $this->Task->args = array('aro', 'User.1', 'User.3'); $this->Task->create(); $Aro = ClassRegistry::init('Aro'); $result = $Aro->read(); $this->assertEquals('User', $result['Aro']['model']); $this->assertEquals(3, $result['Aro']['foreign_key']); $this->assertEquals($id, $result['Aro']['parent_id']); $this->Task->args = array('aro', 'root', 'somealias'); $this->Task->create(); $Aro = ClassRegistry::init('Aro'); $result = $Aro->read(); $this->assertEquals('somealias', $result['Aro']['alias']); $this->assertEquals(null, $result['Aro']['model']); $this->assertEquals(null, $result['Aro']['foreign_key']); $this->assertEquals(null, $result['Aro']['parent_id']); } /** * test the delete method with different node types. * * @return void */ public function testDelete() { $this->Task->args = array('aro', 'AuthUser.1'); $this->Task->expects($this->at(0))->method('out') ->with("Aro deleted.", 2); $this->Task->delete(); $Aro = ClassRegistry::init('Aro'); $result = $Aro->findById(3); $this->assertSame(array(), $result); } /** * test setParent method. * * @return void */ public function testSetParent() { $this->Task->args = array('aro', 'AuthUser.2', 'root'); $this->Task->setParent(); $Aro = ClassRegistry::init('Aro'); $result = $Aro->read(null, 4); $this->assertEquals(null, $result['Aro']['parent_id']); } /** * test grant * * @return void */ public function testGrant() { $this->Task->args = array('AuthUser.2', 'ROOT/Controller1', 'create'); $this->Task->expects($this->at(0))->method('out') ->with($this->matchesRegularExpression('/granted/'), true); $this->Task->grant(); $node = $this->Task->Acl->Aro->node(array('model' => 'AuthUser', 'foreign_key' => 2)); $node = $this->Task->Acl->Aro->read(null, $node[0]['Aro']['id']); $this->assertFalse(empty($node['Aco'][0])); $this->assertEquals(1, $node['Aco'][0]['Permission']['_create']); } /** * test deny * * @return void */ public function testDeny() { $this->Task->args = array('AuthUser.2', 'ROOT/Controller1', 'create'); $this->Task->expects($this->at(0))->method('out') ->with($this->stringContains('Permission denied'), true); $this->Task->deny(); $node = $this->Task->Acl->Aro->node(array('model' => 'AuthUser', 'foreign_key' => 2)); $node = $this->Task->Acl->Aro->read(null, $node[0]['Aro']['id']); $this->assertFalse(empty($node['Aco'][0])); $this->assertEquals(-1, $node['Aco'][0]['Permission']['_create']); } /** * test checking allowed and denied perms * * @return void */ public function testCheck() { $this->Task->expects($this->at(0))->method('out') ->with($this->matchesRegularExpression('/not allowed/'), true); $this->Task->expects($this->at(1))->method('out') ->with($this->matchesRegularExpression('/granted/'), true); $this->Task->expects($this->at(2))->method('out') ->with($this->matchesRegularExpression('/is.*allowed/'), true); $this->Task->expects($this->at(3))->method('out') ->with($this->matchesRegularExpression('/not.*allowed/'), true); $this->Task->args = array('AuthUser.2', 'ROOT/Controller1', '*'); $this->Task->check(); $this->Task->args = array('AuthUser.2', 'ROOT/Controller1', 'create'); $this->Task->grant(); $this->Task->args = array('AuthUser.2', 'ROOT/Controller1', 'create'); $this->Task->check(); $this->Task->args = array('AuthUser.2', 'ROOT/Controller1', '*'); $this->Task->check(); } /** * test inherit and that it 0's the permission fields. * * @return void */ public function testInherit() { $this->Task->expects($this->at(0))->method('out') ->with($this->matchesRegularExpression('/Permission .*granted/'), true); $this->Task->expects($this->at(1))->method('out') ->with($this->matchesRegularExpression('/Permission .*inherited/'), true); $this->Task->args = array('AuthUser.2', 'ROOT/Controller1', 'create'); $this->Task->grant(); $this->Task->args = array('AuthUser.2', 'ROOT/Controller1', 'all'); $this->Task->inherit(); $node = $this->Task->Acl->Aro->node(array('model' => 'AuthUser', 'foreign_key' => 2)); $node = $this->Task->Acl->Aro->read(null, $node[0]['Aro']['id']); $this->assertFalse(empty($node['Aco'][0])); $this->assertEquals(0, $node['Aco'][0]['Permission']['_create']); } /** * test getting the path for an aro/aco * * @return void */ public function testGetPath() { $this->Task->args = array('aro', 'AuthUser.2'); $node = $this->Task->Acl->Aro->node(array('model' => 'AuthUser', 'foreign_key' => 2)); $first = $node[0]['Aro']['id']; $second = $node[1]['Aro']['id']; $last = $node[2]['Aro']['id']; $this->Task->expects($this->at(2))->method('out')->with('[' . $last . '] ROOT'); $this->Task->expects($this->at(3))->method('out')->with(' [' . $second . '] admins'); $this->Task->expects($this->at(4))->method('out')->with(' [' . $first . '] Elrond'); $this->Task->getPath(); } /** * test that initdb makes the correct call. * * @return void */ public function testInitDb() { $this->Task->expects($this->once())->method('dispatchShell') ->with('schema create DbAcl'); $this->Task->initdb(); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/ApiShellTest.php000066400000000000000000000057071265552240500244100ustar00rootroot00000000000000getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Shell = $this->getMock( 'ApiShell', array('in', 'out', 'createFile', 'hr', '_stop'), array($out, $out, $in) ); } /** * Test that method names are detected properly including those with no arguments. * * @return void */ public function testMethodNameDetection() { $this->Shell->expects($this->any())->method('in')->will($this->returnValue('q')); $this->Shell->expects($this->at(0))->method('out')->with('Controller'); $expected = array( '1. afterFilter()', '2. afterScaffoldSave($method)', '3. afterScaffoldSaveError($method)', '4. beforeFilter()', '5. beforeRedirect($url, $status = NULL, $exit = true)', '6. beforeRender()', '7. beforeScaffold($method)', '8. constructClasses()', '9. disableCache()', '10. flash($message, $url, $pause = 1, $layout = \'flash\')', '11. getEventManager()', '12. header($status)', '13. httpCodes($code = NULL)', '14. implementedEvents()', '15. invokeAction($request)', '16. loadModel($modelClass = NULL, $id = NULL)', '17. paginate($object = NULL, $scope = array (), $whitelist = array ())', '18. postConditions($data = array (), $op = NULL, $bool = \'AND\', $exclusive = false)', '19. redirect($url, $status = NULL, $exit = true)', '20. referer($default = NULL, $local = false)', '21. render($view = NULL, $layout = NULL)', '22. scaffoldError($method)', '23. set($one, $two = NULL)', '24. setAction($action)', '25. setRequest($request)', '26. shutdownProcess()', '27. startupProcess()', '28. validate()', '29. validateErrors()' ); $this->Shell->expects($this->at(2))->method('out')->with($expected); $this->Shell->args = array('controller'); $this->Shell->paths['controller'] = CAKE . 'Controller' . DS; $this->Shell->main(); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/BakeShellTest.php000066400000000000000000000063771265552240500245450ustar00rootroot00000000000000getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Shell = $this->getMock( 'BakeShell', array('in', 'out', 'hr', 'err', 'createFile', '_stop', '_checkUnitTest'), array($out, $out, $in) ); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Dispatch, $this->Shell); } /** * test bake all * * @return void */ public function testAllWithModelName() { App::uses('User', 'Model'); $userExists = class_exists('User'); $this->skipIf($userExists, 'User class exists, cannot test `bake all [param]`.'); $this->Shell->Model = $this->getMock('ModelTask', array(), array(&$this->Dispatcher)); $this->Shell->Controller = $this->getMock('ControllerTask', array(), array(&$this->Dispatcher)); $this->Shell->View = $this->getMock('ModelTask', array(), array(&$this->Dispatcher)); $this->Shell->DbConfig = $this->getMock('DbConfigTask', array(), array(&$this->Dispatcher)); $this->Shell->DbConfig->expects($this->once()) ->method('getConfig') ->will($this->returnValue('test')); $this->Shell->Model->expects($this->never()) ->method('getName'); $this->Shell->Model->expects($this->once()) ->method('bake') ->will($this->returnValue(true)); $this->Shell->Controller->expects($this->once()) ->method('bake') ->will($this->returnValue(true)); $this->Shell->View->expects($this->once()) ->method('execute'); $this->Shell->expects($this->once())->method('_stop'); $this->Shell->expects($this->at(0)) ->method('out') ->with('Bake All'); $this->Shell->expects($this->at(5)) ->method('out') ->with('Bake All complete'); $this->Shell->connection = ''; $this->Shell->params = array(); $this->Shell->args = array('User'); $this->Shell->all(); $this->assertEquals('User', $this->Shell->View->args[0]); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/CommandListShellTest.php000066400000000000000000000064311265552240500261040ustar00rootroot00000000000000output .= $message; } } /** * Class CommandListShellTest * * @package Cake.Test.Case.Console.Command */ class CommandListShellTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); App::build(array( 'Plugin' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS ), 'Console/Command' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Console' . DS . 'Command' . DS ) ), App::RESET); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); $out = new TestStringOutput(); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Shell = $this->getMock( 'CommandListShell', array('in', '_stop', 'clear'), array($out, $out, $in) ); $this->Shell->Command = $this->getMock( 'CommandTask', array('in', '_stop', 'clear'), array($out, $out, $in) ); } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Shell); CakePlugin::unload(); } /** * test that main finds core shells. * * @return void */ public function testMain() { $this->Shell->main(); $output = $this->Shell->stdout->output; $expected = "/\[.*TestPlugin.*\] example/"; $this->assertRegExp($expected, $output); $expected = "/\[.*TestPluginTwo.*\] example, welcome/"; $this->assertRegExp($expected, $output); $expected = "/\[.*CORE.*\] acl, api, bake, command_list, completion, console, i18n, schema, server, test, testsuite, upgrade/"; $this->assertRegExp($expected, $output); $expected = "/\[.*app.*\] sample/"; $this->assertRegExp($expected, $output); } /** * test xml output. * * @return void */ public function testMainXml() { $this->Shell->params['xml'] = true; $this->Shell->main(); $output = $this->Shell->stdout->output; $find = ''; $this->assertContains($find, $output); $find = ''; $this->assertContains($find, $output); $find = ''; $this->assertContains($find, $output); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/CompletionShellTest.php000066400000000000000000000150231265552240500260000ustar00rootroot00000000000000output .= $message; } } /** * Class CompletionShellTest * * @package Cake.Test.Case.Console.Command */ class CompletionShellTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); App::build(array( 'Plugin' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS ), 'Console/Command' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Console' . DS . 'Command' . DS ) ), App::RESET); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); $out = new TestCompletionStringOutput(); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Shell = $this->getMock( 'CompletionShell', array('in', '_stop', 'clear'), array($out, $out, $in) ); $this->Shell->Command = $this->getMock( 'CommandTask', array('in', '_stop', 'clear'), array($out, $out, $in) ); } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Shell); CakePlugin::unload(); } /** * test that the startup method supresses the shell header * * @return void */ public function testStartup() { $this->Shell->runCommand('main', array()); $output = $this->Shell->stdout->output; $needle = 'Welcome to CakePHP'; $this->assertTextNotContains($needle, $output); } /** * test that main displays a warning * * @return void */ public function testMain() { $this->Shell->runCommand('main', array()); $output = $this->Shell->stdout->output; $expected = "/This command is not intended to be called manually/"; $this->assertRegExp($expected, $output); } /** * test commands method that list all available commands * * @return void */ public function testCommands() { $this->Shell->runCommand('commands', array()); $output = $this->Shell->stdout->output; $expected = "TestPlugin.example TestPlugin.test_plugin TestPluginTwo.example TestPluginTwo.welcome acl api bake command_list completion console i18n schema server test testsuite upgrade sample\n"; $this->assertEquals($expected, $output); } /** * test that options without argument returns the default options * * @return void */ public function testOptionsNoArguments() { $this->Shell->runCommand('options', array()); $output = $this->Shell->stdout->output; $expected = "--help -h --verbose -v --quiet -q\n"; $this->assertEquals($expected, $output); } /** * test that options with a nonexisting command returns the default options * * @return void */ public function testOptionsNonExistingCommand() { $this->Shell->runCommand('options', array('options', 'foo')); $output = $this->Shell->stdout->output; $expected = "--help -h --verbose -v --quiet -q\n"; $this->assertEquals($expected, $output); } /** * test that options with a existing command returns the proper options * * @return void */ public function testOptions() { $this->Shell->runCommand('options', array('options', 'bake')); $output = $this->Shell->stdout->output; $expected = "--help -h --verbose -v --quiet -q --connection -c --theme -t\n"; $this->assertEquals($expected, $output); } /** * test that subCommands with a existing CORE command returns the proper sub commands * * @return void */ public function testSubCommandsCorePlugin() { $this->Shell->runCommand('subCommands', array('subCommands', 'CORE.bake')); $output = $this->Shell->stdout->output; $expected = "controller db_config fixture model plugin project test view\n"; $this->assertEquals($expected, $output); } /** * test that subCommands with a existing APP command returns the proper sub commands (in this case none) * * @return void */ public function testSubCommandsAppPlugin() { $this->Shell->runCommand('subCommands', array('subCommands', 'app.sample')); $output = $this->Shell->stdout->output; $expected = ''; $this->assertEquals($expected, $output); } /** * test that subCommands with a existing plugin command returns the proper sub commands * * @return void */ public function testSubCommandsPlugin() { $this->Shell->runCommand('subCommands', array('subCommands', 'TestPluginTwo.welcome')); $output = $this->Shell->stdout->output; $expected = "say_hello\n"; $this->assertEquals($expected, $output); } /** * test that subcommands without arguments returns nothing * * @return void */ public function testSubCommandsNoArguments() { $this->Shell->runCommand('subCommands', array()); $output = $this->Shell->stdout->output; $expected = ''; $this->assertEquals($expected, $output); } /** * test that subcommands with a nonexisting command returns nothing * * @return void */ public function testSubCommandsNonExistingCommand() { $this->Shell->runCommand('subCommands', array('subCommands', 'foo')); $output = $this->Shell->stdout->output; $expected = ''; $this->assertEquals($expected, $output); } /** * test that subcommands returns the available subcommands for the given command * * @return void */ public function testSubCommands() { $this->Shell->runCommand('subCommands', array('subCommands', 'bake')); $output = $this->Shell->stdout->output; $expected = "controller db_config fixture model plugin project test view\n"; $this->assertEquals($expected, $output); } /** * test that fuzzy returns nothing * * @return void */ public function testFuzzy() { $this->Shell->runCommand('fuzzy', array()); $output = $this->Shell->stdout->output; $expected = ''; $this->assertEquals($expected, $output); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/SchemaShellTest.php000066400000000000000000000505541265552240500250770ustar00rootroot00000000000000 array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'user_id' => array('type' => 'integer', 'null' => false), 'title' => array('type' => 'string', 'null' => false, 'length' => 100), 'comment' => array('type' => 'text', 'null' => false, 'default' => null), 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1), 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)), ); /** * posts property * * @var array */ public $articles = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'user_id' => array('type' => 'integer', 'null' => true, 'default' => ''), 'title' => array('type' => 'string', 'null' => false, 'default' => 'Title'), 'body' => array('type' => 'text', 'null' => true, 'default' => null), 'summary' => array('type' => 'text', 'null' => true), 'published' => array('type' => 'string', 'null' => true, 'default' => 'Y', 'length' => 1), 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)), ); public $newone = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'testit' => array('type' => 'string', 'null' => false, 'default' => 'Title'), 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)), ); } /** * SchemaShellTest class * * @package Cake.Test.Case.Console.Command */ class SchemaShellTest extends CakeTestCase { /** * Fixtures * * @var array */ public $fixtures = array( 'core.article', 'core.user', 'core.post', 'core.auth_user', 'core.author', 'core.comment', 'core.test_plugin_comment', 'core.aco', 'core.aro', 'core.aros_aco', ); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Shell = $this->getMock( 'SchemaShell', array('in', 'out', 'hr', 'createFile', 'error', 'err', '_stop'), array($out, $out, $in) ); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); if (!empty($this->file) && $this->file instanceof File) { $this->file->delete(); unset($this->file); } } /** * test startup method * * @return void */ public function testStartup() { $this->Shell->startup(); $this->assertTrue(isset($this->Shell->Schema)); $this->assertInstanceOf('CakeSchema', $this->Shell->Schema); $this->assertEquals(Inflector::camelize(Inflector::slug(APP_DIR)), $this->Shell->Schema->name); $this->assertEquals('schema.php', $this->Shell->Schema->file); $this->Shell->Schema = null; $this->Shell->params = array( 'name' => 'TestSchema' ); $this->Shell->startup(); $this->assertEquals('TestSchema', $this->Shell->Schema->name); $this->assertEquals('test_schema.php', $this->Shell->Schema->file); $this->assertEquals('default', $this->Shell->Schema->connection); $this->assertEquals(APP . 'Config' . DS . 'Schema', $this->Shell->Schema->path); $this->Shell->Schema = null; $this->Shell->params = array( 'file' => 'other_file.php', 'connection' => 'test', 'path' => '/test/path' ); $this->Shell->startup(); $this->assertEquals(Inflector::camelize(Inflector::slug(APP_DIR)), $this->Shell->Schema->name); $this->assertEquals('other_file.php', $this->Shell->Schema->file); $this->assertEquals('test', $this->Shell->Schema->connection); $this->assertEquals('/test/path', $this->Shell->Schema->path); } /** * Test View - and that it dumps the schema file to stdout * * @return void */ public function testView() { $this->Shell->startup(); $this->Shell->Schema->path = APP . 'Config' . DS . 'Schema'; $this->Shell->params['file'] = 'i18n.php'; $this->Shell->expects($this->once())->method('_stop'); $this->Shell->expects($this->once())->method('out'); $this->Shell->view(); } /** * test that view() can find plugin schema files. * * @return void */ public function testViewWithPlugins() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); CakePlugin::load('TestPlugin'); $this->Shell->args = array('TestPlugin.schema'); $this->Shell->startup(); $this->Shell->expects($this->exactly(2))->method('_stop'); $this->Shell->expects($this->atLeastOnce())->method('out'); $this->Shell->view(); $this->Shell->args = array(); $this->Shell->params = array('plugin' => 'TestPlugin'); $this->Shell->startup(); $this->Shell->view(); App::build(); CakePlugin::unload(); } /** * test dump() with sql file generation * * @return void */ public function testDumpWithFileWriting() { $this->Shell->params = array( 'name' => 'i18n', 'connection' => 'test', 'write' => TMP . 'tests' . DS . 'i18n.sql' ); $this->Shell->expects($this->once())->method('_stop'); $this->Shell->startup(); $this->Shell->dump(); $this->file = new File(TMP . 'tests' . DS . 'i18n.sql'); $contents = $this->file->read(); $this->assertRegExp('/DROP TABLE/', $contents); $this->assertRegExp('/CREATE TABLE.*?i18n/', $contents); $this->assertRegExp('/id/', $contents); $this->assertRegExp('/model/', $contents); $this->assertRegExp('/field/', $contents); $this->assertRegExp('/locale/', $contents); $this->assertRegExp('/foreign_key/', $contents); $this->assertRegExp('/content/', $contents); } /** * test that dump() can find and work with plugin schema files. * * @return void */ public function testDumpFileWritingWithPlugins() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); CakePlugin::load('TestPlugin'); $this->Shell->args = array('TestPlugin.TestPluginApp'); $this->Shell->params = array( 'connection' => 'test', 'write' => TMP . 'tests' . DS . 'dump_test.sql' ); $this->Shell->startup(); $this->Shell->expects($this->once())->method('_stop'); $this->Shell->dump(); $this->file = new File(TMP . 'tests' . DS . 'dump_test.sql'); $contents = $this->file->read(); $this->assertRegExp('/CREATE TABLE.*?test_plugin_acos/', $contents); $this->assertRegExp('/id/', $contents); $this->assertRegExp('/model/', $contents); $this->file->delete(); App::build(); CakePlugin::unload(); } /** * test generate with snapshot generation * * @return void */ public function testGenerateSnapshot() { $this->Shell->path = TMP; $this->Shell->params['file'] = 'schema.php'; $this->Shell->params['force'] = false; $this->Shell->args = array('snapshot'); $this->Shell->Schema = $this->getMock('CakeSchema'); $this->Shell->Schema->expects($this->at(0))->method('read')->will($this->returnValue(array('schema data'))); $this->Shell->Schema->expects($this->at(0))->method('write')->will($this->returnValue(true)); $this->Shell->Schema->expects($this->at(1))->method('read'); $this->Shell->Schema->expects($this->at(1))->method('write')->with(array('schema data', 'file' => 'schema_0.php')); $this->Shell->generate(); } /** * test generate without a snapshot. * * @return void */ public function testGenerateNoOverwrite() { touch(TMP . 'schema.php'); $this->Shell->params['file'] = 'schema.php'; $this->Shell->params['force'] = false; $this->Shell->args = array(); $this->Shell->expects($this->once())->method('in')->will($this->returnValue('q')); $this->Shell->Schema = $this->getMock('CakeSchema'); $this->Shell->Schema->path = TMP; $this->Shell->Schema->expects($this->never())->method('read'); $this->Shell->generate(); unlink(TMP . 'schema.php'); } /** * test generate with overwriting of the schema files. * * @return void */ public function testGenerateOverwrite() { touch(TMP . 'schema.php'); $this->Shell->params['file'] = 'schema.php'; $this->Shell->params['force'] = false; $this->Shell->args = array(); $this->Shell->expects($this->once())->method('in')->will($this->returnValue('o')); $this->Shell->expects($this->at(2))->method('out') ->with(new PHPUnit_Framework_Constraint_PCREMatch('/Schema file:\s[a-z\.]+\sgenerated/')); $this->Shell->Schema = $this->getMock('CakeSchema'); $this->Shell->Schema->path = TMP; $this->Shell->Schema->expects($this->once())->method('read')->will($this->returnValue(array('schema data'))); $this->Shell->Schema->expects($this->once())->method('write')->will($this->returnValue(true)); $this->Shell->Schema->expects($this->once())->method('read'); $this->Shell->Schema->expects($this->once())->method('write') ->with(array('schema data', 'file' => 'schema.php')); $this->Shell->generate(); unlink(TMP . 'schema.php'); } /** * test that generate() can read plugin dirs and generate schema files for the models * in a plugin. * * @return void */ public function testGenerateWithPlugins() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); $this->db->cacheSources = false; $this->Shell->params = array( 'plugin' => 'TestPlugin', 'connection' => 'test', 'force' => false ); $this->Shell->startup(); $this->Shell->Schema->path = TMP . 'tests' . DS; $this->Shell->generate(); $this->file = new File(TMP . 'tests' . DS . 'schema.php'); $contents = $this->file->read(); $this->assertRegExp('/class TestPluginSchema/', $contents); $this->assertRegExp('/public \$posts/', $contents); $this->assertRegExp('/public \$auth_users/', $contents); $this->assertRegExp('/public \$authors/', $contents); $this->assertRegExp('/public \$test_plugin_comments/', $contents); $this->assertNotRegExp('/public \$users/', $contents); $this->assertNotRegExp('/public \$articles/', $contents); CakePlugin::unload(); } /** * test generate with specific models * * @return void */ public function testGenerateModels() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); $this->db->cacheSources = false; $this->Shell->params = array( 'plugin' => 'TestPlugin', 'connection' => 'test', 'models' => 'TestPluginComment', 'force' => false, 'overwrite' => true ); $this->Shell->startup(); $this->Shell->Schema->path = TMP . 'tests' . DS; $this->Shell->generate(); $this->file = new File(TMP . 'tests' . DS . 'schema.php'); $contents = $this->file->read(); $this->assertRegExp('/class TestPluginSchema/', $contents); $this->assertRegExp('/public \$test_plugin_comments/', $contents); $this->assertNotRegExp('/public \$authors/', $contents); $this->assertNotRegExp('/public \$auth_users/', $contents); $this->assertNotRegExp('/public \$posts/', $contents); CakePlugin::unload(); } /** * test generate with excluded tables * * @return void */ public function testGenerateExclude() { Configure::write('Acl.database', 'test'); $this->db->cacheSources = false; $this->Shell->params = array( 'connection' => 'test', 'force' => false, 'models' => 'Aro, Aco, Permission', 'overwrite' => true, 'exclude' => 'acos, aros', ); $this->Shell->startup(); $this->Shell->Schema->path = TMP . 'tests' . DS; $this->Shell->generate(); $this->file = new File(TMP . 'tests' . DS . 'schema.php'); $contents = $this->file->read(); $this->assertNotContains('public $acos = array(', $contents); $this->assertNotContains('public $aros = array(', $contents); $this->assertContains('public $aros_acos = array(', $contents); } /** * Test schema run create with --yes option * * @return void */ public function testCreateOptionYes() { $this->Shell = $this->getMock( 'SchemaShell', array('in', 'out', 'hr', 'createFile', 'error', 'err', '_stop', '_run'), array(&$this->Dispatcher) ); $this->Shell->params = array( 'connection' => 'test', 'yes' => true, ); $this->Shell->args = array('i18n'); $this->Shell->expects($this->never())->method('in'); $this->Shell->expects($this->exactly(2))->method('_run'); $this->Shell->startup(); $this->Shell->create(); } /** * Test schema run create with no table args. * * @return void */ public function testCreateNoArgs() { $this->Shell->params = array( 'connection' => 'test' ); $this->Shell->args = array('i18n'); $this->Shell->startup(); $this->Shell->expects($this->any())->method('in')->will($this->returnValue('y')); $this->Shell->create(); $db = ConnectionManager::getDataSource('test'); $db->cacheSources = false; $sources = $db->listSources(); $this->assertTrue(in_array($db->config['prefix'] . 'i18n', $sources)); $schema = new i18nSchema(); $db->execute($db->dropSchema($schema)); } /** * Test schema run create with no table args. * * @return void */ public function testCreateWithTableArgs() { $db = ConnectionManager::getDataSource('test'); $sources = $db->listSources(); if (in_array('i18n', $sources)) { $this->markTestSkipped('i18n table already exists, cannot try to create it again.'); } $this->Shell->params = array( 'connection' => 'test', 'name' => 'I18n', 'path' => APP . 'Config' . DS . 'Schema' ); $this->Shell->args = array('I18n', 'i18n'); $this->Shell->startup(); $this->Shell->expects($this->any())->method('in')->will($this->returnValue('y')); $this->Shell->create(); $db = ConnectionManager::getDataSource('test'); $db->cacheSources = false; $sources = $db->listSources(); $this->assertTrue(in_array($db->config['prefix'] . 'i18n', $sources), 'i18n should be present.'); $schema = new I18nSchema(); $db->execute($db->dropSchema($schema, 'i18n')); } /** * test run update with a table arg. * * @return void */ public function testUpdateWithTable() { $this->Shell = $this->getMock( 'SchemaShell', array('in', 'out', 'hr', 'createFile', 'error', 'err', '_stop', '_run'), array(&$this->Dispatcher) ); $this->Shell->params = array( 'connection' => 'test', 'force' => true ); $this->Shell->args = array('SchemaShellTest', 'articles'); $this->Shell->startup(); $this->Shell->expects($this->any()) ->method('in') ->will($this->returnValue('y')); $this->Shell->expects($this->once()) ->method('_run') ->with($this->arrayHasKey('articles'), 'update', $this->isInstanceOf('CakeSchema')); $this->Shell->update(); } /** * test run update with a table arg. and checks that a CREATE statement is issued * table creation * @return void */ public function testUpdateWithTableCreate() { $this->Shell = $this->getMock( 'SchemaShell', array('in', 'out', 'hr', 'createFile', 'error', 'err', '_stop', '_run'), array(&$this->Dispatcher) ); $this->Shell->params = array( 'connection' => 'test', 'force' => true ); $this->Shell->args = array('SchemaShellTest', 'newone'); $this->Shell->startup(); $this->Shell->expects($this->any()) ->method('in') ->will($this->returnValue('y')); $this->Shell->expects($this->once()) ->method('_run') ->with($this->arrayHasKey('newone'), 'update', $this->isInstanceOf('CakeSchema')); $this->Shell->update(); } /** * test run update with --yes option * * @return void */ public function testUpdateWithOptionYes() { $this->Shell = $this->getMock( 'SchemaShell', array('in', 'out', 'hr', 'createFile', 'error', 'err', '_stop', '_run'), array(&$this->Dispatcher) ); $this->Shell->params = array( 'connection' => 'test', 'force' => true, 'yes' => true, ); $this->Shell->args = array('SchemaShellTest', 'articles'); $this->Shell->startup(); $this->Shell->expects($this->never())->method('in'); $this->Shell->expects($this->once()) ->method('_run') ->with($this->arrayHasKey('articles'), 'update', $this->isInstanceOf('CakeSchema')); $this->Shell->update(); } /** * test that the plugin param creates the correct path in the schema object. * * @return void */ public function testPluginParam() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); CakePlugin::load('TestPlugin'); $this->Shell->params = array( 'plugin' => 'TestPlugin', 'connection' => 'test' ); $this->Shell->startup(); $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS . 'TestPlugin' . DS . 'Config' . DS . 'Schema'; $this->assertEquals($expected, $this->Shell->Schema->path); CakePlugin::unload(); } /** * test that underscored names also result in CamelCased class names * * @return void */ public function testName() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); CakePlugin::load('TestPlugin'); $this->Shell->params = array( 'plugin' => 'TestPlugin', 'connection' => 'test', 'name' => 'custom_names', 'force' => false, 'overwrite' => true, ); $this->Shell->startup(); if (file_exists($this->Shell->Schema->path . DS . 'custom_names.php')) { unlink($this->Shell->Schema->path . DS . 'custom_names.php'); } $this->Shell->generate(); $contents = file_get_contents($this->Shell->Schema->path . DS . 'custom_names.php'); $this->assertRegExp('/class CustomNamesSchema/', $contents); unlink($this->Shell->Schema->path . DS . 'custom_names.php'); CakePlugin::unload(); } /** * test that passing name and file creates the passed filename with the * passed class name * * @return void */ public function testNameAndFile() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); CakePlugin::load('TestPlugin'); $this->Shell->params = array( 'plugin' => 'TestPlugin', 'connection' => 'test', 'name' => 'custom_name', 'file' => 'other_name', 'force' => false, 'overwrite' => true, ); $this->Shell->startup(); $file = $this->Shell->Schema->path . DS . 'other_name.php'; if (file_exists($file)) { unlink($file); } $this->Shell->generate(); $this->assertFileExists($file); $contents = file_get_contents($file); $this->assertRegExp('/class CustomNameSchema/', $contents); if (file_exists($file)) { unlink($file); } CakePlugin::unload(); } /** * test that using Plugin.name with write. * * @return void */ public function testPluginDotSyntaxWithCreate() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); CakePlugin::load('TestPlugin'); $this->Shell->params = array( 'connection' => 'test' ); $this->Shell->args = array('TestPlugin.TestPluginApp'); $this->Shell->startup(); $this->Shell->expects($this->any())->method('in')->will($this->returnValue('y')); $this->Shell->create(); $db = ConnectionManager::getDataSource('test'); $sources = $db->listSources(); $this->assertTrue(in_array($db->config['prefix'] . 'test_plugin_acos', $sources)); $schema = new TestPluginAppSchema(); $db->execute($db->dropSchema($schema, 'test_plugin_acos')); CakePlugin::unload(); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/Task/000077500000000000000000000000001265552240500222275ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/Task/CommandTaskTest.php000066400000000000000000000112571265552240500260070ustar00rootroot00000000000000 array( CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS ), 'Console/Command' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Console' . DS . 'Command' . DS ) ), App::RESET); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->CommandTask = $this->getMock( 'CommandTask', array('in', '_stop', 'clear'), array($out, $out, $in) ); } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); unset($this->CommandTask); CakePlugin::unload(); } /** * Test the resulting list of shells * * @return void */ public function testGetShellList() { $result = $this->CommandTask->getShellList(); $expected = array( 'CORE' => array( 'acl', 'api', 'bake', 'command_list', 'completion', 'console', 'i18n', 'schema', 'server', 'test', 'testsuite', 'upgrade' ), 'TestPlugin' => array( 'example', 'test_plugin' ), 'TestPluginTwo' => array( 'example', 'welcome' ), 'app' => array( 'sample' ), ); $this->assertEquals($expected, $result); } /** * Test the resulting list of commands * * @return void */ public function testCommands() { $result = $this->CommandTask->commands(); $expected = array( 'TestPlugin.example', 'TestPlugin.test_plugin', 'TestPluginTwo.example', 'TestPluginTwo.welcome', 'acl', 'api', 'bake', 'command_list', 'completion', 'console', 'i18n', 'schema', 'server', 'test', 'testsuite', 'upgrade', 'sample' ); $this->assertEquals($expected, $result); } /** * Test the resulting list of subcommands for the given command * * @return void */ public function testSubCommands() { $result = $this->CommandTask->subCommands('acl'); $expected = array( 'check', 'create', 'db_config', 'delete', 'deny', 'getPath', 'grant', 'inherit', 'initdb', 'nodeExists', 'parseIdentifier', 'setParent', 'view' ); $this->assertEquals($expected, $result); } /** * Test that unknown commands return an empty array * * @return void */ public function testSubCommandsUnknownCommand() { $result = $this->CommandTask->subCommands('yoghurt'); $expected = array(); $this->assertEquals($expected, $result); } /** * Test that getting a existing shell returns the shell instance * * @return void */ public function testGetShell() { $result = $this->CommandTask->getShell('acl'); $this->assertInstanceOf('AclShell', $result); } /** * Test that getting a non-existing shell returns false * * @return void */ public function testGetShellNonExisting() { $result = $this->CommandTask->getShell('strawberry'); $this->assertFalse($result); } /** * Test that getting a existing core shell with 'core.' prefix returns the correct shell instance * * @return void */ public function testGetShellCore() { $result = $this->CommandTask->getShell('core.bake'); $this->assertInstanceOf('BakeShell', $result); } /** * Test the options array for a known command * * @return void */ public function testOptions() { $result = $this->CommandTask->options('bake'); $expected = array( '--help', '-h', '--verbose', '-v', '--quiet', '-q', '--connection', '-c', '--theme', '-t' ); $this->assertEquals($expected, $result); } /** * Test the options array for an unknown command * * @return void */ public function testOptionsUnknownCommand() { $result = $this->CommandTask->options('pie'); $expected = array( '--help', '-h', '--verbose', '-v', '--quiet', '-q' ); $this->assertEquals($expected, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/Task/ControllerTaskTest.php000066400000000000000000000450451265552240500265560ustar00rootroot00000000000000getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ControllerTask', array('in', 'out', 'err', 'hr', 'createFile', '_stop', '_checkUnitTest'), array($out, $out, $in) ); $this->Task->name = 'Controller'; $this->Task->Template = new TemplateTask($out, $out, $in); $this->Task->Template->params['theme'] = 'default'; $this->Task->Model = $this->getMock('ModelTask', array('in', 'out', 'err', 'createFile', '_stop', '_checkUnitTest'), array($out, $out, $in) ); $this->Task->Project = $this->getMock('ProjectTask', array('in', 'out', 'err', 'createFile', '_stop', '_checkUnitTest', 'getPrefix'), array($out, $out, $in) ); $this->Task->Test = $this->getMock('TestTask', array(), array($out, $out, $in)); if (!defined('ARTICLE_MODEL_CREATED')) { $this->markTestSkipped('Could not run as an Article, Tag or Comment model was already loaded.'); } } /** * tearDown method * * @return void */ public function tearDown() { unset($this->Task); ClassRegistry::flush(); App::build(); parent::tearDown(); } /** * test ListAll * * @return void */ public function testListAll() { $count = count($this->Task->listAll('test')); if ($count != count($this->fixtures)) { $this->markTestSkipped('Additional tables detected.'); } $this->Task->connection = 'test'; $this->Task->interactive = true; $this->Task->expects($this->at(2))->method('out')->with(' 1. BakeArticles'); $this->Task->expects($this->at(3))->method('out')->with(' 2. BakeArticlesBakeTags'); $this->Task->expects($this->at(4))->method('out')->with(' 3. BakeComments'); $this->Task->expects($this->at(5))->method('out')->with(' 4. BakeTags'); $expected = array('BakeArticles', 'BakeArticlesBakeTags', 'BakeComments', 'BakeTags'); $result = $this->Task->listAll('test'); $this->assertEquals($expected, $result); $this->Task->interactive = false; $result = $this->Task->listAll(); $expected = array('bake_articles', 'bake_articles_bake_tags', 'bake_comments', 'bake_tags'); $this->assertEquals($expected, $result); } /** * Test that getName interacts with the user and returns the controller name. * * @return void */ public function testGetNameValidIndex() { $count = count($this->Task->listAll('test')); if ($count != count($this->fixtures)) { $this->markTestSkipped('Additional tables detected.'); } $this->Task->interactive = true; $this->Task->expects($this->any())->method('in')->will( $this->onConsecutiveCalls(3, 1) ); $result = $this->Task->getName('test'); $expected = 'BakeComments'; $this->assertEquals($expected, $result); $result = $this->Task->getName('test'); $expected = 'BakeArticles'; $this->assertEquals($expected, $result); } /** * test getting invalid indexes. * * @return void */ public function testGetNameInvalidIndex() { $this->Task->interactive = true; $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls(50, 'q')); $this->Task->expects($this->once())->method('err'); $this->Task->expects($this->once())->method('_stop'); $this->Task->getName('test'); } /** * test helper interactions * * @return void */ public function testDoHelpersNo() { $this->Task->expects($this->any())->method('in')->will($this->returnValue('n')); $result = $this->Task->doHelpers(); $this->assertSame(array(), $result); } /** * test getting helper values * * @return void */ public function testDoHelpersTrailingSpace() { $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y')); $this->Task->expects($this->at(1))->method('in')->will($this->returnValue(' Text, Number, CustomOne ')); $result = $this->Task->doHelpers(); $expected = array('Text', 'Number', 'CustomOne'); $this->assertEquals($expected, $result); } /** * test doHelpers with extra commas * * @return void */ public function testDoHelpersTrailingCommas() { $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y')); $this->Task->expects($this->at(1))->method('in')->will($this->returnValue(' Text, Number, CustomOne, , ')); $result = $this->Task->doHelpers(); $expected = array('Text', 'Number', 'CustomOne'); $this->assertEquals($expected, $result); } /** * test component interactions * * @return void */ public function testDoComponentsNo() { $this->Task->expects($this->any())->method('in')->will($this->returnValue('n')); $result = $this->Task->doComponents(); $this->assertSame(array('Paginator', 'Flash'), $result); } /** * test components with spaces * * @return void */ public function testDoComponentsTrailingSpaces() { $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y')); $this->Task->expects($this->at(1))->method('in')->will($this->returnValue(' RequestHandler, Security ')); $result = $this->Task->doComponents(); $expected = array('Paginator', 'Flash', 'RequestHandler', 'Security'); $this->assertEquals($expected, $result); } /** * test components with commas * * @return void */ public function testDoComponentsTrailingCommas() { $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y')); $this->Task->expects($this->at(1))->method('in')->will($this->returnValue(' RequestHandler, Security, , ')); $result = $this->Task->doComponents(); $expected = array('Paginator', 'Flash', 'RequestHandler', 'Security'); $this->assertEquals($expected, $result); } /** * test Confirming controller user interaction * * @return void */ public function testConfirmController() { $controller = 'Posts'; $scaffold = false; $helpers = array('Js', 'Time'); $components = array('Acl', 'Auth'); $this->Task->expects($this->at(4))->method('out')->with("Controller Name:\n\t$controller"); $this->Task->expects($this->at(5))->method('out')->with("Helpers:\n\tJs, Time"); $this->Task->expects($this->at(6))->method('out')->with("Components:\n\tAcl, Auth"); $this->Task->confirmController($controller, $scaffold, $helpers, $components); } /** * test the bake method * * @return void */ public function testBake() { $helpers = array('Js', 'Time'); $components = array('Acl', 'Auth'); $this->Task->expects($this->any())->method('createFile')->will($this->returnValue(true)); $result = $this->Task->bake('Articles', null, $helpers, $components); $expected = file_get_contents(CAKE . 'Test' . DS . 'bake_compare' . DS . 'Controller' . DS . 'NoActions.ctp'); $this->assertTextEquals($expected, $result); $result = $this->Task->bake('Articles', null, array(), array()); $expected = file_get_contents(CAKE . 'Test' . DS . 'bake_compare' . DS . 'Controller' . DS . 'NoHelpersOrComponents.ctp'); $this->assertTextEquals($expected, $result); $result = $this->Task->bake('Articles', 'scaffold', $helpers, $components); $expected = file_get_contents(CAKE . 'Test' . DS . 'bake_compare' . DS . 'Controller' . DS . 'Scaffold.ctp'); $this->assertTextEquals($expected, $result); } /** * test bake() with a -plugin param * * @return void */ public function testBakeWithPlugin() { $this->Task->plugin = 'ControllerTest'; //fake plugin path CakePlugin::load('ControllerTest', array('path' => APP . 'Plugin' . DS . 'ControllerTest' . DS)); $path = APP . 'Plugin' . DS . 'ControllerTest' . DS . 'Controller' . DS . 'ArticlesController.php'; $this->Task->expects($this->at(1))->method('createFile')->with( $path, new PHPUnit_Framework_Constraint_IsAnything() ); $this->Task->expects($this->at(3))->method('createFile')->with( $path, $this->stringContains('ArticlesController extends ControllerTestAppController') )->will($this->returnValue(true)); $this->Task->bake('Articles', '--actions--', array(), array(), array()); $this->Task->plugin = 'ControllerTest'; $path = APP . 'Plugin' . DS . 'ControllerTest' . DS . 'Controller' . DS . 'ArticlesController.php'; $result = $this->Task->bake('Articles', '--actions--', array(), array(), array()); $this->assertContains("App::uses('ControllerTestAppController', 'ControllerTest.Controller');", $result); $this->assertEquals('ControllerTest', $this->Task->Template->templateVars['plugin']); $this->assertEquals('ControllerTest.', $this->Task->Template->templateVars['pluginPath']); CakePlugin::unload(); } /** * test that bakeActions is creating the correct controller Code. (Using sessions) * * @return void */ public function testBakeActionsUsingSessions() { $result = $this->Task->bakeActions('BakeArticles', null, true); $expected = file_get_contents(CAKE . 'Test' . DS . 'bake_compare' . DS . 'Controller' . DS . 'ActionsUsingSessions.ctp'); $this->assertTextEquals($expected, $result); $result = $this->Task->bakeActions('BakeArticles', 'admin_', true); $this->assertContains('function admin_index() {', $result); $this->assertContains('function admin_add()', $result); $this->assertContains('function admin_view($id = null)', $result); $this->assertContains('function admin_edit($id = null)', $result); $this->assertContains('function admin_delete($id = null)', $result); } /** * Test baking with Controller::flash() or no sessions. * * @return void */ public function testBakeActionsWithNoSessions() { $result = $this->Task->bakeActions('BakeArticles', null, false); $expected = file_get_contents(CAKE . 'Test' . DS . 'bake_compare' . DS . 'Controller' . DS . 'ActionsWithNoSessions.ctp'); $this->assertTextEquals($expected, $result); } /** * test baking a test * * @return void */ public function testBakeTest() { $this->Task->plugin = 'ControllerTest'; $this->Task->connection = 'test'; $this->Task->interactive = false; $this->Task->Test->expects($this->once())->method('bake')->with('Controller', 'BakeArticles'); $this->Task->bakeTest('BakeArticles'); $this->assertEquals($this->Task->plugin, $this->Task->Test->plugin); $this->assertEquals($this->Task->connection, $this->Task->Test->connection); $this->assertEquals($this->Task->interactive, $this->Task->Test->interactive); } /** * test Interactive mode. * * @return void */ public function testInteractive() { $count = count($this->Task->listAll('test')); if ($count != count($this->fixtures)) { $this->markTestSkipped('Additional tables detected.'); } $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls( '1', 'y', // build interactive 'n', // build no scaffolds 'y', // build normal methods 'n', // build admin methods 'n', // helpers? 'n', // components? 'y', // sessions ? 'y' // looks good? )); $filename = '/my/path/BakeArticlesController.php'; $this->Task->expects($this->once())->method('createFile')->with( $filename, $this->stringContains('class BakeArticlesController') ); $this->Task->execute(); } /** * test Interactive mode. * * @return void */ public function testInteractiveAdminMethodsNotInteractive() { $count = count($this->Task->listAll('test')); if ($count != count($this->fixtures)) { $this->markTestSkipped('Additional tables detected.'); } $this->Task->connection = 'test'; $this->Task->interactive = true; $this->Task->path = '/my/path/'; $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls( '1', 'y', // build interactive 'n', // build no scaffolds 'y', // build normal methods 'y', // build admin methods 'n', // helpers? 'n', // components? 'y', // sessions ? 'y' // looks good? )); $this->Task->Project->expects($this->any()) ->method('getPrefix') ->will($this->returnValue('admin_')); $filename = '/my/path/BakeArticlesController.php'; $this->Task->expects($this->once())->method('createFile')->with( $filename, $this->stringContains('class BakeArticlesController') )->will($this->returnValue(true)); $result = $this->Task->execute(); $this->assertRegExp('/admin_index/', $result); } /** * test that execute runs all when the first arg == all * * @return void */ public function testExecuteIntoAll() { $count = count($this->Task->listAll('test')); if ($count != count($this->fixtures)) { $this->markTestSkipped('Additional tables detected.'); } $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('all'); $this->Task->expects($this->any())->method('_checkUnitTest')->will($this->returnValue(true)); $this->Task->Test->expects($this->once())->method('bake'); $filename = '/my/path/BakeArticlesController.php'; $this->Task->expects($this->once())->method('createFile')->with( $filename, $this->stringContains('class BakeArticlesController') )->will($this->returnValue(true)); $this->Task->execute(); } /** * Test execute() with all and --admin * * @return void */ public function testExecuteIntoAllAdmin() { $count = count($this->Task->listAll('test')); if ($count != count($this->fixtures)) { $this->markTestSkipped('Additional tables detected.'); } $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('all'); $this->Task->params['admin'] = true; $this->Task->Project->expects($this->any()) ->method('getPrefix') ->will($this->returnValue('admin_')); $this->Task->expects($this->any()) ->method('_checkUnitTest') ->will($this->returnValue(true)); $this->Task->Test->expects($this->once())->method('bake'); $filename = '/my/path/BakeArticlesController.php'; $this->Task->expects($this->once())->method('createFile')->with( $filename, $this->stringContains('function admin_index') )->will($this->returnValue(true)); $this->Task->execute(); } /** * test that `cake bake controller foos` works. * * @return void */ public function testExecuteWithController() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('BakeArticles'); $filename = '/my/path/BakeArticlesController.php'; $this->Task->expects($this->once())->method('createFile')->with( $filename, $this->stringContains('$scaffold') ); $this->Task->execute(); } /** * data provider for testExecuteWithControllerNameVariations * * @return void */ public static function nameVariations() { return array( array('BakeArticles'), array('BakeArticle'), array('bake_article'), array('bake_articles') ); } /** * test that both plural and singular forms work for controller baking. * * @dataProvider nameVariations * @return void */ public function testExecuteWithControllerNameVariations($name) { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array($name); $filename = '/my/path/BakeArticlesController.php'; $this->Task->expects($this->once())->method('createFile')->with( $filename, $this->stringContains('$scaffold') ); $this->Task->execute(); } /** * test that `cake bake controller foo scaffold` works. * * @return void */ public function testExecuteWithPublicParam() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('BakeArticles'); $this->Task->params = array('public' => true); $filename = '/my/path/BakeArticlesController.php'; $expected = new PHPUnit_Framework_Constraint_Not($this->stringContains('$scaffold')); $this->Task->expects($this->once())->method('createFile')->with( $filename, $expected ); $this->Task->execute(); } /** * test that `cake bake controller foos both` works. * * @return void */ public function testExecuteWithControllerAndBoth() { $this->Task->Project->expects($this->any())->method('getPrefix')->will($this->returnValue('admin_')); $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('BakeArticles'); $this->Task->params = array('public' => true, 'admin' => true); $filename = '/my/path/BakeArticlesController.php'; $this->Task->expects($this->once())->method('createFile')->with( $filename, $this->stringContains('admin_index') ); $this->Task->execute(); } /** * test that `cake bake controller foos admin` works. * * @return void */ public function testExecuteWithControllerAndAdmin() { $this->Task->Project->expects($this->any())->method('getPrefix')->will($this->returnValue('admin_')); $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('BakeArticles'); $this->Task->params = array('admin' => true); $filename = '/my/path/BakeArticlesController.php'; $this->Task->expects($this->once())->method('createFile')->with( $filename, $this->stringContains('admin_index') ); $this->Task->execute(); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/Task/DbConfigTaskTest.php000066400000000000000000000100641265552240500260770ustar00rootroot00000000000000getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('DbConfigTask', array('in', 'out', 'err', 'hr', 'createFile', '_stop', '_checkUnitTest', '_verify'), array($out, $out, $in) ); $this->Task->path = APP . 'Config' . DS; } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Task); } /** * Test the getConfig method. * * @return void */ public function testGetConfig() { $this->Task->expects($this->any()) ->method('in') ->will($this->returnValue('test')); $result = $this->Task->getConfig(); $this->assertEquals('test', $result); } /** * test that initialize sets the path up. * * @return void */ public function testInitialize() { $this->Task->initialize(); $this->assertFalse(empty($this->Task->path)); $this->assertEquals(APP . 'Config' . DS, $this->Task->path); } /** * test execute and by extension _interactive * * @return void */ public function testExecuteIntoInteractive() { $this->Task->initialize(); $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock( 'DbConfigTask', array('in', '_stop', 'createFile', 'bake'), array($out, $out, $in) ); $this->Task->expects($this->once())->method('_stop'); $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('default')); //name $this->Task->expects($this->at(1))->method('in')->will($this->returnValue('mysql')); //db type $this->Task->expects($this->at(2))->method('in')->will($this->returnValue('n')); //persistent $this->Task->expects($this->at(3))->method('in')->will($this->returnValue('localhost')); //server $this->Task->expects($this->at(4))->method('in')->will($this->returnValue('n')); //port $this->Task->expects($this->at(5))->method('in')->will($this->returnValue('root')); //user $this->Task->expects($this->at(6))->method('in')->will($this->returnValue('password')); //password $this->Task->expects($this->at(10))->method('in')->will($this->returnValue('cake_test')); //db $this->Task->expects($this->at(11))->method('in')->will($this->returnValue('n')); //prefix $this->Task->expects($this->at(12))->method('in')->will($this->returnValue('n')); //encoding $this->Task->expects($this->at(13))->method('in')->will($this->returnValue('y')); //looks good $this->Task->expects($this->at(14))->method('in')->will($this->returnValue('n')); //another $this->Task->expects($this->at(15))->method('bake') ->with(array( array( 'name' => 'default', 'datasource' => 'mysql', 'persistent' => 'false', 'host' => 'localhost', 'login' => 'root', 'password' => 'password', 'database' => 'cake_test', 'prefix' => null, 'encoding' => null, 'port' => '', 'schema' => null ) )); $this->Task->execute(); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/Task/ExtractTaskTest.php000066400000000000000000000464501265552240500260460ustar00rootroot00000000000000getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock( 'ExtractTask', array('in', 'out', 'err', '_stop'), array($out, $out, $in) ); $this->path = TMP . 'tests' . DS . 'extract_task_test'; new Folder($this->path . DS . 'locale', true); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Task); $Folder = new Folder($this->path); $Folder->delete(); CakePlugin::unload(); } /** * testExecute method * * @return void */ public function testExecute() { $this->Task->interactive = false; $this->Task->params['paths'] = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS . 'Pages'; $this->Task->params['output'] = $this->path . DS; $this->Task->params['extract-core'] = 'no'; $this->Task->expects($this->never())->method('err'); $this->Task->expects($this->any())->method('in') ->will($this->returnValue('y')); $this->Task->expects($this->never())->method('_stop'); $this->Task->execute(); $this->assertTrue(file_exists($this->path . DS . 'default.pot')); $result = file_get_contents($this->path . DS . 'default.pot'); $this->assertFalse(file_exists($this->path . DS . 'cake.pot')); $pattern = '/"Content-Type\: text\/plain; charset\=utf-8/'; $this->assertRegExp($pattern, $result); $pattern = '/"Content-Transfer-Encoding\: 8bit/'; $this->assertRegExp($pattern, $result); $pattern = '/"Plural-Forms\: nplurals\=INTEGER; plural\=EXPRESSION;/'; $this->assertRegExp($pattern, $result); // 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); $pattern = '/To change its layout, create: APP\/views\/layouts\/default\.ctp\./s'; $this->assertRegExp($pattern, $result); // extract.ctp $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); $pattern = '/\#: extract\.ctp:14\n'; $pattern .= '\#: home\.ctp:68\n'; $pattern .= 'msgid "Editing this Page"\nmsgstr ""/'; $this->assertRegExp($pattern, $result); $pattern = '/\#: extract\.ctp:22\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'; $pattern .= '\\\n - Active, Friendly Community: Join us #cakephp on IRC. We\'d love to help you get started'; $pattern .= '"\nmsgstr ""/'; $this->assertRegExp($pattern, $result); $this->assertContains('msgid "double \\"quoted\\""', $result, 'Strings with quotes not handled correctly'); $this->assertContains("msgid \"single 'quoted'\"", $result, 'Strings with quotes not handled correctly'); $pattern = '/\#: extract\.ctp:36\nmsgid "letter"/'; $this->assertRegExp($pattern, $result, 'Strings with context should not overwrite strings without context'); $pattern = '/\#: extract\.ctp:37;39\nmsgctxt "A"\nmsgid "letter"/'; $this->assertRegExp($pattern, $result, 'Should contain string with context "A"'); $pattern = '/\#: extract\.ctp:38\nmsgctxt "B"\nmsgid "letter"/'; $this->assertRegExp($pattern, $result, 'Should contain string with context "B"'); $pattern = '/\#: extract\.ctp:40\nmsgid "%d letter"\nmsgid_plural "%d letters"/'; $this->assertRegExp($pattern, $result, 'Plural strings with context should not overwrite strings without context'); $pattern = '/\#: extract\.ctp:41\nmsgctxt "A"\nmsgid "%d letter"\nmsgid_plural "%d letters"/'; $this->assertRegExp($pattern, $result, 'Should contain plural string with context "A"'); // extract.ctp - reading the domain.pot $result = file_get_contents($this->path . DS . 'domain.pot'); $pattern = '/msgid "You have %d new message."\nmsgid_plural "You have %d new messages."/'; $this->assertNotRegExp($pattern, $result); $pattern = '/msgid "You deleted %d message."\nmsgid_plural "You deleted %d messages."/'; $this->assertNotRegExp($pattern, $result); $pattern = '/msgid "You have %d new message \(domain\)."\nmsgid_plural "You have %d new messages \(domain\)."/'; $this->assertRegExp($pattern, $result); $pattern = '/msgid "You deleted %d message \(domain\)."\nmsgid_plural "You deleted %d messages \(domain\)."/'; $this->assertRegExp($pattern, $result); } /** * testExtractCategory method * * @return void */ public function testExtractCategory() { $this->Task->interactive = false; $this->Task->params['paths'] = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS . 'Pages'; $this->Task->params['output'] = $this->path . DS; $this->Task->params['extract-core'] = 'no'; $this->Task->params['merge'] = 'no'; $this->Task->expects($this->never())->method('err'); $this->Task->expects($this->any())->method('in') ->will($this->returnValue('y')); $this->Task->expects($this->never())->method('_stop'); $this->Task->execute(); $this->assertTrue(file_exists($this->path . DS . 'LC_NUMERIC' . DS . 'default.pot')); $this->assertFalse(file_exists($this->path . DS . 'LC_TIME' . DS . 'default.pot')); $result = file_get_contents($this->path . DS . 'default.pot'); $pattern = '/\#: .*extract\.ctp:31\n/'; $this->assertNotRegExp($pattern, $result); $pattern = '/\#: .*extract\.ctp:33\n/'; $this->assertNotRegExp($pattern, $result); } /** * testExtractWithoutLocations method * * @return void */ public function testExtractWithoutLocations() { $this->Task->interactive = false; $this->Task->params['paths'] = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS . 'Pages'; $this->Task->params['output'] = $this->path . DS; $this->Task->params['extract-core'] = 'no'; $this->Task->params['merge'] = 'no'; $this->Task->params['no-location'] = true; $this->Task->expects($this->never())->method('err'); $this->Task->expects($this->any())->method('in') ->will($this->returnValue('y')); $this->Task->expects($this->never())->method('_stop'); $this->Task->execute(); $this->assertTrue(file_exists($this->path . DS . 'default.pot')); $result = file_get_contents($this->path . DS . 'default.pot'); $pattern = '/\n\#: .*\n/'; $this->assertNotRegExp($pattern, $result); } /** * test exclusions * * @return void */ public function testExtractWithExclude() { $this->Task->interactive = false; $this->Task->params['paths'] = CAKE . 'Test' . DS . 'test_app' . DS . 'View'; $this->Task->params['output'] = $this->path . DS; $this->Task->params['exclude'] = 'Pages,Layouts'; $this->Task->params['extract-core'] = 'no'; $this->Task->expects($this->any())->method('in') ->will($this->returnValue('y')); $this->Task->execute(); $this->assertTrue(file_exists($this->path . DS . 'default.pot')); $result = file_get_contents($this->path . DS . 'default.pot'); $pattern = '/\#: .*extract\.ctp:6\n/'; $this->assertNotRegExp($pattern, $result); $pattern = '/\#: .*default\.ctp:26\n/'; $this->assertNotRegExp($pattern, $result); } /** * test extract can read more than one path. * * @return void */ public function testExtractMultiplePaths() { $this->Task->interactive = false; $this->Task->params['paths'] = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS . 'Pages,' . CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS . 'Posts'; $this->Task->params['output'] = $this->path . DS; $this->Task->params['extract-core'] = 'no'; $this->Task->expects($this->never())->method('err'); $this->Task->expects($this->never())->method('_stop'); $this->Task->execute(); $result = file_get_contents($this->path . DS . 'default.pot'); $pattern = '/msgid "Add User"/'; $this->assertRegExp($pattern, $result); } /** * Tests that it is possible to exclude plugin paths by enabling the param option for the ExtractTask * * @return void */ public function testExtractExcludePlugins() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); $this->out = $this->getMock('ConsoleOutput', array(), array(), '', false); $this->in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ExtractTask', array('_isExtractingApp', '_extractValidationMessages', 'in', 'out', 'err', 'clear', '_stop'), array($this->out, $this->out, $this->in) ); $this->Task->expects($this->exactly(2))->method('_isExtractingApp')->will($this->returnValue(true)); $this->Task->params['paths'] = CAKE . 'Test' . DS . 'test_app' . DS; $this->Task->params['output'] = $this->path . DS; $this->Task->params['exclude-plugins'] = true; $this->Task->execute(); $result = file_get_contents($this->path . DS . 'default.pot'); $this->assertNotRegExp('#TestPlugin#', $result); } /** * Test that is possible to extract messages form a single plugin * * @return void */ public function testExtractPlugin() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); $this->out = $this->getMock('ConsoleOutput', array(), array(), '', false); $this->in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ExtractTask', array('_isExtractingApp', 'in', 'out', 'err', 'clear', '_stop'), array($this->out, $this->out, $this->in) ); $this->Task->params['output'] = $this->path . DS; $this->Task->params['plugin'] = 'TestPlugin'; $this->Task->execute(); $result = file_get_contents($this->path . DS . 'default.pot'); $this->assertNotRegExp('#Pages#', $result); $this->assertContains('translate.ctp:1', $result); $this->assertContains('This is a translatable string', $result); $this->assertContains('I can haz plugin model validation message', $result); } /** * Tests that the task will inspect application models and extract the validation messages from them * * @return void */ public function testExtractModelValidation() { App::build(array( 'Model' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS), 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); $this->out = $this->getMock('ConsoleOutput', array(), array(), '', false); $this->in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ExtractTask', array('_isExtractingApp', 'in', 'out', 'err', 'clear', '_stop'), array($this->out, $this->out, $this->in) ); $this->Task->expects($this->exactly(2))->method('_isExtractingApp')->will($this->returnValue(true)); $this->Task->params['paths'] = CAKE . 'Test' . DS . 'test_app' . DS; $this->Task->params['output'] = $this->path . DS; $this->Task->params['extract-core'] = 'no'; $this->Task->params['exclude-plugins'] = true; $this->Task->params['ignore-model-validation'] = false; $this->Task->execute(); $result = file_get_contents($this->path . DS . 'default.pot'); $pattern = preg_quote('#Model/PersisterOne.php:validation for field title#', '\\'); $this->assertRegExp($pattern, $result); $pattern = preg_quote('#Model/PersisterOne.php:validation for field body#', '\\'); $this->assertRegExp($pattern, $result); $pattern = '#msgid "Post title is required"#'; $this->assertRegExp($pattern, $result); $pattern = '#msgid "You may enter up to %s chars \(minimum is %s chars\)"#'; $this->assertRegExp($pattern, $result); $pattern = '#msgid "Post body is required"#'; $this->assertRegExp($pattern, $result); $pattern = '#msgid "Post body is super required"#'; $this->assertRegExp($pattern, $result); $this->assertContains('msgid "double \\"quoted\\" validation"', $result, 'Strings with quotes not handled correctly'); $this->assertContains("msgid \"single 'quoted' validation\"", $result, 'Strings with quotes not handled correctly'); } /** * Tests that the task will inspect application models and extract the validation messages from them * while using a custom validation domain for the messages set on the model itself * * @return void */ public function testExtractModelValidationWithDomainInModel() { App::build(array( 'Model' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS . 'TestPlugin' . DS . 'Model' . DS) )); $this->out = $this->getMock('ConsoleOutput', array(), array(), '', false); $this->in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ExtractTask', array('_isExtractingApp', 'in', 'out', 'err', 'clear', '_stop'), array($this->out, $this->out, $this->in) ); $this->Task->expects($this->exactly(2))->method('_isExtractingApp')->will($this->returnValue(true)); $this->Task->params['paths'] = CAKE . 'Test' . DS . 'test_app' . DS; $this->Task->params['output'] = $this->path . DS; $this->Task->params['extract-core'] = 'no'; $this->Task->params['exclude-plugins'] = true; $this->Task->params['ignore-model-validation'] = false; $this->Task->execute(); $result = file_get_contents($this->path . DS . 'test_plugin.pot'); $pattern = preg_quote('#Plugin/TestPlugin/Model/TestPluginPost.php:validation for field title#', '\\'); $this->assertRegExp($pattern, $result); $pattern = preg_quote('#Plugin/TestPlugin/Model/TestPluginPost.php:validation for field body#', '\\'); $this->assertRegExp($pattern, $result); $pattern = '#msgid "Post title is required"#'; $this->assertRegExp($pattern, $result); $pattern = '#msgid "Post body is required"#'; $this->assertRegExp($pattern, $result); $pattern = '#msgid "Post body is super required"#'; $this->assertRegExp($pattern, $result); } /** * Test that the extract shell can obtain validation messages from models inside a specific plugin * * @return void */ public function testExtractModelValidationInPlugin() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); $this->out = $this->getMock('ConsoleOutput', array(), array(), '', false); $this->in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ExtractTask', array('_isExtractingApp', 'in', 'out', 'err', 'clear', '_stop'), array($this->out, $this->out, $this->in) ); $this->Task->params['output'] = $this->path . DS; $this->Task->params['ignore-model-validation'] = false; $this->Task->params['plugin'] = 'TestPlugin'; $this->Task->execute(); $result = file_get_contents($this->path . DS . 'test_plugin.pot'); $pattern = preg_quote('#Model/TestPluginPost.php:validation for field title#', '\\'); $this->assertRegExp($pattern, $result); $pattern = preg_quote('#Model/TestPluginPost.php:validation for field body#', '\\'); $this->assertRegExp($pattern, $result); $pattern = '#msgid "Post title is required"#'; $this->assertRegExp($pattern, $result); $pattern = '#msgid "Post body is required"#'; $this->assertRegExp($pattern, $result); $pattern = '#msgid "Post body is super required"#'; $this->assertRegExp($pattern, $result); $pattern = '#Plugin/TestPlugin/Model/TestPluginPost.php:validation for field title#'; $this->assertNotRegExp($pattern, $result); } /** * Test that the extract shell overwrites existing files with the overwrite parameter * * @return void */ public function testExtractOverwrite() { $this->Task->interactive = false; $this->Task->params['paths'] = CAKE . 'Test' . DS . 'test_app' . DS; $this->Task->params['output'] = $this->path . DS; $this->Task->params['extract-core'] = 'no'; $this->Task->params['overwrite'] = true; file_put_contents($this->path . DS . 'default.pot', 'will be overwritten'); $this->assertTrue(file_exists($this->path . DS . 'default.pot')); $original = file_get_contents($this->path . DS . 'default.pot'); $this->Task->execute(); $result = file_get_contents($this->path . DS . 'default.pot'); $this->assertNotEquals($original, $result); } /** * Test that the extract shell scans the core libs * * @return void */ public function testExtractCore() { $this->Task->interactive = false; $this->Task->params['paths'] = CAKE . 'Test' . DS . 'test_app' . DS; $this->Task->params['output'] = $this->path . DS; $this->Task->params['extract-core'] = 'yes'; $this->Task->execute(); $this->assertTrue(file_exists($this->path . DS . 'cake.pot')); $result = file_get_contents($this->path . DS . 'cake.pot'); $pattern = '/msgid "Yesterday, %s"\nmsgstr ""\n/'; $this->assertRegExp($pattern, $result); $this->assertTrue(file_exists($this->path . DS . 'cake_dev.pot')); $result = file_get_contents($this->path . DS . 'cake_dev.pot'); $pattern = '/#: Console\/Templates\//'; $this->assertNotRegExp($pattern, $result); $pattern = '/#: Test\//'; $this->assertNotRegExp($pattern, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/Task/FixtureTaskTest.php000066400000000000000000000342011265552240500260510ustar00rootroot00000000000000getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('FixtureTask', array('in', 'err', 'createFile', '_stop', 'clear'), array($out, $out, $in) ); $this->Task->Model = $this->getMock('ModelTask', array('in', 'out', 'err', 'createFile', 'getName', 'getTable', 'listAll'), array($out, $out, $in) ); $this->Task->Template = new TemplateTask($out, $out, $in); $this->Task->DbConfig = $this->getMock('DbConfigTask', array(), array($out, $out, $in)); $this->Task->Template->initialize(); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Task); } /** * test that initialize sets the path * * @return void */ public function testConstruct() { $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $Task = new FixtureTask($out, $out, $in); $this->assertEquals(APP . 'Test' . DS . 'Fixture' . DS, $Task->path); } /** * test import option array generation * * @return void */ public function testImportOptionsSchemaRecords() { $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y')); $this->Task->expects($this->at(1))->method('in')->will($this->returnValue('y')); $result = $this->Task->importOptions('Article'); $expected = array('schema' => 'Article', 'records' => true); $this->assertEquals($expected, $result); } /** * test importOptions choosing nothing. * * @return void */ public function testImportOptionsNothing() { $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('n')); $this->Task->expects($this->at(1))->method('in')->will($this->returnValue('n')); $this->Task->expects($this->at(2))->method('in')->will($this->returnValue('n')); $result = $this->Task->importOptions('Article'); $expected = array(); $this->assertEquals($expected, $result); } /** * test importOptions with overwriting command line options. * * @return void */ public function testImportOptionsWithCommandLineOptions() { $this->Task->params = array('schema' => true, 'records' => true); $result = $this->Task->importOptions('Article'); $expected = array('schema' => 'Article', 'records' => true); $this->assertEquals($expected, $result); } /** * test importOptions with schema. * * @return void */ public function testImportOptionsWithSchema() { $this->Task->params = array('schema' => true); $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('n')); $this->Task->expects($this->at(1))->method('in')->will($this->returnValue('n')); $result = $this->Task->importOptions('Article'); $expected = array('schema' => 'Article'); $this->assertEquals($expected, $result); } /** * test importOptions with records. * * @return void */ public function testImportOptionsWithRecords() { $this->Task->params = array('records' => true); $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('n')); $result = $this->Task->importOptions('Article'); $expected = array('records' => true); $this->assertEquals($expected, $result); } /** * test importOptions choosing from Table. * * @return void */ public function testImportOptionsTable() { $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('n')); $this->Task->expects($this->at(1))->method('in')->will($this->returnValue('n')); $this->Task->expects($this->at(2))->method('in')->will($this->returnValue('y')); $result = $this->Task->importOptions('Article'); $expected = array('fromTable' => true); $this->assertEquals($expected, $result); } /** * test generating a fixture with database conditions. * * @return void */ public function testImportRecordsFromDatabaseWithConditionsPoo() { $this->Task->interactive = true; $this->Task->expects($this->at(0))->method('in') ->will($this->returnValue('WHERE 1=1')); $this->Task->expects($this->at(1))->method('in') ->with($this->anything(), $this->anything(), '3') ->will($this->returnValue('2')); $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $result = $this->Task->bake('Article', false, array( 'fromTable' => true, 'schema' => 'Article', 'records' => false )); $this->assertContains('class ArticleFixture extends CakeTestFixture', $result); $this->assertContains('public $records', $result); $this->assertContains('public $import', $result); $this->assertContains("'title' => 'First Article'", $result, 'Missing import data'); $this->assertContains('Second Article', $result, 'Missing import data'); } /** * test that connection gets set to the import options when a different connection is used. * * @return void */ public function testImportOptionsAlternateConnection() { $this->Task->connection = 'test'; $result = $this->Task->bake('Article', false, array('schema' => 'Article')); $this->assertContains("'connection' => 'test'", $result); } /** * Ensure that fixture data doesn't get overly escaped. * * @return void */ public function testImportRecordsNoEscaping() { $db = ConnectionManager::getDataSource('test'); if ($db instanceof Sqlserver) { $this->markTestSkipped('This test does not run on SQLServer'); } $Article = ClassRegistry::init('Article'); $Article->updateAll(array('body' => "'Body \"value\"'")); $this->Task->interactive = true; $this->Task->expects($this->at(0)) ->method('in') ->will($this->returnValue('WHERE 1=1 LIMIT 10')); $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $result = $this->Task->bake('Article', false, array( 'fromTable' => true, 'schema' => 'Article', 'records' => false )); $this->assertContains("'body' => 'Body \"value\"'", $result, 'Data has bad escaping'); } /** * test that execute passes runs bake depending with named model. * * @return void */ public function testExecuteWithNamedModel() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('article'); $filename = '/my/path/ArticleFixture.php'; $this->Task->expects($this->at(0))->method('createFile') ->with($filename, $this->stringContains('class ArticleFixture')); $this->Task->execute(); } /** * test that execute runs all() when args[0] = all * * @return void */ public function testExecuteIntoAll() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('all'); $this->Task->Model->expects($this->any()) ->method('listAll') ->will($this->returnValue(array('articles', 'comments'))); $filename = '/my/path/ArticleFixture.php'; $this->Task->expects($this->at(0)) ->method('createFile') ->with($filename, $this->stringContains('class ArticleFixture')); $filename = '/my/path/CommentFixture.php'; $this->Task->expects($this->at(1)) ->method('createFile') ->with($filename, $this->stringContains('class CommentFixture')); $this->Task->execute(); } /** * test using all() with -count and -records * * @return void */ public function testAllWithCountAndRecordsFlags() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('all'); $this->Task->params = array('count' => 10, 'records' => true); $this->Task->Model->expects($this->any())->method('listAll') ->will($this->returnValue(array('Articles', 'comments'))); $filename = '/my/path/ArticleFixture.php'; $this->Task->expects($this->at(0))->method('createFile') ->with($filename, $this->stringContains("'title' => 'Third Article'")); $filename = '/my/path/CommentFixture.php'; $this->Task->expects($this->at(1))->method('createFile') ->with($filename, $this->stringContains("'comment' => 'First Comment for First Article'")); $this->Task->expects($this->exactly(2))->method('createFile'); $this->Task->all(); } /** * test using all() with -schema * * @return void */ public function testAllWithSchemaImport() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('all'); $this->Task->params = array('schema' => true); $this->Task->Model->expects($this->any())->method('listAll') ->will($this->returnValue(array('Articles', 'comments'))); $filename = '/my/path/ArticleFixture.php'; $this->Task->expects($this->at(0))->method('createFile') ->with($filename, $this->stringContains('public $import = array(\'model\' => \'Article\'')); $filename = '/my/path/CommentFixture.php'; $this->Task->expects($this->at(1))->method('createFile') ->with($filename, $this->stringContains('public $import = array(\'model\' => \'Comment\'')); $this->Task->expects($this->exactly(2))->method('createFile'); $this->Task->all(); } /** * test interactive mode of execute * * @return void */ public function testExecuteInteractive() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->expects($this->any())->method('in')->will($this->returnValue('y')); $this->Task->Model->expects($this->any())->method('getName')->will($this->returnValue('Article')); $this->Task->Model->expects($this->any())->method('getTable') ->with('Article') ->will($this->returnValue('articles')); $filename = '/my/path/ArticleFixture.php'; $this->Task->expects($this->once())->method('createFile') ->with($filename, $this->stringContains('class ArticleFixture')); $this->Task->execute(); } /** * Test that bake works * * @return void */ public function testBake() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $result = $this->Task->bake('Article'); $this->assertContains('class ArticleFixture extends CakeTestFixture', $result); $this->assertContains('public $fields', $result); $this->assertContains('public $records', $result); $this->assertNotContains('public $import', $result); $result = $this->Task->bake('Article', 'comments'); $this->assertContains('class ArticleFixture extends CakeTestFixture', $result); $this->assertContains('public $table = \'comments\';', $result); $this->assertContains('public $fields = array(', $result); $result = $this->Task->bake('Article', 'comments', array('records' => true)); $this->assertContains("public \$import = array('records' => true, 'connection' => 'test');", $result); $this->assertNotContains('public $records', $result); $result = $this->Task->bake('Article', 'comments', array('schema' => 'Article')); $this->assertContains("public \$import = array('model' => 'Article', 'connection' => 'test');", $result); $this->assertNotContains('public $fields', $result); $result = $this->Task->bake('Article', 'comments', array('schema' => 'Article', 'records' => true)); $this->assertContains("public \$import = array('model' => 'Article', 'records' => true, 'connection' => 'test');", $result); $this->assertNotContains('public $fields', $result); $this->assertNotContains('public $records', $result); } /** * test record generation with float and binary types * * @return void */ public function testRecordGenerationForBinaryAndFloat() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $result = $this->Task->bake('Article', 'datatypes'); $this->assertContains("'float_field' => 1", $result); $this->assertContains("'bool' => 1", $result); $result = $this->Task->bake('Article', 'binary_tests'); $this->assertContains("'data' => 'Lorem ipsum dolor sit amet'", $result); } /** * Test that file generation includes headers and correct path for plugins. * * @return void */ public function testGenerateFixtureFile() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $filename = '/my/path/ArticleFixture.php'; $this->Task->expects($this->at(0))->method('createFile') ->with($filename, $this->stringContains('ArticleFixture')); $this->Task->expects($this->at(1))->method('createFile') ->with($filename, $this->stringContains('Task->generateFixtureFile('Article', array()); $this->Task->generateFixtureFile('Article', array()); } /** * test generating files into plugins. * * @return void */ public function testGeneratePluginFixtureFile() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->plugin = 'TestFixture'; $filename = APP . 'Plugin' . DS . 'TestFixture' . DS . 'Test' . DS . 'Fixture' . DS . 'ArticleFixture.php'; //fake plugin path CakePlugin::load('TestFixture', array('path' => APP . 'Plugin' . DS . 'TestFixture' . DS)); $this->Task->expects($this->at(0))->method('createFile') ->with($filename, $this->stringContains('class Article')); $this->Task->generateFixtureFile('Article', array()); CakePlugin::unload(); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/Task/ModelTaskTest.php000066400000000000000000001176771265552240500255060ustar00rootroot00000000000000getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ModelTask', array('in', 'err', 'createFile', '_stop', '_checkUnitTest'), array($out, $out, $in) ); $this->_setupOtherMocks(); } /** * Setup a mock that has out mocked. Normally this is not used as it makes $this->at() really tricky. * * @return void */ protected function _useMockedOut() { $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ModelTask', array('in', 'out', 'err', 'hr', 'createFile', '_stop', '_checkUnitTest'), array($out, $out, $in) ); $this->_setupOtherMocks(); } /** * sets up the rest of the dependencies for Model Task * * @return void */ protected function _setupOtherMocks() { $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task->Fixture = $this->getMock('FixtureTask', array(), array($out, $out, $in)); $this->Task->Test = $this->getMock('FixtureTask', array(), array($out, $out, $in)); $this->Task->Template = new TemplateTask($out, $out, $in); $this->Task->name = 'Model'; $this->Task->interactive = true; } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Task); } /** * Test that listAll scans the database connection and lists all the tables in it.s * * @return void */ public function testListAllArgument() { $this->_useMockedOut(); $result = $this->Task->listAll('test'); $this->assertContains('bake_articles', $result); $this->assertContains('bake_articles_bake_tags', $result); $this->assertContains('bake_tags', $result); $this->assertContains('bake_comments', $result); $this->assertContains('category_threads', $result); } /** * Test that listAll uses the connection property * * @return void */ public function testListAllConnection() { $this->_useMockedOut(); $this->Task->connection = 'test'; $result = $this->Task->listAll(); $this->assertContains('bake_articles', $result); $this->assertContains('bake_articles_bake_tags', $result); $this->assertContains('bake_tags', $result); $this->assertContains('bake_comments', $result); $this->assertContains('category_threads', $result); } /** * Test that getName interacts with the user and returns the model name. * * @return void */ public function testGetNameQuit() { $this->Task->expects($this->once())->method('in')->will($this->returnValue('q')); $this->Task->expects($this->once())->method('_stop'); $this->Task->getName('test'); } /** * test getName with a valid option. * * @return void */ public function testGetNameValidOption() { $listing = $this->Task->listAll('test'); $this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls(1, 4)); $result = $this->Task->getName('test'); $this->assertEquals(Inflector::classify($listing[0]), $result); $result = $this->Task->getName('test'); $this->assertEquals(Inflector::classify($listing[3]), $result); } /** * test that an out of bounds option causes an error. * * @return void */ public function testGetNameWithOutOfBoundsOption() { $this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls(99, 1)); $this->Task->expects($this->once())->method('err'); $this->Task->getName('test'); } /** * Test table name interactions * * @return void */ public function testGetTableName() { $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y')); $result = $this->Task->getTable('BakeArticle', 'test'); $expected = 'bake_articles'; $this->assertEquals($expected, $result); } /** * test getting a custom table name. * * @return void */ public function testGetTableNameCustom() { $this->Task->expects($this->any())->method('in')->will($this->onConsecutiveCalls('n', 'my_table')); $result = $this->Task->getTable('BakeArticle', 'test'); $expected = 'my_table'; $this->assertEquals($expected, $result); } /** * test getTable with non-conventional tablenames * * @return void */ public function testGetTableOddTableInteractive() { $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ModelTask', array('in', 'err', '_stop', '_checkUnitTest', 'getAllTables'), array($out, $out, $in) ); $this->_setupOtherMocks(); $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->interactive = true; $this->Task->expects($this->once())->method('getAllTables')->will($this->returnValue(array('articles', 'bake_odd'))); $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls( 2 // bake_odd )); $result = $this->Task->getName(); $expected = 'BakeOdd'; $this->assertEquals($expected, $result); $result = $this->Task->getTable($result); $expected = 'bake_odd'; $this->assertEquals($expected, $result); } /** * test getTable with non-conventional tablenames * * @return void */ public function testGetTableOddTable() { $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ModelTask', array('in', 'err', '_stop', '_checkUnitTest', 'getAllTables'), array($out, $out, $in) ); $this->_setupOtherMocks(); $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->interactive = false; $this->Task->args = array('BakeOdd'); $this->Task->expects($this->once())->method('getAllTables')->will($this->returnValue(array('articles', 'bake_odd'))); $this->Task->listAll(); $result = $this->Task->getTable('BakeOdd'); $expected = 'bake_odd'; $this->assertEquals($expected, $result); } /** * test that initializing the validations works. * * @return void */ public function testInitValidations() { $result = $this->Task->initValidations(); $this->assertTrue(in_array('notBlank', $result)); } /** * test that individual field validation works, with interactive = false * tests the guessing features of validation * * @return void */ public function testFieldValidationGuessing() { $this->Task->interactive = false; $this->Task->initValidations(); $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false)); $expected = array('notBlank' => 'notBlank'); $this->assertEquals($expected, $result); $result = $this->Task->fieldValidation('text', array('type' => 'date', 'length' => 10, 'null' => false)); $expected = array('date' => 'date'); $this->assertEquals($expected, $result); $result = $this->Task->fieldValidation('text', array('type' => 'time', 'length' => 10, 'null' => false)); $expected = array('time' => 'time'); $this->assertEquals($expected, $result); $result = $this->Task->fieldValidation('email', array('type' => 'string', 'length' => 10, 'null' => false)); $expected = array('email' => 'email'); $this->assertEquals($expected, $result); $result = $this->Task->fieldValidation('test', array('type' => 'integer', 'length' => 10, 'null' => false)); $expected = array('numeric' => 'numeric'); $this->assertEquals($expected, $result); $result = $this->Task->fieldValidation('test', array('type' => 'boolean', 'length' => 10, 'null' => false)); $expected = array('boolean' => 'boolean'); $this->assertEquals($expected, $result); } /** * test that interactive field validation works and returns multiple validators. * * @return void */ public function testInteractiveFieldValidation() { $this->Task->initValidations(); $this->Task->interactive = true; $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls('24', 'y', '18', 'n')); $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false)); $expected = array('notBlank' => 'notBlank', 'maxLength' => 'maxLength'); $this->assertEquals($expected, $result); } /** * test that a bogus response doesn't cause errors to bubble up. * * @return void */ public function testInteractiveFieldValidationWithBogusResponse() { $this->_useMockedOut(); $this->Task->initValidations(); $this->Task->interactive = true; $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls('999999', '24', 'n')); $this->Task->expects($this->at(10))->method('out') ->with($this->stringContains('make a valid')); $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false)); $expected = array('notBlank' => 'notBlank'); $this->assertEquals($expected, $result); } /** * test that a regular expression can be used for validation. * * @return void */ public function testInteractiveFieldValidationWithRegexp() { $this->Task->initValidations(); $this->Task->interactive = true; $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls('/^[a-z]{0,9}$/', 'n')); $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false)); $expected = array('a_z_0_9' => '/^[a-z]{0,9}$/'); $this->assertEquals($expected, $result); } /** * Test that skipping fields during rule choice works when doing interactive field validation. * * @return void */ public function testSkippingChoiceInteractiveFieldValidation() { $this->Task->initValidations(); $this->Task->interactive = true; $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls('24', 'y', 's')); $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false)); $expected = array('notBlank' => 'notBlank', '_skipFields' => true); $this->assertEquals($expected, $result); } /** * Test that skipping fields after rule choice works when doing interactive field validation. * * @return void */ public function testSkippingAnotherInteractiveFieldValidation() { $this->Task->initValidations(); $this->Task->interactive = true; $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls('24', 's')); $result = $this->Task->fieldValidation('text', array('type' => 'string', 'length' => 10, 'null' => false)); $expected = array('notBlank' => 'notBlank', '_skipFields' => true); $this->assertEquals($expected, $result); } /** * Test the validation generation routine with skipping the rest of the fields * when doing interactive field validation. * * @return void */ public function testInteractiveDoValidationWithSkipping() { $this->Task->expects($this->any()) ->method('in') ->will($this->onConsecutiveCalls('35', '24', 'n', '10', 's')); $this->Task->interactive = true; $Model = $this->getMock('Model'); $Model->primaryKey = 'id'; $Model->expects($this->any()) ->method('schema') ->will($this->returnValue(array( 'id' => array( 'type' => 'integer', 'length' => 11, 'null' => false, 'key' => 'primary', ), 'name' => array( 'type' => 'string', 'length' => 20, 'null' => false, ), 'email' => array( 'type' => 'string', 'length' => 255, 'null' => false, ), 'some_date' => array( 'type' => 'date', 'length' => '', 'null' => false, ), 'some_time' => array( 'type' => 'time', 'length' => '', 'null' => false, ), 'created' => array( 'type' => 'datetime', 'length' => '', 'null' => false, ) ) )); $result = $this->Task->doValidation($Model); $expected = array( 'name' => array( 'notBlank' => 'notBlank' ), 'email' => array( 'email' => 'email', ), ); $this->assertEquals($expected, $result); } /** * test the validation Generation routine * * @return void */ public function testNonInteractiveDoValidation() { $Model = $this->getMock('Model'); $Model->primaryKey = 'id'; $Model->expects($this->any()) ->method('schema') ->will($this->returnValue(array( 'id' => array( 'type' => 'integer', 'length' => 11, 'null' => false, 'key' => 'primary', ), 'name' => array( 'type' => 'string', 'length' => 20, 'null' => false, ), 'email' => array( 'type' => 'string', 'length' => 255, 'null' => false, ), 'some_date' => array( 'type' => 'date', 'length' => '', 'null' => false, ), 'some_time' => array( 'type' => 'time', 'length' => '', 'null' => false, ), 'created' => array( 'type' => 'datetime', 'length' => '', 'null' => false, ) ) )); $this->Task->interactive = false; $result = $this->Task->doValidation($Model); $expected = array( 'name' => array( 'notBlank' => 'notBlank' ), 'email' => array( 'email' => 'email', ), 'some_date' => array( 'date' => 'date' ), 'some_time' => array( 'time' => 'time' ), ); $this->assertEquals($expected, $result); } /** * test that finding primary key works * * @return void */ public function testFindPrimaryKey() { $fields = array( 'one' => array(), 'two' => array(), 'key' => array('key' => 'primary') ); $anything = new PHPUnit_Framework_Constraint_IsAnything(); $this->Task->expects($this->once())->method('in') ->with($anything, null, 'key') ->will($this->returnValue('my_field')); $result = $this->Task->findPrimaryKey($fields); $expected = 'my_field'; $this->assertEquals($expected, $result); } /** * test finding Display field * * @return void */ public function testFindDisplayFieldNone() { $fields = array( 'id' => array(), 'tagname' => array(), 'body' => array(), 'created' => array(), 'modified' => array() ); $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('n')); $result = $this->Task->findDisplayField($fields); $this->assertFalse($result); } /** * Test finding a displayname from user input * * @return void */ public function testFindDisplayName() { $fields = array( 'id' => array(), 'tagname' => array(), 'body' => array(), 'created' => array(), 'modified' => array() ); $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls('y', 2)); $result = $this->Task->findDisplayField($fields); $this->assertEquals('tagname', $result); } /** * test that belongsTo generation works. * * @return void */ public function testBelongsToGeneration() { $model = new Model(array('ds' => 'test', 'name' => 'BakeComment')); $result = $this->Task->findBelongsTo($model, array()); $expected = array( 'belongsTo' => array( array( 'alias' => 'BakeArticle', 'className' => 'BakeArticle', 'foreignKey' => 'bake_article_id', ), array( 'alias' => 'BakeUser', 'className' => 'BakeUser', 'foreignKey' => 'bake_user_id', ), ) ); $this->assertEquals($expected, $result); $model = new Model(array('ds' => 'test', 'name' => 'CategoryThread')); $result = $this->Task->findBelongsTo($model, array()); $expected = array( 'belongsTo' => array( array( 'alias' => 'ParentCategoryThread', 'className' => 'CategoryThread', 'foreignKey' => 'parent_id', ), ) ); $this->assertEquals($expected, $result); } /** * test that hasOne and/or hasMany relations are generated properly. * * @return void */ public function testHasManyHasOneGeneration() { $model = new Model(array('ds' => 'test', 'name' => 'BakeArticle')); $this->Task->connection = 'test'; $this->Task->listAll(); $result = $this->Task->findHasOneAndMany($model, array()); $expected = array( 'hasMany' => array( array( 'alias' => 'BakeComment', 'className' => 'BakeComment', 'foreignKey' => 'bake_article_id', ), ), 'hasOne' => array( array( 'alias' => 'BakeComment', 'className' => 'BakeComment', 'foreignKey' => 'bake_article_id', ), ), ); $this->assertEquals($expected, $result); $model = new Model(array('ds' => 'test', 'name' => 'CategoryThread')); $result = $this->Task->findHasOneAndMany($model, array()); $expected = array( 'hasOne' => array( array( 'alias' => 'ChildCategoryThread', 'className' => 'CategoryThread', 'foreignKey' => 'parent_id', ), ), 'hasMany' => array( array( 'alias' => 'ChildCategoryThread', 'className' => 'CategoryThread', 'foreignKey' => 'parent_id', ), ) ); $this->assertEquals($expected, $result); } /** * Test that HABTM generation works * * @return void */ public function testHasAndBelongsToManyGeneration() { $model = new Model(array('ds' => 'test', 'name' => 'BakeArticle')); $this->Task->connection = 'test'; $this->Task->listAll(); $result = $this->Task->findHasAndBelongsToMany($model, array()); $expected = array( 'hasAndBelongsToMany' => array( array( 'alias' => 'BakeTag', 'className' => 'BakeTag', 'foreignKey' => 'bake_article_id', 'joinTable' => 'bake_articles_bake_tags', 'associationForeignKey' => 'bake_tag_id', ), ), ); $this->assertEquals($expected, $result); } /** * test non interactive doAssociations * * @return void */ public function testDoAssociationsNonInteractive() { $this->Task->connection = 'test'; $this->Task->interactive = false; $model = new Model(array('ds' => 'test', 'name' => 'BakeArticle')); $result = $this->Task->doAssociations($model); $expected = array( 'belongsTo' => array( array( 'alias' => 'BakeUser', 'className' => 'BakeUser', 'foreignKey' => 'bake_user_id', ), ), 'hasMany' => array( array( 'alias' => 'BakeComment', 'className' => 'BakeComment', 'foreignKey' => 'bake_article_id', ), ), 'hasAndBelongsToMany' => array( array( 'alias' => 'BakeTag', 'className' => 'BakeTag', 'foreignKey' => 'bake_article_id', 'joinTable' => 'bake_articles_bake_tags', 'associationForeignKey' => 'bake_tag_id', ), ), ); $this->assertEquals($expected, $result); } /** * test non interactive doActsAs * * @return void */ public function testDoActsAs() { $this->Task->connection = 'test'; $this->Task->interactive = false; $model = new Model(array('ds' => 'test', 'name' => 'NumberTree')); $result = $this->Task->doActsAs($model); $this->assertEquals(array('Tree'), $result); } /** * Ensure that the fixture object is correctly called. * * @return void */ public function testBakeFixture() { $this->Task->plugin = 'TestPlugin'; $this->Task->interactive = true; $this->Task->Fixture->expects($this->at(0))->method('bake')->with('BakeArticle', 'bake_articles'); $this->Task->bakeFixture('BakeArticle', 'bake_articles'); $this->assertEquals($this->Task->plugin, $this->Task->Fixture->plugin); $this->assertEquals($this->Task->connection, $this->Task->Fixture->connection); $this->assertEquals($this->Task->interactive, $this->Task->Fixture->interactive); } /** * Ensure that the test object is correctly called. * * @return void */ public function testBakeTest() { $this->Task->plugin = 'TestPlugin'; $this->Task->interactive = true; $this->Task->Test->expects($this->at(0))->method('bake')->with('Model', 'BakeArticle'); $this->Task->bakeTest('BakeArticle'); $this->assertEquals($this->Task->plugin, $this->Task->Test->plugin); $this->assertEquals($this->Task->connection, $this->Task->Test->connection); $this->assertEquals($this->Task->interactive, $this->Task->Test->interactive); } /** * test confirming of associations, and that when an association is hasMany * a question for the hasOne is also not asked. * * @return void */ public function testConfirmAssociations() { $associations = array( 'hasOne' => array( array( 'alias' => 'ChildCategoryThread', 'className' => 'CategoryThread', 'foreignKey' => 'parent_id', ), ), 'hasMany' => array( array( 'alias' => 'ChildCategoryThread', 'className' => 'CategoryThread', 'foreignKey' => 'parent_id', ), ), 'belongsTo' => array( array( 'alias' => 'User', 'className' => 'User', 'foreignKey' => 'user_id', ), ) ); $model = new Model(array('ds' => 'test', 'name' => 'CategoryThread')); $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls('n', 'y', 'n', 'n', 'n')); $result = $this->Task->confirmAssociations($model, $associations); $this->assertTrue(empty($result['hasOne'])); $result = $this->Task->confirmAssociations($model, $associations); $this->assertTrue(empty($result['hasMany'])); $this->assertTrue(empty($result['hasOne'])); } /** * test that inOptions generates questions and only accepts a valid answer * * @return void */ public function testInOptions() { $this->_useMockedOut(); $options = array('one', 'two', 'three'); $this->Task->expects($this->at(0))->method('out')->with('1. one'); $this->Task->expects($this->at(1))->method('out')->with('2. two'); $this->Task->expects($this->at(2))->method('out')->with('3. three'); $this->Task->expects($this->at(3))->method('in')->will($this->returnValue(10)); $this->Task->expects($this->at(4))->method('out')->with('1. one'); $this->Task->expects($this->at(5))->method('out')->with('2. two'); $this->Task->expects($this->at(6))->method('out')->with('3. three'); $this->Task->expects($this->at(7))->method('in')->will($this->returnValue(2)); $result = $this->Task->inOptions($options, 'Pick a number'); $this->assertEquals(1, $result); } /** * test baking validation * * @return void */ public function testBakeValidation() { $validate = array( 'name' => array( 'notBlank' => 'notBlank' ), 'email' => array( 'email' => 'email', ), 'some_date' => array( 'date' => 'date' ), 'some_time' => array( 'time' => 'time' ) ); $result = $this->Task->bake('BakeArticle', compact('validate')); $this->assertRegExp('/class BakeArticle extends AppModel \{/', $result); $this->assertRegExp('/\$validate \= array\(/', $result); $expected = <<< STRINGEND array( 'notBlank' => array( 'rule' => array('notBlank'), //'message' => 'Your custom message here', //'allowEmpty' => false, //'required' => false, //'last' => false, // Stop validation after this rule //'on' => 'create', // Limit validation to 'create' or 'update' operations ), STRINGEND; $this->assertRegExp('/' . preg_quote(str_replace("\r\n", "\n", $expected), '/') . '/', $result); } /** * test baking relations * * @return void */ public function testBakeRelations() { $associations = array( 'belongsTo' => array( array( 'alias' => 'SomethingElse', 'className' => 'SomethingElse', 'foreignKey' => 'something_else_id', ), array( 'alias' => 'BakeUser', 'className' => 'BakeUser', 'foreignKey' => 'bake_user_id', ), ), 'hasOne' => array( array( 'alias' => 'OtherModel', 'className' => 'OtherModel', 'foreignKey' => 'other_model_id', ), ), 'hasMany' => array( array( 'alias' => 'BakeComment', 'className' => 'BakeComment', 'foreignKey' => 'parent_id', ), ), 'hasAndBelongsToMany' => array( array( 'alias' => 'BakeTag', 'className' => 'BakeTag', 'foreignKey' => 'bake_article_id', 'joinTable' => 'bake_articles_bake_tags', 'associationForeignKey' => 'bake_tag_id', ), ) ); $result = $this->Task->bake('BakeArticle', compact('associations')); $this->assertContains(' * @property BakeUser $BakeUser', $result); $this->assertContains(' * @property OtherModel $OtherModel', $result); $this->assertContains(' * @property BakeComment $BakeComment', $result); $this->assertContains(' * @property BakeTag $BakeTag', $result); $this->assertRegExp('/\$hasAndBelongsToMany \= array\(/', $result); $this->assertRegExp('/\$hasMany \= array\(/', $result); $this->assertRegExp('/\$belongsTo \= array\(/', $result); $this->assertRegExp('/\$hasOne \= array\(/', $result); $this->assertRegExp('/BakeTag/', $result); $this->assertRegExp('/OtherModel/', $result); $this->assertRegExp('/SomethingElse/', $result); $this->assertRegExp('/BakeComment/', $result); } /** * test bake() with a -plugin param * * @return void */ public function testBakeWithPlugin() { $this->Task->plugin = 'ControllerTest'; //fake plugin path CakePlugin::load('ControllerTest', array('path' => APP . 'Plugin' . DS . 'ControllerTest' . DS)); $path = APP . 'Plugin' . DS . 'ControllerTest' . DS . 'Model' . DS . 'BakeArticle.php'; $this->Task->expects($this->once())->method('createFile') ->with($path, $this->stringContains('BakeArticle extends ControllerTestAppModel')); $result = $this->Task->bake('BakeArticle', array(), array()); $this->assertContains("App::uses('ControllerTestAppModel', 'ControllerTest.Model');", $result); $this->assertEquals(count(ClassRegistry::keys()), 0); $this->assertEquals(count(ClassRegistry::mapKeys()), 0); } /** * test bake() for models with behaviors * * @return void */ public function testBakeWithBehaviors() { $result = $this->Task->bake('NumberTree', array('actsAs' => array('Tree', 'PluginName.Sluggable'))); $expected = <<assertTextContains($expected, $result); } /** * test that execute passes runs bake depending with named model. * * @return void */ public function testExecuteWithNamedModel() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('BakeArticle'); $filename = '/my/path/BakeArticle.php'; $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(1)); $this->Task->expects($this->once())->method('createFile') ->with($filename, $this->stringContains('class BakeArticle extends AppModel')); $this->Task->execute(); $this->assertEquals(count(ClassRegistry::keys()), 0); $this->assertEquals(count(ClassRegistry::mapKeys()), 0); } /** * data provider for testExecuteWithNamedModelVariations * * @return void */ public static function nameVariations() { return array( array('BakeArticles'), array('BakeArticle'), array('bake_article'), array('bake_articles') ); } /** * test that execute passes with different inflections of the same name. * * @dataProvider nameVariations * @return void */ public function testExecuteWithNamedModelVariations($name) { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(1)); $this->Task->args = array($name); $filename = '/my/path/BakeArticle.php'; $this->Task->expects($this->at(0))->method('createFile') ->with($filename, $this->stringContains('class BakeArticle extends AppModel')); $this->Task->execute(); } /** * test that execute with a model name picks up hasMany associations. * * @return void */ public function testExecuteWithNamedModelHasManyCreated() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('BakeArticle'); $filename = '/my/path/BakeArticle.php'; $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(1)); $this->Task->expects($this->at(0))->method('createFile') ->with($filename, $this->stringContains("'BakeComment' => array(")); $this->Task->execute(); } /** * test that execute runs all() when args[0] = all * * @return void */ public function testExecuteIntoAll() { $count = count($this->Task->listAll('test')); if ($count != count($this->fixtures)) { $this->markTestSkipped('Additional tables detected.'); } $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('all'); $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true)); $this->Task->Fixture->expects($this->exactly(6))->method('bake'); $this->Task->Test->expects($this->exactly(6))->method('bake'); $filename = '/my/path/BakeArticle.php'; $this->Task->expects($this->at(1))->method('createFile') ->with($filename, $this->stringContains('class BakeArticle')); $filename = '/my/path/BakeArticlesBakeTag.php'; $this->Task->expects($this->at(2))->method('createFile') ->with($filename, $this->stringContains('class BakeArticlesBakeTag')); $filename = '/my/path/BakeComment.php'; $this->Task->expects($this->at(3))->method('createFile') ->with($filename, $this->stringContains('class BakeComment')); $filename = '/my/path/BakeComment.php'; $this->Task->expects($this->at(3))->method('createFile') ->with($filename, $this->stringContains('public $primaryKey = \'otherid\';')); $filename = '/my/path/BakeTag.php'; $this->Task->expects($this->at(4))->method('createFile') ->with($filename, $this->stringContains('class BakeTag')); $filename = '/my/path/BakeTag.php'; $this->Task->expects($this->at(4))->method('createFile') ->with($filename, $this->logicalNot($this->stringContains('public $primaryKey'))); $filename = '/my/path/CategoryThread.php'; $this->Task->expects($this->at(5))->method('createFile') ->with($filename, $this->stringContains('class CategoryThread')); $filename = '/my/path/NumberTree.php'; $this->Task->expects($this->at(6))->method('createFile') ->with($filename, $this->stringContains('class NumberTree')); $this->Task->execute(); $this->assertEquals(count(ClassRegistry::keys()), 0); $this->assertEquals(count(ClassRegistry::mapKeys()), 0); } /** * test that odd tablenames aren't inflected back from modelname * * @return void */ public function testExecuteIntoAllOddTables() { $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ModelTask', array('in', 'err', '_stop', '_checkUnitTest', 'getAllTables', '_getModelObject', 'bake', 'bakeFixture'), array($out, $out, $in) ); $this->_setupOtherMocks(); $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('all'); $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true)); $this->Task->expects($this->once())->method('getAllTables')->will($this->returnValue(array('bake_odd'))); $object = new Model(array('name' => 'BakeOdd', 'table' => 'bake_odd', 'ds' => 'test')); $this->Task->expects($this->once())->method('_getModelObject')->with('BakeOdd', 'bake_odd')->will($this->returnValue($object)); $this->Task->expects($this->at(3))->method('bake')->with($object, false)->will($this->returnValue(true)); $this->Task->expects($this->once())->method('bakeFixture')->with('BakeOdd', 'bake_odd'); $this->Task->execute(); $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ModelTask', array('in', 'err', '_stop', '_checkUnitTest', 'getAllTables', '_getModelObject', 'doAssociations', 'doValidation', 'doActsAs', 'createFile'), array($out, $out, $in) ); $this->_setupOtherMocks(); $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('all'); $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true)); $this->Task->expects($this->once())->method('getAllTables')->will($this->returnValue(array('bake_odd'))); $object = new Model(array('name' => 'BakeOdd', 'table' => 'bake_odd', 'ds' => 'test')); $this->Task->expects($this->once())->method('_getModelObject')->will($this->returnValue($object)); $this->Task->expects($this->once())->method('doAssociations')->will($this->returnValue(array())); $this->Task->expects($this->once())->method('doValidation')->will($this->returnValue(array())); $this->Task->expects($this->once())->method('doActsAs')->will($this->returnValue(array())); $filename = '/my/path/BakeOdd.php'; $this->Task->expects($this->once())->method('createFile') ->with($filename, $this->stringContains('class BakeOdd')); $filename = '/my/path/BakeOdd.php'; $this->Task->expects($this->once())->method('createFile') ->with($filename, $this->stringContains('public $useTable = \'bake_odd\'')); $this->Task->execute(); } /** * test that odd tablenames aren't inflected back from modelname * * @return void */ public function testExecuteIntoBakeOddTables() { $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ModelTask', array('in', 'err', '_stop', '_checkUnitTest', 'getAllTables', '_getModelObject', 'bake', 'bakeFixture'), array($out, $out, $in) ); $this->_setupOtherMocks(); $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('BakeOdd'); $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true)); $this->Task->expects($this->once())->method('getAllTables')->will($this->returnValue(array('articles', 'bake_odd'))); $object = new Model(array('name' => 'BakeOdd', 'table' => 'bake_odd', 'ds' => 'test')); $this->Task->expects($this->once())->method('_getModelObject')->with('BakeOdd', 'bake_odd')->will($this->returnValue($object)); $this->Task->expects($this->once())->method('bake')->with($object, false)->will($this->returnValue(true)); $this->Task->expects($this->once())->method('bakeFixture')->with('BakeOdd', 'bake_odd'); $this->Task->execute(); $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ModelTask', array('in', 'err', '_stop', '_checkUnitTest', 'getAllTables', '_getModelObject', 'doAssociations', 'doValidation', 'doActsAs', 'createFile'), array($out, $out, $in) ); $this->_setupOtherMocks(); $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('BakeOdd'); $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true)); $this->Task->expects($this->once())->method('getAllTables')->will($this->returnValue(array('articles', 'bake_odd'))); $object = new Model(array('name' => 'BakeOdd', 'table' => 'bake_odd', 'ds' => 'test')); $this->Task->expects($this->once())->method('_getModelObject')->will($this->returnValue($object)); $this->Task->expects($this->once())->method('doAssociations')->will($this->returnValue(array())); $this->Task->expects($this->once())->method('doValidation')->will($this->returnValue(array())); $this->Task->expects($this->once())->method('doActsAs')->will($this->returnValue(array())); $filename = '/my/path/BakeOdd.php'; $this->Task->expects($this->once())->method('createFile') ->with($filename, $this->stringContains('class BakeOdd')); $filename = '/my/path/BakeOdd.php'; $this->Task->expects($this->once())->method('createFile') ->with($filename, $this->stringContains('public $useTable = \'bake_odd\'')); $this->Task->execute(); } /** * test that skipTables changes how all() works. * * @return void */ public function testSkipTablesAndAll() { $count = count($this->Task->listAll('test')); if ($count != count($this->fixtures)) { $this->markTestSkipped('Additional tables detected.'); } $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->args = array('all'); $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true)); $this->Task->skipTables = array('bake_tags', 'number_trees'); $this->Task->Fixture->expects($this->exactly(4))->method('bake'); $this->Task->Test->expects($this->exactly(4))->method('bake'); $filename = '/my/path/BakeArticle.php'; $this->Task->expects($this->at(1))->method('createFile') ->with($filename, $this->stringContains('class BakeArticle')); $filename = '/my/path/BakeArticlesBakeTag.php'; $this->Task->expects($this->at(2))->method('createFile') ->with($filename, $this->stringContains('class BakeArticlesBakeTag')); $filename = '/my/path/BakeComment.php'; $this->Task->expects($this->at(3))->method('createFile') ->with($filename, $this->stringContains('class BakeComment')); $filename = '/my/path/CategoryThread.php'; $this->Task->expects($this->at(4))->method('createFile') ->with($filename, $this->stringContains('class CategoryThread')); $this->Task->execute(); } /** * test the interactive side of bake. * * @return void */ public function testExecuteIntoInteractive() { $tables = $this->Task->listAll('test'); $article = array_search('bake_articles', $tables) + 1; $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->interactive = true; $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls( $article, // article 'n', // no validation 'y', // associations 'y', // comment relation 'y', // user relation 'y', // tag relation 'n', // additional assocs 'y' // looks good? )); $this->Task->expects($this->once())->method('_checkUnitTest')->will($this->returnValue(true)); $this->Task->Test->expects($this->once())->method('bake'); $this->Task->Fixture->expects($this->once())->method('bake'); $filename = '/my/path/BakeArticle.php'; $this->Task->expects($this->once())->method('createFile') ->with($filename, $this->stringContains('class BakeArticle')); $this->Task->execute(); $this->assertEquals(count(ClassRegistry::keys()), 0); $this->assertEquals(count(ClassRegistry::mapKeys()), 0); } /** * test using bake interactively with a table that does not exist. * * @return void */ public function testExecuteWithNonExistantTableName() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls( 'Foobar', // Or type in the name of the model 'y', // Do you want to use this table 'n' // Doesn't exist, continue anyway? )); $this->Task->execute(); } /** * test using bake interactively with a table that does not exist. * * @return void */ public function testForcedExecuteWithNonExistantTableName() { $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls( 'Foobar', // Or type in the name of the model 'y', // Do you want to use this table 'y', // Doesn't exist, continue anyway? 'id', // Primary key 'y' // Looks good? )); $this->Task->execute(); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/Task/PluginTaskTest.php000066400000000000000000000146261265552240500256720ustar00rootroot00000000000000out = $this->getMock('ConsoleOutput', array(), array(), '', false); $this->in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('PluginTask', array('in', 'err', 'createFile', '_stop', 'clear'), array($this->out, $this->out, $this->in) ); $this->Task->path = TMP . 'tests' . DS; $this->Task->bootstrap = TMP . 'tests' . DS . 'bootstrap.php'; touch($this->Task->bootstrap); $this->_paths = $paths = App::path('plugins'); foreach ($paths as $i => $p) { if (!is_dir($p)) { array_splice($paths, $i, 1); } } $this->_testPath = array_push($paths, TMP . 'tests' . DS) - 1; App::build(array('plugins' => $paths)); } /** * tearDown() * * @return void */ public function tearDown() { if (file_exists($this->Task->bootstrap)) { unlink($this->Task->bootstrap); } parent::tearDown(); } /** * test bake() * * @return void */ public function testBakeFoldersAndFiles() { $this->Task->expects($this->at(0)) ->method('in') ->will($this->returnValue($this->_testPath)); $this->Task->expects($this->at(1)) ->method('in') ->will($this->returnValue('y')); $path = $this->Task->path . 'BakeTestPlugin'; $file = $path . DS . 'Controller' . DS . 'BakeTestPluginAppController.php'; $this->Task->expects($this->at(2)) ->method('createFile') ->with($file, new PHPUnit_Framework_Constraint_IsAnything()); $file = $path . DS . 'Model' . DS . 'BakeTestPluginAppModel.php'; $this->Task->expects($this->at(3)) ->method('createFile') ->with($file, new PHPUnit_Framework_Constraint_IsAnything()); $this->Task->bake('BakeTestPlugin'); $path = $this->Task->path . 'BakeTestPlugin'; $this->assertTrue(is_dir($path), 'No plugin dir %s'); $directories = array( 'Config' . DS . 'Schema', 'Console' . DS . 'Command' . DS . 'Task', 'Console' . DS . 'Templates', 'Controller' . DS . 'Component', 'Lib', 'Locale' . DS . 'eng' . DS . 'LC_MESSAGES', 'Model' . DS . 'Behavior', 'Model' . DS . 'Datasource', 'Test' . DS . 'Case' . DS . 'Controller' . DS . 'Component', 'Test' . DS . 'Case' . DS . 'Lib', 'Test' . DS . 'Case' . DS . 'Model' . DS . 'Behavior', 'Test' . DS . 'Case' . DS . 'Model' . DS . 'Datasource', 'Test' . DS . 'Case' . DS . 'View' . DS . 'Helper', 'Test' . DS . 'Fixture', 'View' . DS . 'Elements', 'View' . DS . 'Helper', 'View' . DS . 'Layouts', 'webroot' . DS . 'css', 'webroot' . DS . 'js', 'webroot' . DS . 'img', ); foreach ($directories as $dir) { $this->assertTrue(is_dir($path . DS . $dir), 'Missing directory for ' . $dir); } $Folder = new Folder($this->Task->path . 'BakeTestPlugin'); $Folder->delete(); } /** * test execute with no args, flowing into interactive, * * @return void */ public function testExecuteWithNoArgs() { $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('TestPlugin')); $this->Task->expects($this->at(1))->method('in')->will($this->returnValue($this->_testPath)); $this->Task->expects($this->at(2))->method('in')->will($this->returnValue('y')); $path = $this->Task->path . 'TestPlugin'; $file = $path . DS . 'Controller' . DS . 'TestPluginAppController.php'; $this->Task->expects($this->at(3))->method('createFile') ->with($file, new PHPUnit_Framework_Constraint_IsAnything()); $file = $path . DS . 'Model' . DS . 'TestPluginAppModel.php'; $this->Task->expects($this->at(4))->method('createFile') ->with($file, new PHPUnit_Framework_Constraint_IsAnything()); $this->Task->args = array(); $this->Task->execute(); $Folder = new Folder($path); $Folder->delete(); } /** * Test Execute * * @return void */ public function testExecuteWithOneArg() { $this->Task->expects($this->at(0))->method('in') ->will($this->returnValue($this->_testPath)); $this->Task->expects($this->at(1))->method('in') ->will($this->returnValue('y')); $path = $this->Task->path . 'BakeTestPlugin'; $file = $path . DS . 'Controller' . DS . 'BakeTestPluginAppController.php'; $this->Task->expects($this->at(2))->method('createFile') ->with($file, new PHPUnit_Framework_Constraint_IsAnything()); $path = $this->Task->path . 'BakeTestPlugin'; $file = $path . DS . 'Model' . DS . 'BakeTestPluginAppModel.php'; $this->Task->expects($this->at(3))->method('createFile') ->with($file, new PHPUnit_Framework_Constraint_IsAnything()); $this->Task->args = array('BakeTestPlugin'); $this->Task->execute(); $Folder = new Folder($this->Task->path . 'BakeTestPlugin'); $Folder->delete(); } /** * Test that findPath ignores paths that don't exist. * * @return void */ public function testFindPathNonExistant() { $paths = App::path('plugins'); $last = count($paths); array_unshift($paths, '/fake/path'); $paths[] = '/fake/path2'; $this->Task = $this->getMock('PluginTask', array('in', 'out', 'err', 'createFile', '_stop'), array($this->out, $this->out, $this->in) ); $this->Task->path = TMP . 'tests' . DS; // Make sure the added path is filtered out. $this->Task->expects($this->exactly($last)) ->method('out'); $this->Task->expects($this->once()) ->method('in') ->will($this->returnValue($last)); $this->Task->findPath($paths); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/Task/ProjectTaskTest.php000066400000000000000000000275201265552240500260370ustar00rootroot00000000000000getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ProjectTask', array('in', 'err', 'createFile', '_stop'), array($out, $out, $in) ); $this->Task->path = TMP . 'tests' . DS; } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); $Folder = new Folder($this->Task->path . 'bake_test_app'); $Folder->delete(); unset($this->Task); } /** * creates a test project that is used for testing project task. * * @return void */ protected function _setupTestProject() { $skel = CAKE . 'Console' . DS . 'Templates' . DS . 'skel'; $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y')); $this->Task->bake($this->Task->path . 'bake_test_app', $skel); } /** * test bake() method and directory creation. * * @return void */ public function testBake() { $this->_setupTestProject(); $path = $this->Task->path . 'bake_test_app'; $this->assertTrue(is_dir($path), 'No project dir %s'); $dirs = array( 'Config', 'Config' . DS . 'Schema', 'Console', 'Console' . DS . 'Command', 'Console' . DS . 'Templates', 'Console' . DS . 'Command' . DS . 'Task', 'Controller', 'Controller' . DS . 'Component', 'Locale', 'Model', 'Model' . DS . 'Behavior', 'Model' . DS . 'Datasource', 'Plugin', 'Test', 'Test' . DS . 'Case', 'Test' . DS . 'Case' . DS . 'Controller', 'Test' . DS . 'Case' . DS . 'Controller' . DS . 'Component', 'Test' . DS . 'Case' . DS . 'Model', 'Test' . DS . 'Case' . DS . 'Model' . DS . 'Behavior', 'Test' . DS . 'Fixture', 'Vendor', 'View', 'View' . DS . 'Helper', 'tmp', 'tmp' . DS . 'cache', 'tmp' . DS . 'cache' . DS . 'models', 'tmp' . DS . 'cache' . DS . 'persistent', 'tmp' . DS . 'cache' . DS . 'views', 'tmp' . DS . 'logs', 'tmp' . DS . 'sessions', 'tmp' . DS . 'tests', 'webroot', 'webroot' . DS . 'css', 'webroot' . DS . 'files', 'webroot' . DS . 'img', 'webroot' . DS . 'js', ); foreach ($dirs as $dir) { $this->assertTrue(is_dir($path . DS . $dir), 'Missing ' . $dir); } } /** * test bake with an absolute path. * * @return void */ public function testExecuteWithAbsolutePath() { $path = $this->Task->args[0] = TMP . 'tests' . DS . 'bake_test_app'; $this->Task->params['skel'] = CAKE . 'Console' . DS . 'Templates' . DS . 'skel'; $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y')); $this->Task->execute(); $this->assertTrue(is_dir($this->Task->args[0]), 'No project dir'); $File = new File($path . DS . 'webroot' . DS . 'index.php'); $contents = $File->read(); $this->assertRegExp('/define\(\'CAKE_CORE_INCLUDE_PATH\', .*?DS/', $contents); $File = new File($path . DS . 'webroot' . DS . 'test.php'); $contents = $File->read(); $this->assertRegExp('/define\(\'CAKE_CORE_INCLUDE_PATH\', .*?DS/', $contents); } /** * test bake with CakePHP on the include path. The constants should remain commented out. * * @return void */ public function testExecuteWithCakeOnIncludePath() { if (!function_exists('ini_set')) { $this->markTestAsSkipped('Not access to ini_set, cannot proceed.'); } $restore = ini_get('include_path'); ini_set('include_path', CAKE_CORE_INCLUDE_PATH . PATH_SEPARATOR . $restore); $path = $this->Task->args[0] = TMP . 'tests' . DS . 'bake_test_app'; $this->Task->params['skel'] = CAKE . 'Console' . DS . 'Templates' . DS . 'skel'; $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y')); $this->Task->execute(); $this->assertTrue(is_dir($this->Task->args[0]), 'No project dir'); $contents = file_get_contents($path . DS . 'webroot' . DS . 'index.php'); $this->assertRegExp('#//define\(\'CAKE_CORE_INCLUDE_PATH#', $contents); $contents = file_get_contents($path . DS . 'webroot' . DS . 'test.php'); $this->assertRegExp('#//define\(\'CAKE_CORE_INCLUDE_PATH#', $contents); ini_set('include_path', $restore); } /** * test bake() method with -empty flag, directory creation and empty files. * * @return void */ public function testBakeEmptyFlag() { $this->Task->params['empty'] = true; $this->_setupTestProject(); $path = $this->Task->path . 'bake_test_app'; $empty = array( 'Console' . DS . 'Command' . DS . 'Task' => 'empty', 'Controller' . DS . 'Component' => 'empty', 'Lib' => 'empty', 'Model' . DS . 'Behavior' => 'empty', 'Model' . DS . 'Datasource' => 'empty', 'Plugin' => 'empty', 'Test' . DS . 'Case' . DS . 'Model' . DS . 'Behavior' => 'empty', 'Test' . DS . 'Case' . DS . 'Controller' . DS . 'Component' => 'empty', 'Test' . DS . 'Case' . DS . 'View' . DS . 'Helper' => 'empty', 'Test' . DS . 'Fixture' => 'empty', 'Vendor' => 'empty', 'View' . DS . 'Scaffolds' => 'empty', 'tmp' . DS . 'cache' . DS . 'models' => 'empty', 'tmp' . DS . 'cache' . DS . 'persistent' => 'empty', 'tmp' . DS . 'cache' . DS . 'views' => 'empty', 'tmp' . DS . 'logs' => 'empty', 'tmp' . DS . 'sessions' => 'empty', 'tmp' . DS . 'tests' => 'empty', 'webroot' . DS . 'js' => 'empty', 'webroot' . DS . 'files' => 'empty' ); foreach ($empty as $dir => $file) { $this->assertTrue(is_file($path . DS . $dir . DS . $file), sprintf('Missing %s file in %s', $file, $dir)); } } /** * test generation of Security.salt * * @return void */ public function testSecuritySaltGeneration() { $this->_setupTestProject(); $path = $this->Task->path . 'bake_test_app' . DS; $result = $this->Task->securitySalt($path); $this->assertTrue($result); $File = new File($path . 'Config' . DS . 'core.php'); $contents = $File->read(); $this->assertNotRegExp('/DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi/', $contents, 'Default Salt left behind. %s'); } /** * test generation of Security.cipherSeed * * @return void */ public function testSecurityCipherSeedGeneration() { $this->_setupTestProject(); $path = $this->Task->path . 'bake_test_app' . DS; $result = $this->Task->securityCipherSeed($path); $this->assertTrue($result); $File = new File($path . 'Config' . DS . 'core.php'); $contents = $File->read(); $this->assertNotRegExp('/76859309657453542496749683645/', $contents, 'Default CipherSeed left behind. %s'); } /** * test generation of cache prefix * * @return void */ public function testCachePrefixGeneration() { $this->_setupTestProject(); $path = $this->Task->path . 'bake_test_app' . DS; $result = $this->Task->cachePrefix($path); $this->assertTrue($result); $File = new File($path . 'Config' . DS . 'core.php'); $contents = $File->read(); $this->assertRegExp('/\$prefix = \'.+\';/', $contents, '$prefix is not defined'); $this->assertNotRegExp('/\$prefix = \'myapp_\';/', $contents, 'Default cache prefix left behind. %s'); } /** * Test that index.php is generated correctly. * * @return void */ public function testIndexPhpGeneration() { $this->_setupTestProject(); $path = $this->Task->path . 'bake_test_app' . DS; $this->Task->corePath($path); $File = new File($path . 'webroot' . DS . 'index.php'); $contents = $File->read(); $this->assertNotRegExp('/define\(\'CAKE_CORE_INCLUDE_PATH\', ROOT/', $contents); $File = new File($path . 'webroot' . DS . 'test.php'); $contents = $File->read(); $this->assertNotRegExp('/define\(\'CAKE_CORE_INCLUDE_PATH\', ROOT/', $contents); } /** * test getPrefix method, and that it returns Routing.prefix or writes to config file. * * @return void */ public function testGetPrefix() { Configure::write('Routing.prefixes', array('admin')); $result = $this->Task->getPrefix(); $this->assertEquals('admin_', $result); Configure::write('Routing.prefixes', null); $this->_setupTestProject(); $this->Task->configPath = $this->Task->path . 'bake_test_app' . DS . 'Config' . DS; $this->Task->expects($this->once())->method('in')->will($this->returnValue('super_duper_admin')); $result = $this->Task->getPrefix(); $this->assertEquals('super_duper_admin_', $result); $File = new File($this->Task->configPath . 'core.php'); $File->delete(); } /** * test cakeAdmin() writing core.php * * @return void */ public function testCakeAdmin() { $File = new File(APP . 'Config' . DS . 'core.php'); $contents = $File->read(); $File = new File(TMP . 'tests' . DS . 'core.php'); $File->write($contents); Configure::write('Routing.prefixes', null); $this->Task->configPath = TMP . 'tests' . DS; $result = $this->Task->cakeAdmin('my_prefix'); $this->assertTrue($result); $this->assertEquals(Configure::read('Routing.prefixes'), array('my_prefix')); $File->delete(); } /** * test getting the prefix with more than one prefix setup * * @return void */ public function testGetPrefixWithMultiplePrefixes() { Configure::write('Routing.prefixes', array('admin', 'ninja', 'shinobi')); $this->_setupTestProject(); $this->Task->configPath = $this->Task->path . 'bake_test_app' . DS . 'Config' . DS; $this->Task->expects($this->once())->method('in')->will($this->returnValue(2)); $result = $this->Task->getPrefix(); $this->assertEquals('ninja_', $result); } /** * Test execute method with one param to destination folder. * * @return void */ public function testExecute() { $this->Task->params['skel'] = CAKE . 'Console' . DS . 'Templates' . DS . 'skel'; $this->Task->params['working'] = TMP . 'tests' . DS; $path = $this->Task->path . 'bake_test_app'; $this->Task->expects($this->at(0))->method('in')->will($this->returnValue($path)); $this->Task->expects($this->at(1))->method('in')->will($this->returnValue('y')); $this->Task->execute(); $this->assertTrue(is_dir($path), 'No project dir'); $this->assertTrue(is_dir($path . DS . 'Controller'), 'No controllers dir '); $this->assertTrue(is_dir($path . DS . 'Controller' . DS . 'Component'), 'No components dir '); $this->assertTrue(is_dir($path . DS . 'Model'), 'No models dir'); $this->assertTrue(is_dir($path . DS . 'View'), 'No views dir'); $this->assertTrue(is_dir($path . DS . 'View' . DS . 'Helper'), 'No helpers dir'); $this->assertTrue(is_dir($path . DS . 'Test'), 'No tests dir'); $this->assertTrue(is_dir($path . DS . 'Test' . DS . 'Case'), 'No cases dir'); $this->assertTrue(is_dir($path . DS . 'Test' . DS . 'Fixture'), 'No fixtures dir'); } /** * test console path * * @return void */ public function testConsolePath() { $this->_setupTestProject(); $path = $this->Task->path . 'bake_test_app' . DS; $result = $this->Task->consolePath($path); $this->assertTrue($result); $File = new File($path . 'Console' . DS . 'cake.php'); $contents = $File->read(); $this->assertNotRegExp('/__CAKE_PATH__/', $contents, 'Console path placeholder left behind.'); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/Task/TemplateTaskTest.php000066400000000000000000000114021265552240500261740ustar00rootroot00000000000000getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('TemplateTask', array('in', 'err', 'createFile', '_stop', 'clear'), array($out, $out, $in) ); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Task); } /** * test that set sets variables * * @return void */ public function testSet() { $this->Task->set('one', 'two'); $this->assertTrue(isset($this->Task->templateVars['one'])); $this->assertEquals('two', $this->Task->templateVars['one']); $this->Task->set(array('one' => 'three', 'four' => 'five')); $this->assertTrue(isset($this->Task->templateVars['one'])); $this->assertEquals('three', $this->Task->templateVars['one']); $this->assertTrue(isset($this->Task->templateVars['four'])); $this->assertEquals('five', $this->Task->templateVars['four']); $this->Task->templateVars = array(); $this->Task->set(array(3 => 'three', 4 => 'four')); $this->Task->set(array(1 => 'one', 2 => 'two')); $expected = array(3 => 'three', 4 => 'four', 1 => 'one', 2 => 'two'); $this->assertEquals($expected, $this->Task->templateVars); } /** * test finding themes installed in * * @return void */ public function testFindingInstalledThemesForBake() { $consoleLibs = CAKE . 'Console' . DS; $this->Task->initialize(); $this->assertEquals($this->Task->templatePaths['default'], $consoleLibs . 'Templates' . DS . 'default' . DS); } /** * test getting the correct theme name. Ensure that with only one theme, or a theme param * that the user is not bugged. If there are more, find and return the correct theme name * * @return void */ public function testGetThemePath() { $defaultTheme = CAKE . 'Console' . DS . 'Templates' . DS . 'default' . DS; $this->Task->templatePaths = array('default' => $defaultTheme); $this->Task->expects($this->exactly(1))->method('in')->will($this->returnValue('1')); $result = $this->Task->getThemePath(); $this->assertEquals($defaultTheme, $result); $this->Task->templatePaths = array('other' => '/some/path', 'default' => $defaultTheme); $this->Task->params['theme'] = 'other'; $result = $this->Task->getThemePath(); $this->assertEquals('/some/path', $result); $this->Task->params = array(); $result = $this->Task->getThemePath(); $this->assertEquals('/some/path', $result); $this->assertEquals('other', $this->Task->params['theme']); } /** * test generate * * @return void */ public function testGenerate() { App::build(array( 'Console' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Console' . DS ) )); $this->Task->initialize(); $this->Task->expects($this->any())->method('in')->will($this->returnValue(1)); $result = $this->Task->generate('classes', 'test_object', array('test' => 'foo')); $expected = "I got rendered\nfoo"; $this->assertTextEquals($expected, $result); } /** * test generate with a missing template in the chosen theme. * ensure fallback to default works. * * @return void */ public function testGenerateWithTemplateFallbacks() { App::build(array( 'Console' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Console' . DS, CAKE_CORE_INCLUDE_PATH . DS . 'console' . DS ) )); $this->Task->initialize(); $this->Task->params['theme'] = 'test'; $this->Task->set(array( 'model' => 'Article', 'table' => 'articles', 'import' => false, 'records' => false, 'schema' => '' )); $result = $this->Task->generate('classes', 'fixture'); $this->assertRegExp('/ArticleFixture extends CakeTestFixture/', $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/Task/TestTaskTest.php000066400000000000000000000537251265552240500253560ustar00rootroot00000000000000 array( 'className' => 'TestTask.TestTaskComment', 'foreignKey' => 'article_id', ) ); /** * Has and Belongs To Many Associations * * @var array */ public $hasAndBelongsToMany = array( 'Tag' => array( 'className' => 'TestTaskTag', 'joinTable' => 'articles_tags', 'foreignKey' => 'article_id', 'associationForeignKey' => 'tag_id' ) ); /** * Example public method * * @return void */ public function doSomething() { } /** * Example Secondary public method * * @return void */ public function doSomethingElse() { } /** * Example protected method * * @return void */ protected function _innerMethod() { } } /** * Tag Testing Model * * @package Cake.Test.Case.Console.Command.Task */ class TestTaskTag extends Model { /** * Table name * * @var string */ public $useTable = 'tags'; /** * Has and Belongs To Many Associations * * @var array */ public $hasAndBelongsToMany = array( 'Article' => array( 'className' => 'TestTaskArticle', 'joinTable' => 'articles_tags', 'foreignKey' => 'tag_id', 'associationForeignKey' => 'article_id' ) ); } /** * Simulated plugin * * @package Cake.Test.Case.Console.Command.Task */ class TestTaskAppModel extends Model { } /** * Testing AppMode (TaskComment) * * @package Cake.Test.Case.Console.Command.Task */ class TestTaskComment extends TestTaskAppModel { /** * Table name * * @var string */ public $useTable = 'comments'; /** * Belongs To Associations * * @var array */ public $belongsTo = array( 'Article' => array( 'className' => 'TestTaskArticle', 'foreignKey' => 'article_id', ) ); } /** * Test Task Comments Controller * * @package Cake.Test.Case.Console.Command.Task */ class TestTaskCommentsController extends Controller { /** * Models to use * * @var array */ public $uses = array('TestTaskComment', 'TestTaskTag'); } /** * TestTaskTest class * * @package Cake.Test.Case.Console.Command.Task */ class TestTaskTest extends CakeTestCase { /** * Fixtures * * @var string */ public $fixtures = array('core.article', 'core.comment', 'core.articles_tag', 'core.tag'); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('TestTask', array('in', 'err', 'createFile', '_stop', 'isLoadableClass'), array($out, $out, $in) ); $this->Task->name = 'Test'; $this->Task->Template = new TemplateTask($out, $out, $in); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Task); CakePlugin::unload(); } /** * Test that file path generation doesn't continuously append paths. * * @return void */ public function testFilePathGenerationModelRepeated() { $this->Task->expects($this->never())->method('err'); $this->Task->expects($this->never())->method('_stop'); $file = TESTS . 'Case' . DS . 'Model' . DS . 'MyClassTest.php'; $this->Task->expects($this->at(1))->method('createFile') ->with($file, $this->anything()); $this->Task->expects($this->at(3))->method('createFile') ->with($file, $this->anything()); $file = TESTS . 'Case' . DS . 'Controller' . DS . 'CommentsControllerTest.php'; $this->Task->expects($this->at(5))->method('createFile') ->with($file, $this->anything()); $this->Task->bake('Model', 'MyClass'); $this->Task->bake('Model', 'MyClass'); $this->Task->bake('Controller', 'Comments'); } /** * Test that method introspection pulls all relevant non parent class * methods into the test case. * * @return void */ public function testMethodIntrospection() { $result = $this->Task->getTestableMethods('TestTaskArticle'); $expected = array('dosomething', 'dosomethingelse'); $this->assertEquals($expected, array_map('strtolower', $result)); } /** * test that the generation of fixtures works correctly. * * @return void */ public function testFixtureArrayGenerationFromModel() { $subject = ClassRegistry::init('TestTaskArticle'); $result = $this->Task->generateFixtureList($subject); $expected = array('plugin.test_task.test_task_comment', 'app.articles_tags', 'app.test_task_article', 'app.test_task_tag'); $this->assertEquals(sort($expected), sort($result)); } /** * test that the generation of fixtures works correctly. * * @return void */ public function testFixtureArrayGenerationFromController() { $subject = new TestTaskCommentsController(); $result = $this->Task->generateFixtureList($subject); $expected = array('plugin.test_task.test_task_comment', 'app.articles_tags', 'app.test_task_article', 'app.test_task_tag'); $this->assertEquals(sort($expected), sort($result)); } /** * test user interaction to get object type * * @return void */ public function testGetObjectType() { $this->Task->expects($this->once())->method('_stop'); $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('q')); $this->Task->expects($this->at(2))->method('in')->will($this->returnValue(2)); $this->Task->getObjectType(); $result = $this->Task->getObjectType(); $this->assertEquals($this->Task->classTypes['Controller'], $result); } /** * creating test subjects should clear the registry so the registry is always fresh * * @return void */ public function testRegistryClearWhenBuildingTestObjects() { ClassRegistry::flush(); $model = ClassRegistry::init('TestTaskComment'); $model->bindModel(array( 'belongsTo' => array( 'Random' => array( 'className' => 'TestTaskArticle', 'foreignKey' => 'article_id', ) ) )); $keys = ClassRegistry::keys(); $this->assertTrue(in_array('test_task_comment', $keys)); $this->Task->buildTestSubject('Model', 'TestTaskComment'); $keys = ClassRegistry::keys(); $this->assertFalse(in_array('random', $keys)); } /** * test that getClassName returns the user choice as a class name. * * @return void */ public function testGetClassName() { $objects = App::objects('model'); $this->skipIf(empty($objects), 'No models in app.'); $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('MyCustomClass')); $this->Task->expects($this->at(1))->method('in')->will($this->returnValue(1)); $result = $this->Task->getClassName('Model'); $this->assertEquals('MyCustomClass', $result); $result = $this->Task->getClassName('Model'); $options = App::objects('model'); $this->assertEquals($options[0], $result); } /** * Test the user interaction for defining additional fixtures. * * @return void */ public function testGetUserFixtures() { $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('y')); $this->Task->expects($this->at(1))->method('in') ->will($this->returnValue('app.pizza, app.topping, app.side_dish')); $result = $this->Task->getUserFixtures(); $expected = array('app.pizza', 'app.topping', 'app.side_dish'); $this->assertEquals($expected, $result); } /** * test that resolving class names works * * @return void */ public function testGetRealClassname() { $result = $this->Task->getRealClassname('Model', 'Post'); $this->assertEquals('Post', $result); $result = $this->Task->getRealClassname('Controller', 'Posts'); $this->assertEquals('PostsController', $result); $result = $this->Task->getRealClassname('Controller', 'PostsController'); $this->assertEquals('PostsController', $result); $result = $this->Task->getRealClassname('Controller', 'AlertTypes'); $this->assertEquals('AlertTypesController', $result); $result = $this->Task->getRealClassname('Helper', 'Form'); $this->assertEquals('FormHelper', $result); $result = $this->Task->getRealClassname('Helper', 'FormHelper'); $this->assertEquals('FormHelper', $result); $result = $this->Task->getRealClassname('Behavior', 'Containable'); $this->assertEquals('ContainableBehavior', $result); $result = $this->Task->getRealClassname('Behavior', 'ContainableBehavior'); $this->assertEquals('ContainableBehavior', $result); $result = $this->Task->getRealClassname('Component', 'Auth'); $this->assertEquals('AuthComponent', $result); } /** * test baking files. The conditionally run tests are known to fail in PHP4 * as PHP4 class names are all lower case, breaking the plugin path inflection. * * @return void */ public function testBakeModelTest() { $this->Task->expects($this->once())->method('createFile')->will($this->returnValue(true)); $this->Task->expects($this->once())->method('isLoadableClass')->will($this->returnValue(true)); $result = $this->Task->bake('Model', 'TestTaskArticle'); $this->assertContains("App::uses('TestTaskArticle', 'Model')", $result); $this->assertContains('class TestTaskArticleTest extends CakeTestCase', $result); $this->assertContains('function setUp()', $result); $this->assertContains("\$this->TestTaskArticle = ClassRegistry::init('TestTaskArticle')", $result); $this->assertContains('function tearDown()', $result); $this->assertContains('unset($this->TestTaskArticle)', $result); $this->assertContains('function testDoSomething()', $result); $this->assertContains('function testDoSomethingElse()', $result); $this->assertContains('$this->markTestIncomplete(\'testDoSomething not implemented.\')', $result); $this->assertContains('$this->markTestIncomplete(\'testDoSomethingElse not implemented.\')', $result); $this->assertContains("'app.test_task_article'", $result); $this->assertContains("'app.test_task_comment'", $result); $this->assertContains("'app.test_task_tag'", $result); $this->assertContains("'app.articles_tag'", $result); } /** * test baking controller test files * * @return void */ public function testBakeControllerTest() { $this->Task->expects($this->once())->method('createFile')->will($this->returnValue(true)); $this->Task->expects($this->once())->method('isLoadableClass')->will($this->returnValue(true)); $result = $this->Task->bake('Controller', 'TestTaskComments'); $this->assertContains("App::uses('TestTaskCommentsController', 'Controller')", $result); $this->assertContains('class TestTaskCommentsControllerTest extends ControllerTestCase', $result); $this->assertNotContains('function setUp()', $result); $this->assertNotContains("\$this->TestTaskComments = new TestTaskCommentsController()", $result); $this->assertNotContains("\$this->TestTaskComments->constructClasses()", $result); $this->assertNotContains('function tearDown()', $result); $this->assertNotContains('unset($this->TestTaskComments)', $result); $this->assertContains("'app.test_task_article'", $result); $this->assertContains("'app.test_task_comment'", $result); $this->assertContains("'app.test_task_tag'", $result); $this->assertContains("'app.articles_tag'", $result); } /** * test baking component test files, * * @return void */ public function testBakeComponentTest() { $this->Task->expects($this->once())->method('createFile')->will($this->returnValue(true)); $result = $this->Task->bake('Component', 'Example'); $this->assertContains("App::uses('Component', 'Controller')", $result); $this->assertContains("App::uses('ComponentCollection', 'Controller')", $result); $this->assertContains("App::uses('ExampleComponent', 'Controller/Component')", $result); $this->assertContains('class ExampleComponentTest extends CakeTestCase', $result); $this->assertContains('function setUp()', $result); $this->assertContains("\$Collection = new ComponentCollection()", $result); $this->assertContains("\$this->Example = new ExampleComponent(\$Collection)", $result); $this->assertContains('function tearDown()', $result); $this->assertContains('unset($this->Example)', $result); } /** * test baking behavior test files, * * @return void */ public function testBakeBehaviorTest() { $this->Task->expects($this->once())->method('createFile')->will($this->returnValue(true)); $result = $this->Task->bake('Behavior', 'Example'); $this->assertContains("App::uses('ExampleBehavior', 'Model/Behavior')", $result); $this->assertContains('class ExampleBehaviorTest extends CakeTestCase', $result); $this->assertContains('function setUp()', $result); $this->assertContains("\$this->Example = new ExampleBehavior()", $result); $this->assertContains('function tearDown()', $result); $this->assertContains('unset($this->Example)', $result); } /** * test baking helper test files, * * @return void */ public function testBakeHelperTest() { $this->Task->expects($this->once())->method('createFile')->will($this->returnValue(true)); $result = $this->Task->bake('Helper', 'Example'); $this->assertContains("App::uses('ExampleHelper', 'View/Helper')", $result); $this->assertContains('class ExampleHelperTest extends CakeTestCase', $result); $this->assertContains('function setUp()', $result); $this->assertContains("\$View = new View()", $result); $this->assertContains("\$this->Example = new ExampleHelper(\$View)", $result); $this->assertContains('function tearDown()', $result); $this->assertContains('unset($this->Example)', $result); } /** * test Constructor generation ensure that constructClasses is called for controllers * * @return void */ public function testGenerateConstructor() { $result = $this->Task->generateConstructor('controller', 'PostsController', null); $expected = array('', '', ''); $this->assertEquals($expected, $result); $result = $this->Task->generateConstructor('model', 'Post', null); $expected = array('', "ClassRegistry::init('Post');\n", ''); $this->assertEquals($expected, $result); $result = $this->Task->generateConstructor('helper', 'FormHelper', null); $expected = array("\$View = new View();\n", "new FormHelper(\$View);\n", ''); $this->assertEquals($expected, $result); } /** * Test generateUses() * * @return void */ public function testGenerateUses() { $result = $this->Task->generateUses('model', 'Model', 'Post'); $expected = array( array('Post', 'Model') ); $this->assertEquals($expected, $result); $result = $this->Task->generateUses('controller', 'Controller', 'PostsController'); $expected = array( array('PostsController', 'Controller') ); $this->assertEquals($expected, $result); $result = $this->Task->generateUses('helper', 'View/Helper', 'FormHelper'); $expected = array( array('View', 'View'), array('Helper', 'View'), array('FormHelper', 'View/Helper'), ); $this->assertEquals($expected, $result); $result = $this->Task->generateUses('component', 'Controller/Component', 'AuthComponent'); $expected = array( array('ComponentCollection', 'Controller'), array('Component', 'Controller'), array('AuthComponent', 'Controller/Component') ); $this->assertEquals($expected, $result); } /** * Test that mock class generation works for the appropriate classes * * @return void */ public function testMockClassGeneration() { $result = $this->Task->hasMockClass('controller'); $this->assertTrue($result); } /** * test bake() with a -plugin param * * @return void */ public function testBakeWithPlugin() { $this->Task->plugin = 'TestTest'; //fake plugin path CakePlugin::load('TestTest', array('path' => APP . 'Plugin' . DS . 'TestTest' . DS)); $path = APP . 'Plugin' . DS . 'TestTest' . DS . 'Test' . DS . 'Case' . DS . 'View' . DS . 'Helper' . DS . 'FormHelperTest.php'; $this->Task->expects($this->once())->method('createFile') ->with($path, $this->anything()); $this->Task->bake('Helper', 'Form'); CakePlugin::unload(); } /** * test interactive with plugins lists from the plugin * * @return void */ public function testInteractiveWithPlugin() { $testApp = CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS; App::build(array( 'Plugin' => array($testApp) ), App::RESET); CakePlugin::load('TestPlugin'); $this->Task->plugin = 'TestPlugin'; $path = $testApp . 'TestPlugin' . DS . 'Test' . DS . 'Case' . DS . 'View' . DS . 'Helper' . DS . 'OtherHelperTest.php'; $this->Task->expects($this->any()) ->method('in') ->will($this->onConsecutiveCalls( 5, //helper 1 //OtherHelper )); $this->Task->expects($this->once()) ->method('createFile') ->with($path, $this->anything()); $this->Task->stdout->expects($this->at(21)) ->method('write') ->with('1. OtherHelperHelper'); $this->Task->execute(); } public static function caseFileNameProvider() { return array( array('Model', 'Post', 'Case' . DS . 'Model' . DS . 'PostTest.php'), array('Helper', 'Form', 'Case' . DS . 'View' . DS . 'Helper' . DS . 'FormHelperTest.php'), array('Controller', 'Posts', 'Case' . DS . 'Controller' . DS . 'PostsControllerTest.php'), array('Behavior', 'Containable', 'Case' . DS . 'Model' . DS . 'Behavior' . DS . 'ContainableBehaviorTest.php'), array('Component', 'Auth', 'Case' . DS . 'Controller' . DS . 'Component' . DS . 'AuthComponentTest.php'), array('model', 'Post', 'Case' . DS . 'Model' . DS . 'PostTest.php'), array('helper', 'Form', 'Case' . DS . 'View' . DS . 'Helper' . DS . 'FormHelperTest.php'), array('controller', 'Posts', 'Case' . DS . 'Controller' . DS . 'PostsControllerTest.php'), array('behavior', 'Containable', 'Case' . DS . 'Model' . DS . 'Behavior' . DS . 'ContainableBehaviorTest.php'), array('component', 'Auth', 'Case' . DS . 'Controller' . DS . 'Component' . DS . 'AuthComponentTest.php'), ); } /** * Test filename generation for each type + plugins * * @dataProvider caseFileNameProvider * @return void */ public function testTestCaseFileName($type, $class, $expected) { $this->Task->path = DS . 'my' . DS . 'path' . DS . 'tests' . DS; $result = $this->Task->testCaseFileName($type, $class); $expected = $this->Task->path . $expected; $this->assertEquals($expected, $result); } /** * Test filename generation for plugins. * * @return void */ public function testTestCaseFileNamePlugin() { $this->Task->path = DS . 'my' . DS . 'path' . DS . 'tests' . DS; CakePlugin::load('TestTest', array('path' => APP . 'Plugin' . DS . 'TestTest' . DS)); $this->Task->plugin = 'TestTest'; $result = $this->Task->testCaseFileName('Model', 'Post'); $expected = APP . 'Plugin' . DS . 'TestTest' . DS . 'Test' . DS . 'Case' . DS . 'Model' . DS . 'PostTest.php'; $this->assertEquals($expected, $result); } /** * test execute with a type defined * * @return void */ public function testExecuteWithOneArg() { $this->Task->args[0] = 'Model'; $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('TestTaskTag')); $this->Task->expects($this->once())->method('isLoadableClass')->will($this->returnValue(true)); $this->Task->expects($this->once())->method('createFile') ->with( $this->anything(), $this->stringContains('class TestTaskTagTest extends CakeTestCase') ); $this->Task->execute(); } /** * test execute with type and class name defined * * @return void */ public function testExecuteWithTwoArgs() { $this->Task->args = array('Model', 'TestTaskTag'); $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('TestTaskTag')); $this->Task->expects($this->once())->method('createFile') ->with( $this->anything(), $this->stringContains('class TestTaskTagTest extends CakeTestCase') ); $this->Task->expects($this->any())->method('isLoadableClass')->will($this->returnValue(true)); $this->Task->execute(); } /** * test execute with type and class name defined and lower case. * * @return void */ public function testExecuteWithTwoArgsLowerCase() { $this->Task->args = array('model', 'TestTaskTag'); $this->Task->expects($this->at(0))->method('in')->will($this->returnValue('TestTaskTag')); $this->Task->expects($this->once())->method('createFile') ->with( $this->anything(), $this->stringContains('class TestTaskTagTest extends CakeTestCase') ); $this->Task->expects($this->any())->method('isLoadableClass')->will($this->returnValue(true)); $this->Task->execute(); } /** * Data provider for mapType() tests. * * @return array */ public static function mapTypeProvider() { return array( array('controller', null, 'Controller'), array('Controller', null, 'Controller'), array('component', null, 'Controller/Component'), array('Component', null, 'Controller/Component'), array('model', null, 'Model'), array('Model', null, 'Model'), array('behavior', null, 'Model/Behavior'), array('Behavior', null, 'Model/Behavior'), array('helper', null, 'View/Helper'), array('Helper', null, 'View/Helper'), array('Helper', 'DebugKit', 'DebugKit.View/Helper'), ); } /** * Test that mapType returns the correct package names. * * @dataProvider mapTypeProvider * @return void */ public function testMapType($original, $plugin, $expected) { $this->assertEquals($expected, $this->Task->mapType($original, $plugin)); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/Task/ViewTaskTest.php000066400000000000000000000426141265552240500253440ustar00rootroot00000000000000 array( 'className' => 'TestTest.ViewTaskArticle', 'foreignKey' => 'article_id' ) ); } /** * Test View Task Article Model * * @package Cake.Test.Case.Console.Command.Task */ class ViewTaskArticle extends Model { /** * Table name * * @var string */ public $useTable = 'articles'; } /** * Test View Task Comments Controller * * @package Cake.Test.Case.Console.Command.Task */ class ViewTaskCommentsController extends Controller { /** * Testing public controller action * * @return void */ public function index() { } /** * Testing public controller action * * @return void */ public function add() { } } /** * Test View Task Articles Controller * * @package Cake.Test.Case.Console.Command.Task */ class ViewTaskArticlesController extends Controller { /** * Test public controller action * * @return void */ public function index() { } /** * Test public controller action * * @return void */ public function add() { } /** * Test admin prefixed controller action * * @return void */ public function admin_index() { } /** * Test admin prefixed controller action * * @return void */ public function admin_add() { } /** * Test admin prefixed controller action * * @return void */ public function admin_view() { } /** * Test admin prefixed controller action * * @return void */ public function admin_edit() { } /** * Test admin prefixed controller action * * @return void */ public function admin_delete() { } } /** * ViewTaskTest class * * @package Cake.Test.Case.Console.Command.Task */ class ViewTaskTest extends CakeTestCase { /** * Fixtures * * @var array */ public $fixtures = array('core.article', 'core.comment', 'core.articles_tag', 'core.tag'); /** * setUp method * * Ensure that the default theme is used * * @return void */ public function setUp() { parent::setUp(); $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Task = $this->getMock('ViewTask', array('in', 'err', 'createFile', '_stop'), array($out, $out, $in) ); $this->Task->Template = new TemplateTask($out, $out, $in); $this->Task->Controller = $this->getMock('ControllerTask', array(), array($out, $out, $in)); $this->Task->Project = $this->getMock('ProjectTask', array(), array($out, $out, $in)); $this->Task->DbConfig = $this->getMock('DbConfigTask', array(), array($out, $out, $in)); $this->Task->path = TMP; $this->Task->Template->params['theme'] = 'default'; $this->Task->Template->templatePaths = array('default' => CAKE . 'Console' . DS . 'Templates' . DS . 'default' . DS); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Task, $this->Dispatch); } /** * Test getContent and parsing of Templates. * * @return void */ public function testGetContent() { $vars = array( 'modelClass' => 'TestViewModel', 'schema' => array(), 'primaryKey' => 'id', 'displayField' => 'name', 'singularVar' => 'testViewModel', 'pluralVar' => 'testViewModels', 'singularHumanName' => 'Test View Model', 'pluralHumanName' => 'Test View Models', 'fields' => array('id', 'name', 'body'), 'associations' => array() ); $result = $this->Task->getContent('view', $vars); $this->assertRegExp('/Delete Test View Model/', $result); $this->assertRegExp('/Edit Test View Model/', $result); $this->assertRegExp('/List Test View Models/', $result); $this->assertRegExp('/New Test View Model/', $result); $this->assertRegExp('/testViewModel\[\'TestViewModel\'\]\[\'id\'\]/', $result); $this->assertRegExp('/testViewModel\[\'TestViewModel\'\]\[\'name\'\]/', $result); $this->assertRegExp('/testViewModel\[\'TestViewModel\'\]\[\'body\'\]/', $result); } /** * test getContent() using an admin_prefixed action. * * @return void */ public function testGetContentWithAdminAction() { $_back = Configure::read('Routing'); Configure::write('Routing.prefixes', array('admin')); $vars = array( 'modelClass' => 'TestViewModel', 'schema' => array(), 'primaryKey' => 'id', 'displayField' => 'name', 'singularVar' => 'testViewModel', 'pluralVar' => 'testViewModels', 'singularHumanName' => 'Test View Model', 'pluralHumanName' => 'Test View Models', 'fields' => array('id', 'name', 'body'), 'associations' => array() ); $result = $this->Task->getContent('admin_view', $vars); $this->assertRegExp('/Delete Test View Model/', $result); $this->assertRegExp('/Edit Test View Model/', $result); $this->assertRegExp('/List Test View Models/', $result); $this->assertRegExp('/New Test View Model/', $result); $this->assertRegExp('/testViewModel\[\'TestViewModel\'\]\[\'id\'\]/', $result); $this->assertRegExp('/testViewModel\[\'TestViewModel\'\]\[\'name\'\]/', $result); $this->assertRegExp('/testViewModel\[\'TestViewModel\'\]\[\'body\'\]/', $result); $result = $this->Task->getContent('admin_add', $vars); $this->assertRegExp("/input\('name'\)/", $result); $this->assertRegExp("/input\('body'\)/", $result); $this->assertRegExp('/List Test View Models/', $result); Configure::write('Routing', $_back); } /** * test Bake method * * @return void */ public function testBakeView() { $this->Task->controllerName = 'ViewTaskComments'; $this->Task->expects($this->at(0))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'view.ctp', $this->stringContains('View Task Articles') ); $this->Task->bake('view', true); } /** * test baking an edit file * * @return void */ public function testBakeEdit() { $this->Task->controllerName = 'ViewTaskComments'; $this->Task->expects($this->at(0))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'edit.ctp', new PHPUnit_Framework_Constraint_IsAnything() ); $this->Task->bake('edit', true); } /** * test baking an index * * @return void */ public function testBakeIndex() { $this->Task->controllerName = 'ViewTaskComments'; $expected = file_get_contents(CAKE . 'Test' . DS . 'bake_compare' . DS . 'View' . DS . 'index.ctp'); $this->Task->expects($this->at(0))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'index.ctp', $expected ); $this->Task->bake('index', true); } /** * test that baking a view with no template doesn't make a file. * * @return void */ public function testBakeWithNoTemplate() { $this->Task->controllerName = 'ViewTaskComments'; $this->Task->expects($this->never())->method('createFile'); $this->Task->bake('delete', true); } /** * test bake() with a -plugin param * * @return void */ public function testBakeWithPlugin() { $this->Task->controllerName = 'ViewTaskComments'; $this->Task->plugin = 'TestTest'; $this->Task->name = 'View'; //fake plugin path CakePlugin::load('TestTest', array('path' => APP . 'Plugin' . DS . 'TestTest' . DS)); $path = APP . 'Plugin' . DS . 'TestTest' . DS . 'View' . DS . 'ViewTaskComments' . DS . 'view.ctp'; $result = $this->Task->getContent('index'); $this->assertNotContains('List Test Test.view Task Articles', $result); $this->Task->expects($this->once()) ->method('createFile') ->with($path, $this->anything()); $this->Task->bake('view', true); CakePlugin::unload(); } /** * test bake actions baking multiple actions. * * @return void */ public function testBakeActions() { $this->Task->controllerName = 'ViewTaskComments'; $this->Task->expects($this->at(0))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'view.ctp', $this->stringContains('View Task Comments') ); $this->Task->expects($this->at(1))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'edit.ctp', $this->stringContains('Edit View Task Comment') ); $this->Task->expects($this->at(2))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'index.ctp', $this->stringContains('ViewTaskComment') ); $this->Task->bakeActions(array('view', 'edit', 'index'), array()); } /** * test baking a customAction (non crud) * * @return void */ public function testCustomAction() { $this->Task->controllerName = 'ViewTaskComments'; $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls('', 'my_action', 'y')); $this->Task->expects($this->once())->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'my_action.ctp', $this->anything() ); $this->Task->customAction(); } /** * Test all() * * @return void */ public function testExecuteIntoAll() { $this->Task->args[0] = 'all'; $this->Task->Controller->expects($this->once())->method('listAll') ->will($this->returnValue(array('view_task_comments'))); $this->Task->expects($this->at(0))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'index.ctp', $this->anything() ); $this->Task->expects($this->at(1))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'add.ctp', $this->anything() ); $this->Task->expects($this->exactly(2))->method('createFile'); $this->Task->execute(); } /** * Test all() with action parameter * * @return void */ public function testExecuteIntoAllWithActionName() { $this->Task->args = array('all', 'index'); $this->Task->Controller->expects($this->once())->method('listAll') ->will($this->returnValue(array('view_task_comments'))); $this->Task->expects($this->once())->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'index.ctp', $this->anything() ); $this->Task->execute(); } /** * test `cake bake view $controller view` * * @return void */ public function testExecuteWithActionParam() { $this->Task->args[0] = 'ViewTaskComments'; $this->Task->args[1] = 'view'; $this->Task->expects($this->once())->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'view.ctp', $this->anything() ); $this->Task->execute(); } /** * test `cake bake view $controller` * Ensure that views are only baked for actions that exist in the controller. * * @return void */ public function testExecuteWithController() { $this->Task->args[0] = 'ViewTaskComments'; $this->Task->expects($this->at(0))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'index.ctp', $this->anything() ); $this->Task->expects($this->at(1))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'add.ctp', $this->anything() ); $this->Task->expects($this->exactly(2))->method('createFile'); $this->Task->execute(); } /** * static dataprovider for test cases * * @return void */ public static function nameVariations() { return array(array('ViewTaskComments'), array('ViewTaskComment'), array('view_task_comment')); } /** * test that both plural and singular forms can be used for baking views. * * @dataProvider nameVariations * @return void */ public function testExecuteWithControllerVariations($name) { $this->Task->args = array($name); $this->Task->expects($this->at(0))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'index.ctp', $this->anything() ); $this->Task->expects($this->at(1))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'add.ctp', $this->anything() ); $this->Task->execute(); } /** * test `cake bake view $controller --admin` * Which only bakes admin methods, not non-admin methods. * * @return void */ public function testExecuteWithControllerAndAdminFlag() { $_back = Configure::read('Routing'); Configure::write('Routing.prefixes', array('admin')); $this->Task->args[0] = 'ViewTaskArticles'; $this->Task->params['admin'] = 1; $this->Task->Project->expects($this->any())->method('getPrefix')->will($this->returnValue('admin_')); $this->Task->expects($this->exactly(4))->method('createFile'); $views = array('admin_index.ctp', 'admin_add.ctp', 'admin_view.ctp', 'admin_edit.ctp'); foreach ($views as $i => $view) { $this->Task->expects($this->at($i))->method('createFile') ->with( TMP . 'ViewTaskArticles' . DS . $view, $this->anything() ); } $this->Task->execute(); Configure::write('Routing', $_back); } /** * test execute into interactive. * * @return void */ public function testExecuteInteractive() { $this->Task->connection = 'test'; $this->Task->args = array(); $this->Task->params = array(); $this->Task->Controller->expects($this->once())->method('getName') ->will($this->returnValue('ViewTaskComments')); $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls('y', 'y', 'n')); $this->Task->expects($this->at(3))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'index.ctp', $this->stringContains('ViewTaskComment') ); $this->Task->expects($this->at(4))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'view.ctp', $this->stringContains('ViewTaskComment') ); $this->Task->expects($this->at(5))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'add.ctp', $this->stringContains('Add View Task Comment') ); $this->Task->expects($this->at(6))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'edit.ctp', $this->stringContains('Edit View Task Comment') ); $this->Task->expects($this->exactly(4))->method('createFile'); $this->Task->execute(); } /** * test `cake bake view posts index list` * * @return void */ public function testExecuteWithAlternateTemplates() { $this->Task->connection = 'test'; $this->Task->args = array('ViewTaskComments', 'index', 'list'); $this->Task->params = array(); $this->Task->expects($this->once())->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'list.ctp', $this->stringContains('ViewTaskComment') ); $this->Task->execute(); } /** * test execute into interactive() with admin methods. * * @return void */ public function testExecuteInteractiveWithAdmin() { Configure::write('Routing.prefixes', array('admin')); $this->Task->connection = 'test'; $this->Task->args = array(); $this->Task->Controller->expects($this->once())->method('getName') ->will($this->returnValue('ViewTaskComments')); $this->Task->Project->expects($this->once())->method('getPrefix') ->will($this->returnValue('admin_')); $this->Task->expects($this->any())->method('in') ->will($this->onConsecutiveCalls('y', 'n', 'y')); $this->Task->expects($this->at(3))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'admin_index.ctp', $this->stringContains('ViewTaskComment') ); $this->Task->expects($this->at(4))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'admin_view.ctp', $this->stringContains('ViewTaskComment') ); $this->Task->expects($this->at(5))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'admin_add.ctp', $this->stringContains('Add View Task Comment') ); $this->Task->expects($this->at(6))->method('createFile') ->with( TMP . 'ViewTaskComments' . DS . 'admin_edit.ctp', $this->stringContains('Edit View Task Comment') ); $this->Task->expects($this->exactly(4))->method('createFile'); $this->Task->execute(); } /** * test getting templates, make sure noTemplateActions works and prefixed template is used before generic one. * * @return void */ public function testGetTemplate() { $result = $this->Task->getTemplate('delete'); $this->assertFalse($result); $result = $this->Task->getTemplate('add'); $this->assertEquals('form', $result); Configure::write('Routing.prefixes', array('admin')); $result = $this->Task->getTemplate('admin_add'); $this->assertEquals('form', $result); $this->Task->Template->templatePaths = array( 'test' => CAKE . 'Test' . DS . 'test_app' . DS . 'Console' . DS . 'Templates' . DS . 'test' . DS ); $this->Task->Template->params['theme'] = 'test'; $result = $this->Task->getTemplate('admin_edit'); $this->assertEquals('admin_edit', $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Command/TestShellTest.php000066400000000000000000000246571265552240500246230ustar00rootroot00000000000000_mapFileToCase($file, $category, $throwOnMissingFile); } public function mapFileToCategory($file) { return $this->_mapFileToCategory($file); } } /** * Class TestShellTest * * @package Cake.Test.Case.Console.Command */ class TestShellTest extends CakeTestCase { /** * setUp test case * * @return void */ public function setUp() { parent::setUp(); $out = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Shell = $this->getMock( 'TestTestShell', array('in', 'out', 'hr', 'help', 'error', 'err', '_stop', 'initialize', '_run', 'clear'), array($out, $out, $in) ); $this->Shell->OptionParser = $this->getMock('ConsoleOptionParser', array(), array(null, false)); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Dispatch, $this->Shell); } /** * testMapCoreFileToCategory * * @return void */ public function testMapCoreFileToCategory() { $this->Shell->startup(); $return = $this->Shell->mapFileToCategory('lib/Cake/basics.php'); $this->assertSame('core', $return); $return = $this->Shell->mapFileToCategory('lib/Cake/Core/App.php'); $this->assertSame('core', $return); $return = $this->Shell->mapFileToCategory('lib/Cake/Some/Deeply/Nested/Structure.php'); $this->assertSame('core', $return); } /** * testMapCoreFileToCase * * basics.php is a slightly special case - it's the only file in the core with a test that isn't Capitalized * * @return void */ public function testMapCoreFileToCase() { $this->Shell->startup(); $return = $this->Shell->mapFileToCase('lib/Cake/basics.php', 'core'); $this->assertSame('Basics', $return); $return = $this->Shell->mapFileToCase('lib/Cake/Core/App.php', 'core'); $this->assertSame('Core/App', $return); $return = $this->Shell->mapFileToCase('lib/Cake/Some/Deeply/Nested/Structure.php', 'core', false); $this->assertSame('Some/Deeply/Nested/Structure', $return); } /** * testMapAppFileToCategory * * @return void */ public function testMapAppFileToCategory() { $this->Shell->startup(); $return = $this->Shell->mapFileToCategory(APP . 'Controller/ExampleController.php'); $this->assertSame('app', $return); $return = $this->Shell->mapFileToCategory(APP . 'My/File/Is/Here.php'); $this->assertSame('app', $return); } /** * testMapAppFileToCase * * @return void */ public function testMapAppFileToCase() { $this->Shell->startup(); $return = $this->Shell->mapFileToCase(APP . 'Controller/ExampleController.php', 'app', false); $this->assertSame('Controller/ExampleController', $return); $return = $this->Shell->mapFileToCase(APP . 'My/File/Is/Here.php', 'app', false); $this->assertSame('My/File/Is/Here', $return); } /** * testMapPluginFileToCategory * * @return void */ public function testMapPluginFileToCategory() { $this->Shell->startup(); $return = $this->Shell->mapFileToCategory(APP . 'Plugin/awesome/Controller/ExampleController.php'); $this->assertSame('awesome', $return); $return = $this->Shell->mapFileToCategory(dirname(CAKE) . 'plugins/awesome/Controller/ExampleController.php'); $this->assertSame('awesome', $return); } /** * testMapPluginFileToCase * * @return void */ public function testMapPluginFileToCase() { $this->Shell->startup(); $return = $this->Shell->mapFileToCase(APP . 'Plugin/awesome/Controller/ExampleController.php', 'awesome', false); $this->assertSame('Controller/ExampleController', $return); $return = $this->Shell->mapFileToCase(dirname(CAKE) . 'plugins/awesome/Controller/ExampleController.php', 'awesome', false); $this->assertSame('Controller/ExampleController', $return); } /** * testMapCoreTestToCategory * * @return void */ public function testMapCoreTestToCategory() { $this->Shell->startup(); $return = $this->Shell->mapFileToCategory('lib/Cake/Test/Case/BasicsTest.php'); $this->assertSame('core', $return); $return = $this->Shell->mapFileToCategory('lib/Cake/Test/Case/BasicsTest.php'); $this->assertSame('core', $return); $return = $this->Shell->mapFileToCategory('lib/Cake/Test/Case/Some/Deeply/Nested/StructureTest.php'); $this->assertSame('core', $return); } /** * testMapCoreTestToCase * * basics.php is a slightly special case - it's the only file in the core with a test that isn't Capitalized * * @return void */ public function testMapCoreTestToCase() { $this->Shell->startup(); $return = $this->Shell->mapFileToCase('lib/Cake/Test/Case/BasicsTest.php', 'core'); $this->assertSame('Basics', $return); $return = $this->Shell->mapFileToCase('lib/Cake/Test/Case/Core/AppTest.php', 'core'); $this->assertSame('Core/App', $return); $return = $this->Shell->mapFileToCase('lib/Cake/Test/Case/Some/Deeply/Nested/StructureTest.php', 'core', false); $this->assertSame('Some/Deeply/Nested/Structure', $return); } /** * testMapAppTestToCategory * * @return void */ public function testMapAppTestToCategory() { $this->Shell->startup(); $return = $this->Shell->mapFileToCategory(APP . 'Test/Case/Controller/ExampleControllerTest.php'); $this->assertSame('app', $return); $return = $this->Shell->mapFileToCategory(APP . 'Test/Case/My/File/Is/HereTest.php'); $this->assertSame('app', $return); } /** * testMapAppTestToCase * * @return void */ public function testMapAppTestToCase() { $this->Shell->startup(); $return = $this->Shell->mapFileToCase(APP . 'Test/Case/Controller/ExampleControllerTest.php', 'app', false); $this->assertSame('Controller/ExampleController', $return); $return = $this->Shell->mapFileToCase(APP . 'Test/Case/My/File/Is/HereTest.php', 'app', false); $this->assertSame('My/File/Is/Here', $return); } /** * testMapPluginTestToCategory * * @return void */ public function testMapPluginTestToCategory() { $this->Shell->startup(); $return = $this->Shell->mapFileToCategory(APP . 'Plugin/awesome/Test/Case/Controller/ExampleControllerTest.php'); $this->assertSame('awesome', $return); $return = $this->Shell->mapFileToCategory(dirname(CAKE) . 'plugins/awesome/Test/Case/Controller/ExampleControllerTest.php'); $this->assertSame('awesome', $return); } /** * testMapPluginTestToCase * * @return void */ public function testMapPluginTestToCase() { $this->Shell->startup(); $return = $this->Shell->mapFileToCase(APP . 'Plugin/awesome/Test/Case/Controller/ExampleControllerTest.php', 'awesome', false); $this->assertSame('Controller/ExampleController', $return); $return = $this->Shell->mapFileToCase(dirname(CAKE) . 'plugins/awesome/Test/Case/Controller/ExampleControllerTest.php', 'awesome', false); $this->assertSame('Controller/ExampleController', $return); } /** * testMapNotTestToNothing * * @return void */ public function testMapNotTestToNothing() { $this->Shell->startup(); $return = $this->Shell->mapFileToCategory(APP . 'Test/Case/NotATestFile.php'); $this->assertSame('app', $return); $return = $this->Shell->mapFileToCase(APP . 'Test/Case/NotATestFile.php', false, false); $this->assertFalse($return); $return = $this->Shell->mapFileToCategory(APP . 'Test/Fixture/SomeTest.php'); $this->assertSame('app', $return); $return = $this->Shell->mapFileToCase(APP . 'Test/Fixture/SomeTest.php', false, false); $this->assertFalse($return); } /** * test available list of test cases for an empty category * * @return void */ public function testAvailableWithEmptyList() { $this->Shell->startup(); $this->Shell->args = array('unexistant-category'); $this->Shell->expects($this->at(0))->method('out')->with(__d('cake_console', "No test cases available \n\n")); $this->Shell->OptionParser->expects($this->once())->method('help'); $this->Shell->available(); } /** * test available list of test cases for core category * * @return void */ public function testAvailableCoreCategory() { $this->Shell->startup(); $this->Shell->args = array('core'); $this->Shell->expects($this->at(0))->method('out')->with('Core Test Cases:'); $this->Shell->expects($this->at(1))->method('out') ->with($this->stringContains('[1]')); $this->Shell->expects($this->at(2))->method('out') ->with($this->stringContains('[2]')); $this->Shell->expects($this->once())->method('in') ->with(__d('cake_console', 'What test case would you like to run?'), null, 'q') ->will($this->returnValue('1')); $this->Shell->expects($this->once())->method('_run'); $this->Shell->available(); $this->assertEquals(array('core', 'AllBehaviors'), $this->Shell->args); } /** * Tests that correct option for test runner are passed * * @return void */ public function testRunnerOptions() { $this->Shell->startup(); $this->Shell->args = array('core', 'Basics'); $this->Shell->params = array('filter' => 'myFilter', 'colors' => true, 'verbose' => true); $this->Shell->expects($this->once())->method('_run') ->with( array('app' => false, 'plugin' => null, 'core' => true, 'output' => 'text', 'case' => 'Basics'), array('--filter', 'myFilter', '--colors', '--verbose') ); $this->Shell->main(); } /** * Tests that the 'quiet' parameter gets swallowed before calling PHPUnit * * @return void */ public function testRunnerOptionsQuiet() { $this->Shell->startup(); $this->Shell->args = array('core', 'Basics'); $this->Shell->params = array('quiet' => true); $this->Shell->expects($this->once())->method('_run') ->with( array('app' => false, 'plugin' => null, 'core' => true, 'output' => 'text', 'case' => 'Basics'), array('--colors') ); $this->Shell->main(); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/ConsoleErrorHandlerTest.php000066400000000000000000000110141265552240500252270ustar00rootroot00000000000000Error = $this->getMock('ConsoleErrorHandler', array('_stop')); ConsoleErrorHandler::$stderr = $this->getMock('ConsoleOutput', array(), array(), '', false); } /** * tearDown * * @return void */ public function tearDown() { unset($this->Error); parent::tearDown(); } /** * test that the console error handler can deal with CakeExceptions. * * @return void */ public function testHandleError() { $content = "Notice Error: This is a notice error in [/some/file, line 275]\n"; ConsoleErrorHandler::$stderr->expects($this->once())->method('write') ->with($content); $this->Error->handleError(E_NOTICE, 'This is a notice error', '/some/file', 275); } /** * test that the console error handler can deal with fatal errors. * * @return void */ public function testHandleFatalError() { $content = "Fatal Error Error: This is a fatal error in [/some/file, line 275]\n"; ConsoleErrorHandler::$stderr->expects($this->once())->method('write') ->with($content); $this->Error->expects($this->once()) ->method('_stop') ->with(1); $this->Error->handleError(E_USER_ERROR, 'This is a fatal error', '/some/file', 275); } /** * test that the console error handler can deal with CakeExceptions. * * @return void */ public function testCakeErrors() { $exception = new MissingActionException('Missing action'); ConsoleErrorHandler::$stderr->expects($this->once())->method('write') ->with($this->stringContains('Missing action')); $this->Error->expects($this->once()) ->method('_stop') ->with(404); $this->Error->handleException($exception); } /** * test a non CakeException exception. * * @return void */ public function testNonCakeExceptions() { $exception = new InvalidArgumentException('Too many parameters.'); ConsoleErrorHandler::$stderr->expects($this->once())->method('write') ->with($this->stringContains('Too many parameters.')); $this->Error->expects($this->once()) ->method('_stop') ->with(1); $this->Error->handleException($exception); } /** * test a Error404 exception. * * @return void */ public function testError404Exception() { $exception = new NotFoundException('dont use me in cli.'); ConsoleErrorHandler::$stderr->expects($this->once())->method('write') ->with($this->stringContains('dont use me in cli.')); $this->Error->expects($this->once()) ->method('_stop') ->with(404); $this->Error->handleException($exception); } /** * test a Error500 exception. * * @return void */ public function testError500Exception() { $exception = new InternalErrorException('dont use me in cli.'); ConsoleErrorHandler::$stderr->expects($this->once())->method('write') ->with($this->stringContains('dont use me in cli.')); $this->Error->expects($this->once()) ->method('_stop') ->with(500); $this->Error->handleException($exception); } /** * test a exception with non-integer code * * @return void */ public function testNonIntegerExceptionCode() { if (PHP_VERSION_ID < 50300) { $this->markTestSkipped('ReflectionProperty::setAccessible() is available since 5.3'); } $exception = new Exception('Non-integer exception code'); $class = new ReflectionClass('Exception'); $property = $class->getProperty('code'); $property->setAccessible(true); $property->setValue($exception, '42S22'); ConsoleErrorHandler::$stderr->expects($this->once())->method('write') ->with($this->stringContains('Non-integer exception code')); $this->Error->expects($this->once()) ->method('_stop') ->with(1); $this->Error->handleException($exception); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/ConsoleOptionParserTest.php000066400000000000000000000454161265552240500253020ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Console * @since CakePHP(tm) v 2.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('ConsoleOptionParser', 'Console'); /** * Class ConsoleOptionParserTest * * @package Cake.Test.Case.Console */ class ConsoleOptionParserTest extends CakeTestCase { /** * test setting the console description * * @return void */ public function testDescription() { $parser = new ConsoleOptionParser('test', false); $result = $parser->description('A test'); $this->assertEquals($parser, $result, 'Setting description is not chainable'); $this->assertEquals('A test', $parser->description(), 'getting value is wrong.'); $parser->description(array('A test', 'something')); $this->assertEquals("A test\nsomething", $parser->description(), 'getting value is wrong.'); } /** * test setting the console epilog * * @return void */ public function testEpilog() { $parser = new ConsoleOptionParser('test', false); $result = $parser->epilog('A test'); $this->assertEquals($parser, $result, 'Setting epilog is not chainable'); $this->assertEquals('A test', $parser->epilog(), 'getting value is wrong.'); $parser->epilog(array('A test', 'something')); $this->assertEquals("A test\nsomething", $parser->epilog(), 'getting value is wrong.'); } /** * test adding an option returns self. * * @return void */ public function testAddOptionReturnSelf() { $parser = new ConsoleOptionParser('test', false); $result = $parser->addOption('test'); $this->assertEquals($parser, $result, 'Did not return $this from addOption'); } /** * test adding an option and using the long value for parsing. * * @return void */ public function testAddOptionLong() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('test', array( 'short' => 't' )); $result = $parser->parse(array('--test', 'value')); $this->assertEquals(array('test' => 'value', 'help' => false), $result[0], 'Long parameter did not parse out'); } /** * test adding an option with a zero value * * @return void */ public function testAddOptionZero() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('count', array()); $result = $parser->parse(array('--count', '0')); $this->assertEquals(array('count' => '0', 'help' => false), $result[0], 'Zero parameter did not parse out'); } /** * test addOption with an object. * * @return void */ public function testAddOptionObject() { $parser = new ConsoleOptionParser('test', false); $parser->addOption(new ConsoleInputOption('test', 't')); $result = $parser->parse(array('--test=value')); $this->assertEquals(array('test' => 'value', 'help' => false), $result[0], 'Long parameter did not parse out'); } /** * test adding an option and using the long value for parsing. * * @return void */ public function testAddOptionLongEquals() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('test', array( 'short' => 't' )); $result = $parser->parse(array('--test=value')); $this->assertEquals(array('test' => 'value', 'help' => false), $result[0], 'Long parameter did not parse out'); } /** * test adding an option and using the default. * * @return void */ public function testAddOptionDefault() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('test', array( 'default' => 'default value', )); $result = $parser->parse(array('--test')); $this->assertEquals(array('test' => 'default value', 'help' => false), $result[0], 'Default value did not parse out'); $parser = new ConsoleOptionParser('test', false); $parser->addOption('test', array( 'default' => 'default value', )); $result = $parser->parse(array()); $this->assertEquals(array('test' => 'default value', 'help' => false), $result[0], 'Default value did not parse out'); } /** * test adding an option and using the short value for parsing. * * @return void */ public function testAddOptionShort() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('test', array( 'short' => 't' )); $result = $parser->parse(array('-t', 'value')); $this->assertEquals(array('test' => 'value', 'help' => false), $result[0], 'Short parameter did not parse out'); } /** * Test that adding an option using a two letter short value causes an exception. * As they will not parse correctly. * * @expectedException ConsoleException * @return void */ public function testAddOptionShortOneLetter() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('test', array('short' => 'te')); } /** * test adding and using boolean options. * * @return void */ public function testAddOptionBoolean() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('test', array( 'boolean' => true, )); $result = $parser->parse(array('--test', 'value')); $expected = array(array('test' => true, 'help' => false), array('value')); $this->assertEquals($expected, $result); $result = $parser->parse(array('value')); $expected = array(array('test' => false, 'help' => false), array('value')); $this->assertEquals($expected, $result); } /** * test adding an multiple shorts. * * @return void */ public function testAddOptionMultipleShort() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('test', array('short' => 't', 'boolean' => true)) ->addOption('file', array('short' => 'f', 'boolean' => true)) ->addOption('output', array('short' => 'o', 'boolean' => true)); $result = $parser->parse(array('-o', '-t', '-f')); $expected = array('file' => true, 'test' => true, 'output' => true, 'help' => false); $this->assertEquals($expected, $result[0], 'Short parameter did not parse out'); $result = $parser->parse(array('-otf')); $this->assertEquals($expected, $result[0], 'Short parameter did not parse out'); } /** * test multiple options at once. * * @return void */ public function testMultipleOptions() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('test') ->addOption('connection') ->addOption('table', array('short' => 't', 'default' => true)); $result = $parser->parse(array('--test', 'value', '-t', '--connection', 'postgres')); $expected = array('test' => 'value', 'table' => true, 'connection' => 'postgres', 'help' => false); $this->assertEquals($expected, $result[0], 'multiple options did not parse'); } /** * Test adding multiple options. * * @return void */ public function testAddOptions() { $parser = new ConsoleOptionParser('something', false); $result = $parser->addOptions(array( 'name' => array('help' => 'The name'), 'other' => array('help' => 'The other arg') )); $this->assertEquals($parser, $result, 'addOptions is not chainable.'); $result = $parser->options(); $this->assertEquals(3, count($result), 'Not enough options'); } /** * test that boolean options work * * @return void */ public function testOptionWithBooleanParam() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('no-commit', array('boolean' => true)) ->addOption('table', array('short' => 't')); $result = $parser->parse(array('--table', 'posts', '--no-commit', 'arg1', 'arg2')); $expected = array(array('table' => 'posts', 'no-commit' => true, 'help' => false), array('arg1', 'arg2')); $this->assertEquals($expected, $result, 'Boolean option did not parse correctly.'); } /** * test parsing options that do not exist. * * @expectedException ConsoleException * @return void */ public function testOptionThatDoesNotExist() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('no-commit', array('boolean' => true)); $parser->parse(array('--fail', 'other')); } /** * test parsing short options that do not exist. * * @expectedException ConsoleException * @return void */ public function testShortOptionThatDoesNotExist() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('no-commit', array('boolean' => true)); $parser->parse(array('-f')); } /** * test that options with choices enforce them. * * @expectedException ConsoleException * @return void */ public function testOptionWithChoices() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('name', array('choices' => array('mark', 'jose'))); $result = $parser->parse(array('--name', 'mark')); $expected = array('name' => 'mark', 'help' => false); $this->assertEquals($expected, $result[0], 'Got the correct value.'); $parser->parse(array('--name', 'jimmy')); } /** * Ensure that option values can start with - * * @return void */ public function testOptionWithValueStartingWithMinus() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('name') ->addOption('age'); $result = $parser->parse(array('--name', '-foo', '--age', 'old')); $expected = array('name' => '-foo', 'age' => 'old', 'help' => false); $this->assertEquals($expected, $result[0], 'Option values starting with "-" are broken.'); } /** * test positional argument parsing. * * @return void */ public function testPositionalArgument() { $parser = new ConsoleOptionParser('test', false); $result = $parser->addArgument('name', array('help' => 'An argument')); $this->assertEquals($parser, $result, 'Should return this'); } /** * test addOption with an object. * * @return void */ public function testAddArgumentObject() { $parser = new ConsoleOptionParser('test', false); $parser->addArgument(new ConsoleInputArgument('test')); $result = $parser->arguments(); $this->assertCount(1, $result); $this->assertEquals('test', $result[0]->name()); } /** * Test adding arguments out of order. * * @return void */ public function testAddArgumentOutOfOrder() { $parser = new ConsoleOptionParser('test', false); $parser->addArgument('name', array('index' => 1, 'help' => 'first argument')) ->addArgument('bag', array('index' => 2, 'help' => 'second argument')) ->addArgument('other', array('index' => 0, 'help' => 'Zeroth argument')); $result = $parser->arguments(); $this->assertCount(3, $result); $this->assertEquals('other', $result[0]->name()); $this->assertEquals('name', $result[1]->name()); $this->assertEquals('bag', $result[2]->name()); $this->assertSame(array(0, 1, 2), array_keys($result)); } /** * test overwriting positional arguments. * * @return void */ public function testPositionalArgOverwrite() { $parser = new ConsoleOptionParser('test', false); $parser->addArgument('name', array('help' => 'An argument')) ->addArgument('other', array('index' => 0)); $result = $parser->arguments(); $this->assertEquals(1, count($result), 'Overwrite did not occur'); } /** * test parsing arguments. * * @expectedException ConsoleException * @return void */ public function testParseArgumentTooMany() { $parser = new ConsoleOptionParser('test', false); $parser->addArgument('name', array('help' => 'An argument')) ->addArgument('other'); $expected = array('one', 'two'); $result = $parser->parse($expected); $this->assertEquals($expected, $result[1], 'Arguments are not as expected'); $parser->parse(array('one', 'two', 'three')); } /** * test parsing arguments with 0 value. * * @return void */ public function testParseArgumentZero() { $parser = new ConsoleOptionParser('test', false); $expected = array('one', 'two', 0, 'after', 'zero'); $result = $parser->parse($expected); $this->assertEquals($expected, $result[1], 'Arguments are not as expected'); } /** * test that when there are not enough arguments an exception is raised * * @expectedException ConsoleException * @return void */ public function testPositionalArgNotEnough() { $parser = new ConsoleOptionParser('test', false); $parser->addArgument('name', array('required' => true)) ->addArgument('other', array('required' => true)); $parser->parse(array('one')); } /** * test that arguments with choices enforce them. * * @expectedException ConsoleException * @return void */ public function testPositionalArgWithChoices() { $parser = new ConsoleOptionParser('test', false); $parser->addArgument('name', array('choices' => array('mark', 'jose'))) ->addArgument('alias', array('choices' => array('cowboy', 'samurai'))) ->addArgument('weapon', array('choices' => array('gun', 'sword'))); $result = $parser->parse(array('mark', 'samurai', 'sword')); $expected = array('mark', 'samurai', 'sword'); $this->assertEquals($expected, $result[1], 'Got the correct value.'); $parser->parse(array('jose', 'coder')); } /** * Test adding multiple arguments. * * @return void */ public function testAddArguments() { $parser = new ConsoleOptionParser('test', false); $result = $parser->addArguments(array( 'name' => array('help' => 'The name'), 'other' => array('help' => 'The other arg') )); $this->assertEquals($parser, $result, 'addArguments is not chainable.'); $result = $parser->arguments(); $this->assertEquals(2, count($result), 'Not enough arguments'); } /** * test setting a subcommand up. * * @return void */ public function testSubcommand() { $parser = new ConsoleOptionParser('test', false); $result = $parser->addSubcommand('initdb', array( 'help' => 'Initialize the database' )); $this->assertEquals($parser, $result, 'Adding a subcommand is not chainable'); } /** * test addSubcommand with an object. * * @return void */ public function testAddSubcommandObject() { $parser = new ConsoleOptionParser('test', false); $parser->addSubcommand(new ConsoleInputSubcommand('test')); $result = $parser->subcommands(); $this->assertEquals(1, count($result)); $this->assertEquals('test', $result['test']->name()); } /** * test removeSubcommand with an object. * * @return void */ public function testRemoveSubcommand() { $parser = new ConsoleOptionParser('test', false); $parser->addSubcommand(new ConsoleInputSubcommand('test')); $result = $parser->subcommands(); $this->assertEquals(1, count($result)); $parser->removeSubcommand('test'); $result = $parser->subcommands(); $this->assertEquals(0, count($result), 'Remove a subcommand does not work'); } /** * test adding multiple subcommands * * @return void */ public function testAddSubcommands() { $parser = new ConsoleOptionParser('test', false); $result = $parser->addSubcommands(array( 'initdb' => array('help' => 'Initialize the database'), 'create' => array('help' => 'Create something') )); $this->assertEquals($parser, $result, 'Adding a subcommands is not chainable'); $result = $parser->subcommands(); $this->assertEquals(2, count($result), 'Not enough subcommands'); } /** * test that no exception is triggered when help is being generated * * @return void */ public function testHelpNoExceptionWhenGettingHelp() { $parser = new ConsoleOptionParser('mycommand', false); $parser->addOption('test', array('help' => 'A test option.')) ->addArgument('model', array('help' => 'The model to make.', 'required' => true)); $result = $parser->parse(array('--help')); $this->assertTrue($result[0]['help']); } /** * test that help() with a command param shows the help for a subcommand * * @return void */ public function testHelpSubcommandHelp() { $subParser = new ConsoleOptionParser('method', false); $subParser->addOption('connection', array('help' => 'Db connection.')); $parser = new ConsoleOptionParser('mycommand', false); $parser->addSubcommand('method', array( 'help' => 'This is another command', 'parser' => $subParser )) ->addOption('test', array('help' => 'A test option.')); $result = $parser->help('method'); $expected = <<Usage: cake mycommand method [-h] [--connection] Options: --help, -h Display this help. --connection Db connection. TEXT; $this->assertTextEquals($expected, $result, 'Help is not correct.'); } /** * test building a parser from an array. * * @return void */ public function testBuildFromArray() { $spec = array( 'command' => 'test', 'arguments' => array( 'name' => array('help' => 'The name'), 'other' => array('help' => 'The other arg') ), 'options' => array( 'name' => array('help' => 'The name'), 'other' => array('help' => 'The other arg') ), 'subcommands' => array( 'initdb' => array('help' => 'make database') ), 'description' => 'description text', 'epilog' => 'epilog text' ); $parser = ConsoleOptionParser::buildFromArray($spec); $this->assertEquals($spec['description'], $parser->description()); $this->assertEquals($spec['epilog'], $parser->epilog()); $options = $parser->options(); $this->assertTrue(isset($options['name'])); $this->assertTrue(isset($options['other'])); $args = $parser->arguments(); $this->assertEquals(2, count($args)); $commands = $parser->subcommands(); $this->assertEquals(1, count($commands)); } /** * test that create() returns instances * * @return void */ public function testCreateFactory() { $parser = ConsoleOptionParser::create('factory', false); $this->assertInstanceOf('ConsoleOptionParser', $parser); $this->assertEquals('factory', $parser->command()); } /** * test that command() inflects the command name. * * @return void */ public function testCommandInflection() { $parser = new ConsoleOptionParser('CommandLine'); $this->assertEquals('command_line', $parser->command()); } /** * test that parse() takes a subcommand argument, and that the subcommand parser * is used. * * @return void */ public function testParsingWithSubParser() { $parser = new ConsoleOptionParser('test', false); $parser->addOption('primary') ->addArgument('one', array('required' => true, 'choices' => array('a', 'b'))) ->addArgument('two', array('required' => true)) ->addSubcommand('sub', array( 'parser' => array( 'options' => array( 'secondary' => array('boolean' => true), 'fourth' => array('help' => 'fourth option') ), 'arguments' => array( 'sub_arg' => array('choices' => array('c', 'd')) ) ) )); $result = $parser->parse(array('--secondary', '--fourth', '4', 'c'), 'sub'); $expected = array(array( 'secondary' => true, 'fourth' => '4', 'help' => false, 'verbose' => false, 'quiet' => false), array('c')); $this->assertEquals($expected, $result, 'Sub parser did not parse request.'); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/ConsoleOutputTest.php000066400000000000000000000157031265552240500241510ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Console * @since CakePHP(tm) v 1.2.0.5432 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('ConsoleOutput', 'Console'); /** * Class ConsoleOutputTest * * @package Cake.Test.Case.Console */ class ConsoleOutputTest extends CakeTestCase { /** * setup * * @return void */ public function setUp() { parent::setUp(); $this->output = $this->getMock('ConsoleOutput', array('_write')); $this->output->outputAs(ConsoleOutput::COLOR); } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); unset($this->output); } /** * test writing with no new line * * @return void */ public function testWriteNoNewLine() { $this->output->expects($this->once())->method('_write') ->with('Some output'); $this->output->write('Some output', false); } /** * test writing with no new line * * @return void */ public function testWriteNewLine() { $this->output->expects($this->once())->method('_write') ->with('Some output' . PHP_EOL); $this->output->write('Some output'); } /** * test write() with multiple new lines * * @return void */ public function testWriteMultipleNewLines() { $this->output->expects($this->once())->method('_write') ->with('Some output' . PHP_EOL . PHP_EOL . PHP_EOL . PHP_EOL); $this->output->write('Some output', 4); } /** * test writing an array of messages. * * @return void */ public function testWriteArray() { $this->output->expects($this->once())->method('_write') ->with('Line' . PHP_EOL . 'Line' . PHP_EOL . 'Line' . PHP_EOL); $this->output->write(array('Line', 'Line', 'Line')); } /** * test writing an array of messages. * * @return void */ public function testOverwrite() { $testString = "Text"; $this->output->expects($this->at(0))->method('_write') ->with($testString); $this->output->expects($this->at(1))->method('_write') ->with(""); $this->output->expects($this->at(2))->method('_write') ->with("Overwriting text"); $this->output->write($testString, 0); $this->output->overwrite("Overwriting text"); } /** * test getting a style. * * @return void */ public function testStylesGet() { $result = $this->output->styles('error'); $expected = array('text' => 'red', 'underline' => true); $this->assertEquals($expected, $result); $this->assertNull($this->output->styles('made_up_goop')); $result = $this->output->styles(); $this->assertNotEmpty($result, 'error', 'Error is missing'); $this->assertNotEmpty($result, 'warning', 'Warning is missing'); } /** * test adding a style. * * @return void */ public function testStylesAdding() { $this->output->styles('test', array('text' => 'red', 'background' => 'black')); $result = $this->output->styles('test'); $expected = array('text' => 'red', 'background' => 'black'); $this->assertEquals($expected, $result); $this->assertTrue($this->output->styles('test', false), 'Removing a style should return true.'); $this->assertNull($this->output->styles('test'), 'Removed styles should be null.'); } /** * test formatting text with styles. * * @return void */ public function testFormattingSimple() { $this->output->expects($this->once())->method('_write') ->with("\033[31;4mError:\033[0m Something bad"); $this->output->write('Error: Something bad', false); } /** * test that formatting doesn't eat tags it doesn't know about. * * @return void */ public function testFormattingNotEatingTags() { $this->output->expects($this->once())->method('_write') ->with(" Something bad"); $this->output->write(' Something bad', false); } /** * test formatting with custom styles. * * @return void */ public function testFormattingCustom() { $this->output->styles('annoying', array( 'text' => 'magenta', 'background' => 'cyan', 'blink' => true, 'underline' => true )); $this->output->expects($this->once())->method('_write') ->with("\033[35;46;5;4mAnnoy:\033[0m Something bad"); $this->output->write('Annoy: Something bad', false); } /** * test formatting text with missing styles. * * @return void */ public function testFormattingMissingStyleName() { $this->output->expects($this->once())->method('_write') ->with("Error: Something bad"); $this->output->write('Error: Something bad', false); } /** * test formatting text with multiple styles. * * @return void */ public function testFormattingMultipleStylesName() { $this->output->expects($this->once())->method('_write') ->with("\033[31;4mBad\033[0m \033[33mWarning\033[0m Regular"); $this->output->write('Bad Warning Regular', false); } /** * test that multiple tags of the same name work in one string. * * @return void */ public function testFormattingMultipleSameTags() { $this->output->expects($this->once())->method('_write') ->with("\033[31;4mBad\033[0m \033[31;4mWarning\033[0m Regular"); $this->output->write('Bad Warning Regular', false); } /** * test raw output not getting tags replaced. * * @return void */ public function testOutputAsRaw() { $this->output->outputAs(ConsoleOutput::RAW); $this->output->expects($this->once())->method('_write') ->with('Bad Regular'); $this->output->write('Bad Regular', false); } /** * test plain output. * * @return void */ public function testOutputAsPlain() { $this->output->outputAs(ConsoleOutput::PLAIN); $this->output->expects($this->once())->method('_write') ->with('Bad Regular'); $this->output->write('Bad Regular', false); } /** * test plain output when php://output, as php://output is * not compatible with posix_ functions. * * @return void */ public function testOutputAsPlainWhenOutputStream() { $output = $this->getMock('ConsoleOutput', array('_write'), array('php://output')); $this->assertEquals(ConsoleOutput::PLAIN, $output->outputAs()); } /** * test plain output only strips tags used for formatting. * * @return void */ public function testOutputAsPlainSelectiveTagRemoval() { $this->output->outputAs(ConsoleOutput::PLAIN); $this->output->expects($this->once())->method('_write') ->with('Bad Regular Left behind '); $this->output->write('Bad Regular Left behind ', false); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/HelpFormatterTest.php000066400000000000000000000343661265552240500241100ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Console * @since CakePHP(tm) v 2.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('ConsoleOptionParser', 'Console'); App::uses('HelpFormatter', 'Console'); /** * Class HelpFormatterTest * * @package Cake.Test.Case.Console */ class HelpFormatterTest extends CakeTestCase { /** * test that the console max width is respected when generating help. * * @return void */ public function testWidthFormatting() { $parser = new ConsoleOptionParser('test', false); $parser->description('This is fifteen This is fifteen This is fifteen') ->addOption('four', array('help' => 'this is help text this is help text')) ->addArgument('four', array('help' => 'this is help text this is help text')) ->addSubcommand('four', array('help' => 'this is help text this is help text')); $formatter = new HelpFormatter($parser); $result = $formatter->text(30); $expected = <<Usage: cake test [subcommand] [-h] [--four] [] Subcommands: four this is help text this is help text To see help on a subcommand use `cake test [subcommand] --help` Options: --help, -h Display this help. --four this is help text this is help text Arguments: four this is help text this is help text (optional) TEXT; $this->assertTextEquals($expected, $result, 'Generated help is too wide'); } /** * test help() with options and arguments that have choices. * * @return void */ public function testHelpWithChoices() { $parser = new ConsoleOptionParser('mycommand', false); $parser->addOption('test', array('help' => 'A test option.', 'choices' => array('one', 'two'))) ->addArgument('type', array( 'help' => 'Resource type.', 'choices' => array('aco', 'aro'), 'required' => true )) ->addArgument('other_longer', array('help' => 'Another argument.')); $formatter = new HelpFormatter($parser); $result = $formatter->text(); $expected = <<Usage: cake mycommand [-h] [--test one|two] [] Options: --help, -h Display this help. --test A test option. (choices: one|two) Arguments: type Resource type. (choices: aco|aro) other_longer Another argument. (optional) TEXT; $this->assertTextEquals($expected, $result, 'Help does not match'); } /** * test description and epilog in the help * * @return void */ public function testHelpDescriptionAndEpilog() { $parser = new ConsoleOptionParser('mycommand', false); $parser->description('Description text') ->epilog('epilog text') ->addOption('test', array('help' => 'A test option.')) ->addArgument('model', array('help' => 'The model to make.', 'required' => true)); $formatter = new HelpFormatter($parser); $result = $formatter->text(); $expected = <<Usage: cake mycommand [-h] [--test] Options: --help, -h Display this help. --test A test option. Arguments: model The model to make. epilog text TEXT; $this->assertTextEquals($expected, $result, 'Help is wrong.'); } /** * test that help() outputs subcommands. * * @return void */ public function testHelpSubcommand() { $parser = new ConsoleOptionParser('mycommand', false); $parser->addSubcommand('method', array('help' => 'This is another command')) ->addOption('test', array('help' => 'A test option.')); $formatter = new HelpFormatter($parser); $result = $formatter->text(); $expected = <<Usage: cake mycommand [subcommand] [-h] [--test] Subcommands: method This is another command To see help on a subcommand use `cake mycommand [subcommand] --help` Options: --help, -h Display this help. --test A test option. TEXT; $this->assertTextEquals($expected, $result, 'Help is not correct.'); } /** * test getting help with defined options. * * @return void */ public function testHelpWithOptions() { $parser = new ConsoleOptionParser('mycommand', false); $parser->addOption('test', array('help' => 'A test option.')) ->addOption('connection', array( 'short' => 'c', 'help' => 'The connection to use.', 'default' => 'default' )); $formatter = new HelpFormatter($parser); $result = $formatter->text(); $expected = <<Usage: cake mycommand [-h] [--test] [-c default] Options: --help, -h Display this help. --test A test option. --connection, -c The connection to use. (default: default) TEXT; $this->assertTextEquals($expected, $result, 'Help does not match'); } /** * test getting help with defined options. * * @return void */ public function testHelpWithOptionsAndArguments() { $parser = new ConsoleOptionParser('mycommand', false); $parser->addOption('test', array('help' => 'A test option.')) ->addArgument('model', array('help' => 'The model to make.', 'required' => true)) ->addArgument('other_longer', array('help' => 'Another argument.')); $formatter = new HelpFormatter($parser); $result = $formatter->text(); $expected = <<Usage: cake mycommand [-h] [--test] [] Options: --help, -h Display this help. --test A test option. Arguments: model The model to make. other_longer Another argument. (optional) TEXT; $this->assertTextEquals($expected, $result, 'Help does not match'); } /** * Test that a long set of options doesn't make useless output. * * @return void */ public function testHelpWithLotsOfOptions() { $parser = new ConsoleOptionParser('mycommand', false); $parser ->addOption('test', array('help' => 'A test option.')) ->addOption('test2', array('help' => 'A test option.')) ->addOption('test3', array('help' => 'A test option.')) ->addOption('test4', array('help' => 'A test option.')) ->addOption('test5', array('help' => 'A test option.')) ->addOption('test6', array('help' => 'A test option.')) ->addOption('test7', array('help' => 'A test option.')) ->addArgument('model', array('help' => 'The model to make.', 'required' => true)) ->addArgument('other_longer', array('help' => 'Another argument.')); $formatter = new HelpFormatter($parser); $result = $formatter->text(); $expected = 'cake mycommand [options] []'; $this->assertContains($expected, $result); } /** * Test that a long set of arguments doesn't make useless output. * * @return void */ public function testHelpWithLotsOfArguments() { $parser = new ConsoleOptionParser('mycommand', false); $parser ->addArgument('test', array('help' => 'A test option.')) ->addArgument('test2', array('help' => 'A test option.')) ->addArgument('test3', array('help' => 'A test option.')) ->addArgument('test4', array('help' => 'A test option.')) ->addArgument('test5', array('help' => 'A test option.')) ->addArgument('test6', array('help' => 'A test option.')) ->addArgument('test7', array('help' => 'A test option.')) ->addArgument('model', array('help' => 'The model to make.', 'required' => true)) ->addArgument('other_longer', array('help' => 'Another argument.')); $formatter = new HelpFormatter($parser); $result = $formatter->text(); $expected = 'cake mycommand [-h] [arguments]'; $this->assertContains($expected, $result); } /** * test help() with options and arguments that have choices. * * @return void */ public function testXmlHelpWithChoices() { $parser = new ConsoleOptionParser('mycommand', false); $parser->addOption('test', array('help' => 'A test option.', 'choices' => array('one', 'two'))) ->addArgument('type', array( 'help' => 'Resource type.', 'choices' => array('aco', 'aro'), 'required' => true )) ->addArgument('other_longer', array('help' => 'Another argument.')); $formatter = new HelpFormatter($parser); $result = $formatter->xml(); $expected = << mycommand Description text aco aro epilog text TEXT; $this->assertEquals(new DomDocument($expected), new DomDocument($result), 'Help does not match'); } /** * test description and epilog in the help * * @return void */ public function testXmlHelpDescriptionAndEpilog() { $parser = new ConsoleOptionParser('mycommand', false); $parser->description('Description text') ->epilog('epilog text') ->addOption('test', array('help' => 'A test option.')) ->addArgument('model', array('help' => 'The model to make.', 'required' => true)); $formatter = new HelpFormatter($parser); $result = $formatter->xml(); $expected = << mycommand Description text epilog text TEXT; $this->assertEquals(new DomDocument($expected), new DomDocument($result), 'Help does not match'); } /** * test that help() outputs subcommands. * * @return void */ public function testXmlHelpSubcommand() { $parser = new ConsoleOptionParser('mycommand', false); $parser->addSubcommand('method', array('help' => 'This is another command')) ->addOption('test', array('help' => 'A test option.')); $formatter = new HelpFormatter($parser); $result = $formatter->xml(); $expected = << mycommand TEXT; $this->assertEquals(new DomDocument($expected), new DomDocument($result), 'Help does not match'); } /** * test getting help with defined options. * * @return void */ public function testXmlHelpWithOptions() { $parser = new ConsoleOptionParser('mycommand', false); $parser->addOption('test', array('help' => 'A test option.')) ->addOption('connection', array( 'short' => 'c', 'help' => 'The connection to use.', 'default' => 'default' )); $formatter = new HelpFormatter($parser); $result = $formatter->xml(); $expected = << mycommand TEXT; $this->assertEquals(new DomDocument($expected), new DomDocument($result), 'Help does not match'); } /** * test getting help with defined options. * * @return void */ public function testXmlHelpWithOptionsAndArguments() { $parser = new ConsoleOptionParser('mycommand', false); $parser->addOption('test', array('help' => 'A test option.')) ->addArgument('model', array('help' => 'The model to make.', 'required' => true)) ->addArgument('other_longer', array('help' => 'Another argument.')); $formatter = new HelpFormatter($parser); $result = $formatter->xml(); $expected = << mycommand TEXT; $this->assertEquals(new DomDocument($expected), new DomDocument($result), 'Help does not match'); } /** * Test xml help as object * * @return void */ public function testXmlHelpAsObject() { $parser = new ConsoleOptionParser('mycommand', false); $parser->addOption('test', array('help' => 'A test option.')) ->addArgument('model', array('help' => 'The model to make.', 'required' => true)) ->addArgument('other_longer', array('help' => 'Another argument.')); $formatter = new HelpFormatter($parser); $result = $formatter->xml(false); $this->assertInstanceOf('SimpleXmlElement', $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/Helper/000077500000000000000000000000001265552240500211665ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Console/Helper/ProgressShellHelperTest.php000066400000000000000000000135431265552240500265010ustar00rootroot00000000000000consoleOutput = new ConsoleOutputStub(); $this->helper = new ProgressShellHelper($this->consoleOutput); } /** * Test that a callback is required.* * * @expectedException \RuntimeException * @return void */ public function testOutputFailure() { $this->helper->output(array('not a callback')); } /** * Test that the callback is invoked until 100 is reached. * * @return void */ public function testOutputSuccess() { $this->helper->output(array(function ($progress) { $progress->increment(20); })); $expected = array( '', '==============> 20%', '', '=============================> 40%', '', '============================================> 60%', '', '===========================================================> 80%', '', '==========================================================================> 100%', '', ); $this->assertEquals($expected, $this->consoleOutput->messages()); } /** * Test output with options * * @return void */ public function testOutputSuccessOptions() { $this->helper->output(array( 'total' => 10, 'width' => 20, 'callback' => function ($progress) { $progress->increment(2); } )); $expected = array( '', '==> 20%', '', '=====> 40%', '', '========> 60%', '', '===========> 80%', '', '==============> 100%', '', ); $this->assertEquals($expected, $this->consoleOutput->messages()); } /** * Test using the helper manually. * * @return void */ public function testIncrementAndRender() { $this->helper->init(); $this->helper->increment(20); $this->helper->draw(); $this->helper->increment(40); $this->helper->draw(); $this->helper->increment(40); $this->helper->draw(); $expected = array( '', '==============> 20%', '', '============================================> 60%', '', '==========================================================================> 100%', ); $this->assertEquals($expected, $this->consoleOutput->messages()); } /** * Test negative numbers * * @return void */ public function testIncrementWithNegatives() { $this->helper->init(); $this->helper->increment(40); $this->helper->draw(); $this->helper->increment(-60); $this->helper->draw(); $this->helper->increment(80); $this->helper->draw(); $expected = array( '', '=============================> 40%', '', ' 0%', '', '===========================================================> 80%', ); $this->assertEquals($expected, $this->consoleOutput->messages()); } /** * Test increment and draw with options * * @return void */ public function testIncrementWithOptions() { $this->helper->init(array( 'total' => 10, 'width' => 20, )); $this->helper->increment(4); $this->helper->draw(); $this->helper->increment(4); $this->helper->draw(); $this->helper->increment(4); $this->helper->draw(); $expected = array( '', '=====> 40%', '', '===========> 80%', '', '==============> 100%', ); $this->assertEquals($expected, $this->consoleOutput->messages()); } /** * Test increment and draw with value that makes the pad * be a float * * @return void */ public function testIncrementFloatPad() { $this->helper->init(array( 'total' => 50 )); $this->helper->increment(7); $this->helper->draw(); $this->helper->increment(7); $this->helper->draw(); $this->helper->increment(7); $this->helper->draw(); $this->helper->increment(7); $this->helper->draw(); $this->helper->increment(7); $this->helper->draw(); $this->helper->increment(3); $this->helper->draw(); $this->helper->increment(4); $this->helper->draw(); $this->helper->increment(8); $this->helper->draw(); $expected = array( '', '=========> 14%', '', '====================> 28%', '', '==============================> 42%', '', '=========================================> 56%', '', '===================================================> 70%', '', '========================================================> 76%', '', '==============================================================> 84%', '', '==========================================================================> 100%', ); $this->assertEquals($expected, $this->consoleOutput->messages()); } }cakephp-2.8.0/lib/Cake/Test/Case/Console/Helper/TableShellHelperTest.php000066400000000000000000000147461265552240500257320ustar00rootroot00000000000000consoleOutput = new ConsoleOutputStub(); $this->helper = new TableShellHelper($this->consoleOutput); } /** * Test output * * @return void */ public function testDefaultOutput() { $data = array( array('Header 1', 'Header', 'Long Header'), array('short', 'Longish thing', 'short'), array('Longer thing', 'short', 'Longest Value'), ); $this->helper->output($data); $expected = array( '+--------------+---------------+---------------+', '| Header 1 | Header | Long Header |', '+--------------+---------------+---------------+', '| short | Longish thing | short |', '| Longer thing | short | Longest Value |', '+--------------+---------------+---------------+', ); $this->assertEquals($expected, $this->consoleOutput->messages()); } /** * Test output with multibyte characters * * @return void */ public function testOutputUtf8() { $data = array( array('Header 1', 'Head', 'Long Header'), array('short', 'ร„ร„ร„รœรœรœ', 'short'), array('Longer thing', 'longerish', 'Longest Value'), ); $this->helper->output($data); $expected = array( '+--------------+-----------+---------------+', '| Header 1 | Head | Long Header |', '+--------------+-----------+---------------+', '| short | ร„ร„ร„รœรœรœ | short |', '| Longer thing | longerish | Longest Value |', '+--------------+-----------+---------------+', ); $this->assertEquals($expected, $this->consoleOutput->messages()); } /** * Test output without headers * * @return void */ public function testOutputWithoutHeaderStyle() { $data = array( array('Header 1', 'Header', 'Long Header'), array('short', 'Longish thing', 'short'), array('Longer thing', 'short', 'Longest Value'), ); $this->helper->config(array('headerStyle' => false)); $this->helper->output($data); $expected = array( '+--------------+---------------+---------------+', '| Header 1 | Header | Long Header |', '+--------------+---------------+---------------+', '| short | Longish thing | short |', '| Longer thing | short | Longest Value |', '+--------------+---------------+---------------+', ); $this->assertEquals($expected, $this->consoleOutput->messages()); } /** * Test output with different header style * * @return void */ public function testOutputWithDifferentHeaderStyle() { $data = array( array('Header 1', 'Header', 'Long Header'), array('short', 'Longish thing', 'short'), array('Longer thing', 'short', 'Longest Value'), ); $this->helper->config(array('headerStyle' => 'error')); $this->helper->output($data); $expected = array( '+--------------+---------------+---------------+', '| Header 1 | Header | Long Header |', '+--------------+---------------+---------------+', '| short | Longish thing | short |', '| Longer thing | short | Longest Value |', '+--------------+---------------+---------------+', ); $this->assertEquals($expected, $this->consoleOutput->messages()); } /** * Test output without table headers * * @return void */ public function testOutputWithoutHeaders() { $data = array( array('short', 'Longish thing', 'short'), array('Longer thing', 'short', 'Longest Value'), ); $this->helper->config(array('headers' => false)); $this->helper->output($data); $expected = array( '+--------------+---------------+---------------+', '| short | Longish thing | short |', '| Longer thing | short | Longest Value |', '+--------------+---------------+---------------+', ); $this->assertEquals($expected, $this->consoleOutput->messages()); } /** * Test output with row separator * * @return void */ public function testOutputWithRowSeparator() { $data = array( array('Header 1', 'Header', 'Long Header'), array('short', 'Longish thing', 'short'), array('Longer thing', 'short', 'Longest Value') ); $this->helper->config(array('rowSeparator' => true)); $this->helper->output($data); $expected = array( '+--------------+---------------+---------------+', '| Header 1 | Header | Long Header |', '+--------------+---------------+---------------+', '| short | Longish thing | short |', '+--------------+---------------+---------------+', '| Longer thing | short | Longest Value |', '+--------------+---------------+---------------+', ); $this->assertEquals($expected, $this->consoleOutput->messages()); } /** * Test output with row separator and no headers * * @return void */ public function testOutputWithRowSeparatorAndHeaders() { $data = array( array('Header 1', 'Header', 'Long Header'), array('short', 'Longish thing', 'short'), array('Longer thing', 'short', 'Longest Value'), ); $this->helper->config(array('rowSeparator' => true)); $this->helper->output($data); $expected = array( '+--------------+---------------+---------------+', '| Header 1 | Header | Long Header |', '+--------------+---------------+---------------+', '| short | Longish thing | short |', '+--------------+---------------+---------------+', '| Longer thing | short | Longest Value |', '+--------------+---------------+---------------+', ); $this->assertEquals($expected, $this->consoleOutput->messages()); } }cakephp-2.8.0/lib/Cake/Test/Case/Console/ShellDispatcherTest.php000066400000000000000000000345101265552240500244010ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Console * @since CakePHP(tm) v 1.2.0.5432 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('ShellDispatcher', 'Console'); /** * TestShellDispatcher class * * @package Cake.Test.Case.Console */ class TestShellDispatcher extends ShellDispatcher { /** * params property * * @var array */ public $params = array(); /** * stopped property * * @var string */ public $stopped = null; /** * TestShell * * @var mixed */ public $TestShell; /** * _initEnvironment method * * @return void */ protected function _initEnvironment() { } /** * clear method * * @return void */ public function clear() { } /** * _stop method * * @return void */ protected function _stop($status = 0) { $this->stopped = 'Stopped with status: ' . $status; return $status; } /** * getShell * * @param string $shell * @return mixed */ public function getShell($shell) { return $this->_getShell($shell); } /** * _getShell * * @param string $plugin * @return mixed */ protected function _getShell($shell) { if (isset($this->TestShell)) { return $this->TestShell; } return parent::_getShell($shell); } } /** * ShellDispatcherTest * * @package Cake.Test.Case.Console */ class ShellDispatcherTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); App::build(array( 'Plugin' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS ), 'Console/Command' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Console' . DS . 'Command' . DS ) ), App::RESET); CakePlugin::load('TestPlugin'); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); CakePlugin::unload(); } /** * testParseParams method * * @return void */ public function testParseParams() { $Dispatcher = new TestShellDispatcher(); $params = array( '/cake/1.2.x.x/cake/console/cake.php', 'bake', '-app', 'new', '-working', '/var/www/htdocs' ); $expected = array( 'app' => 'new', 'webroot' => 'webroot', 'working' => str_replace('/', DS, '/var/www/htdocs/new'), 'root' => str_replace('/', DS, '/var/www/htdocs') ); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); $params = array('cake.php'); $expected = array( 'app' => 'app', 'webroot' => 'webroot', 'working' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH) . DS . 'app'), 'root' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH)), ); $Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); $params = array( 'cake.php', '-app', 'new', ); $expected = array( 'app' => 'new', 'webroot' => 'webroot', 'working' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH) . DS . 'new'), 'root' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH)) ); $Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); $params = array( './cake.php', 'bake', '-app', 'new', '-working', '/cake/1.2.x.x/cake/console' ); $expected = array( 'app' => 'new', 'webroot' => 'webroot', 'working' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH) . DS . 'new'), 'root' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH)) ); $Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); $params = array( './console/cake.php', 'bake', '-app', 'new', '-working', '/cake/1.2.x.x/cake' ); $expected = array( 'app' => 'new', 'webroot' => 'webroot', 'working' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH) . DS . 'new'), 'root' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH)) ); $Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); $params = array( './console/cake.php', 'bake', '-app', 'new', '-dry', '-working', '/cake/1.2.x.x/cake' ); $expected = array( 'app' => 'new', 'working' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH) . DS . 'new'), 'root' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH)), 'webroot' => 'webroot' ); $Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); $params = array( './console/cake.php', '-working', '/cake/1.2.x.x/cake', 'schema', 'run', 'create', '-dry', '-f', '-name', 'DbAcl' ); $expected = array( 'app' => 'app', 'webroot' => 'webroot', 'working' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH) . DS . 'app'), 'root' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH)), ); $Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); $expected = array( './console/cake.php', 'schema', 'run', 'create', '-dry', '-f', '-name', 'DbAcl' ); $this->assertEquals($expected, $Dispatcher->args); $params = array( '/cake/1.2.x.x/cake/console/cake.php', '-working', '/cake/1.2.x.x/app', 'schema', 'run', 'create', '-dry', '-name', 'DbAcl' ); $expected = array( 'app' => 'app', 'webroot' => 'webroot', 'working' => str_replace('/', DS, '/cake/1.2.x.x/app'), 'root' => str_replace('/', DS, '/cake/1.2.x.x'), ); $Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); $params = array( 'cake.php', '-working', 'C:/wamp/www/cake/app', 'bake', '-app', 'C:/wamp/www/apps/cake/app', ); $expected = array( 'app' => 'app', 'webroot' => 'webroot', 'working' => 'C:\wamp\www\apps\cake\app', 'root' => 'C:\wamp\www\apps\cake' ); $Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); $params = array( 'cake.php', '-working', 'C:\wamp\www\cake\app', 'bake', '-app', 'C:\wamp\www\apps\cake\app', ); $expected = array( 'app' => 'app', 'webroot' => 'webroot', 'working' => 'C:\wamp\www\apps\cake\app', 'root' => 'C:\wamp\www\apps\cake' ); $Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); $params = array( 'cake.php', '-working', 'C:\wamp\www\apps', 'bake', '-app', 'cake\app', '-url', 'http://example.com/some/url/with/a/path' ); $expected = array( 'app' => 'app', 'webroot' => 'webroot', 'working' => 'C:\wamp\www\apps\cake\app', 'root' => 'C:\wamp\www\apps\cake', ); $Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); $params = array( '/home/amelo/dev/cake-common/cake/console/cake.php', '-root', '/home/amelo/dev/lsbu-vacancy', '-working', '/home/amelo/dev/lsbu-vacancy', '-app', 'app', ); $expected = array( 'app' => 'app', 'webroot' => 'webroot', 'working' => '/home/amelo/dev/lsbu-vacancy/app', 'root' => '/home/amelo/dev/lsbu-vacancy', ); $Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); $params = array( '/cake/1.2.x.x/cake/console/cake.php', 'bake', '-app', 'new', '-app', 'old', '-working', '/var/www/htdocs' ); $expected = array( 'app' => 'old', 'webroot' => 'webroot', 'working' => str_replace('/', DS, '/var/www/htdocs/old'), 'root' => str_replace('/', DS, '/var/www/htdocs') ); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); if (DS === '\\') { $params = array( 'cake.php', '-working', 'D:\www', 'bake', 'my_app', ); $expected = array( 'working' => 'D:\\\\www', 'app' => 'www', 'root' => 'D:\\', 'webroot' => 'webroot' ); $Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->parseParams($params); $this->assertEquals($expected, $Dispatcher->params); } } /** * Verify loading of (plugin-) shells * * @return void */ public function testGetShell() { $this->skipIf(class_exists('SampleShell'), 'SampleShell Class already loaded.'); $this->skipIf(class_exists('ExampleShell'), 'ExampleShell Class already loaded.'); $Dispatcher = new TestShellDispatcher(); $result = $Dispatcher->getShell('sample'); $this->assertInstanceOf('SampleShell', $result); $Dispatcher = new TestShellDispatcher(); $result = $Dispatcher->getShell('test_plugin.example'); $this->assertInstanceOf('ExampleShell', $result); $this->assertEquals('TestPlugin', $result->plugin); $this->assertEquals('Example', $result->name); $Dispatcher = new TestShellDispatcher(); $result = $Dispatcher->getShell('TestPlugin.example'); $this->assertInstanceOf('ExampleShell', $result); $Dispatcher = new TestShellDispatcher(); $result = $Dispatcher->getShell('test_plugin'); $this->assertInstanceOf('TestPluginShell', $result); $Dispatcher = new TestShellDispatcher(); $result = $Dispatcher->getShell('TestPlugin'); $this->assertInstanceOf('TestPluginShell', $result); } /** * Verify correct dispatch of Shell subclasses with a main method * * @return void */ public function testDispatchShellWithMain() { $Dispatcher = new TestShellDispatcher(); $Shell = $this->getMock('Shell'); $Shell->expects($this->once())->method('initialize'); $Shell->expects($this->once())->method('runCommand') ->with(null, array()) ->will($this->returnValue(true)); $Dispatcher->TestShell = $Shell; $Dispatcher->args = array('mock_with_main'); $result = $Dispatcher->dispatch(); $this->assertTrue($result); $this->assertEquals(array(), $Dispatcher->args); } /** * Verify correct dispatch of Shell subclasses without a main method * * @return void */ public function testDispatchShellWithoutMain() { $Dispatcher = new TestShellDispatcher(); $Shell = $this->getMock('Shell'); $Shell->expects($this->once())->method('initialize'); $Shell->expects($this->once())->method('runCommand') ->with('initdb', array('initdb')) ->will($this->returnValue(true)); $Dispatcher->TestShell = $Shell; $Dispatcher->args = array('mock_without_main', 'initdb'); $result = $Dispatcher->dispatch(); $this->assertTrue($result); } /** * Verify correct dispatch of custom classes with a main method * * @return void */ public function testDispatchNotAShellWithMain() { $Dispatcher = new TestShellDispatcher(); $methods = get_class_methods('Object'); array_push($methods, 'main', 'initdb', 'initialize', 'loadTasks', 'startup', '_secret'); $Shell = $this->getMock('Object', $methods); $Shell->expects($this->never())->method('initialize'); $Shell->expects($this->once())->method('startup'); $Shell->expects($this->once())->method('main')->will($this->returnValue(true)); $Dispatcher->TestShell = $Shell; $Dispatcher->args = array('mock_with_main_not_a'); $result = $Dispatcher->dispatch(); $this->assertTrue($result); $this->assertEquals(array(), $Dispatcher->args); $Shell = $this->getMock('Object', $methods); $Shell->expects($this->once())->method('initdb')->will($this->returnValue(true)); $Shell->expects($this->once())->method('startup'); $Dispatcher->TestShell = $Shell; $Dispatcher->args = array('mock_with_main_not_a', 'initdb'); $result = $Dispatcher->dispatch(); $this->assertTrue($result); } /** * Verify correct dispatch of custom classes without a main method * * @return void */ public function testDispatchNotAShellWithoutMain() { $Dispatcher = new TestShellDispatcher(); $methods = get_class_methods('Object'); array_push($methods, 'main', 'initdb', 'initialize', 'loadTasks', 'startup', '_secret'); $Shell = $this->getMock('Object', $methods); $Shell->expects($this->never())->method('initialize'); $Shell->expects($this->once())->method('startup'); $Shell->expects($this->once())->method('main')->will($this->returnValue(true)); $Dispatcher->TestShell = $Shell; $Dispatcher->args = array('mock_without_main_not_a'); $result = $Dispatcher->dispatch(); $this->assertTrue($result); $this->assertEquals(array(), $Dispatcher->args); $Shell = $this->getMock('Object', $methods); $Shell->expects($this->once())->method('initdb')->will($this->returnValue(true)); $Shell->expects($this->once())->method('startup'); $Dispatcher->TestShell = $Shell; $Dispatcher->args = array('mock_without_main_not_a', 'initdb'); $result = $Dispatcher->dispatch(); $this->assertTrue($result); } /** * Verify shifting of arguments * * @return void */ public function testShiftArgs() { $Dispatcher = new TestShellDispatcher(); $Dispatcher->args = array('a', 'b', 'c'); $this->assertEquals('a', $Dispatcher->shiftArgs()); $this->assertSame($Dispatcher->args, array('b', 'c')); $Dispatcher->args = array('a' => 'b', 'c', 'd'); $this->assertEquals('b', $Dispatcher->shiftArgs()); $this->assertSame($Dispatcher->args, array('c', 'd')); $Dispatcher->args = array('a', 'b' => 'c', 'd'); $this->assertEquals('a', $Dispatcher->shiftArgs()); $this->assertSame($Dispatcher->args, array('b' => 'c', 'd')); $Dispatcher->args = array(0 => 'a', 2 => 'b', 30 => 'c'); $this->assertEquals('a', $Dispatcher->shiftArgs()); $this->assertSame($Dispatcher->args, array(0 => 'b', 1 => 'c')); $Dispatcher->args = array(); $this->assertNull($Dispatcher->shiftArgs()); $this->assertSame(array(), $Dispatcher->args); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/ShellTest.php000066400000000000000000000636701265552240500224030ustar00rootroot00000000000000stopped = $status; } protected function _secret() { } //@codingStandardsIgnoreStart public function do_something() { } protected function no_access() { } public function log_something() { $this->log($this->testMessage); } //@codingStandardsIgnoreEnd public function mergeVars($properties, $class, $normalize = true) { return $this->_mergeVars($properties, $class, $normalize); } public function useLogger($enable = true) { $this->_useLogger($enable); } } /** * Class for testing merging vars * * @package Cake.Test.Case.Console.Command */ class TestMergeShell extends Shell { public $tasks = array('DbConfig', 'Fixture'); public $uses = array('Comment'); } /** * TestAppleTask class * * @package Cake.Test.Case.Console.Command */ class TestAppleTask extends Shell { } /** * TestBananaTask class * * @package Cake.Test.Case.Console.Command */ class TestBananaTask extends Shell { } /** * ShellTest class * * @package Cake.Test.Case.Console.Command */ class ShellTest extends CakeTestCase { /** * Fixtures used in this test case * * @var array */ public $fixtures = array( 'core.post', 'core.comment', 'core.article', 'core.user', 'core.tag', 'core.articles_tag', 'core.attachment' ); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $output = $this->getMock('ConsoleOutput', array(), array(), '', false); $error = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Shell = new ShellTestShell($output, $error, $in); if (is_dir(TMP . 'shell_test')) { $Folder = new Folder(TMP . 'shell_test'); $Folder->delete(); } } /** * testConstruct method * * @return void */ public function testConstruct() { $this->assertEquals('ShellTestShell', $this->Shell->name); $this->assertInstanceOf('ConsoleInput', $this->Shell->stdin); $this->assertInstanceOf('ConsoleOutput', $this->Shell->stdout); $this->assertInstanceOf('ConsoleOutput', $this->Shell->stderr); } /** * test merging vars * * @return void */ public function testMergeVars() { $this->Shell->tasks = array('DbConfig' => array('one', 'two')); $this->Shell->uses = array('Posts'); $this->Shell->mergeVars(array('tasks'), 'TestMergeShell'); $this->Shell->mergeVars(array('uses'), 'TestMergeShell', false); $expected = array('DbConfig' => null, 'Fixture' => null, 'DbConfig' => array('one', 'two')); $this->assertEquals($expected, $this->Shell->tasks); $expected = array('Fixture' => null, 'DbConfig' => array('one', 'two')); $this->assertEquals($expected, Hash::normalize($this->Shell->tasks), 'Normalized results are wrong.'); $this->assertEquals(array('Comment', 'Posts'), $this->Shell->uses, 'Merged models are wrong.'); } /** * testInitialize method * * @return void */ public function testInitialize() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'Model' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); $this->Shell->tasks = array('DbConfig' => array('one', 'two')); $this->Shell->uses = array('TestPlugin.TestPluginPost'); $this->Shell->initialize(); $this->assertTrue(isset($this->Shell->TestPluginPost)); $this->assertInstanceOf('TestPluginPost', $this->Shell->TestPluginPost); $this->assertEquals('TestPluginPost', $this->Shell->modelClass); CakePlugin::unload('TestPlugin'); $this->Shell->uses = array('Comment'); $this->Shell->initialize(); $this->assertTrue(isset($this->Shell->Comment)); $this->assertInstanceOf('Comment', $this->Shell->Comment); $this->assertEquals('Comment', $this->Shell->modelClass); $this->assertInstanceOf('DbConfigTask', $this->Shell->DbConfig); App::build(); } /** * testLoadModel method * * @return void */ public function testLoadModel() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'Model' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS) ), App::RESET); $Shell = new TestMergeShell(); $this->assertEquals('Comment', $Shell->Comment->alias); $this->assertInstanceOf('Comment', $Shell->Comment); $this->assertEquals('Comment', $Shell->modelClass); CakePlugin::load('TestPlugin'); $this->Shell->loadModel('TestPlugin.TestPluginPost'); $this->assertTrue(isset($this->Shell->TestPluginPost)); $this->assertInstanceOf('TestPluginPost', $this->Shell->TestPluginPost); $this->assertEquals('TestPluginPost', $this->Shell->modelClass); CakePlugin::unload('TestPlugin'); App::build(); } /** * testIn method * * @return void */ public function testIn() { $this->Shell->stdin->expects($this->at(0)) ->method('read') ->will($this->returnValue('n')); $this->Shell->stdin->expects($this->at(1)) ->method('read') ->will($this->returnValue('Y')); $this->Shell->stdin->expects($this->at(2)) ->method('read') ->will($this->returnValue('y')); $this->Shell->stdin->expects($this->at(3)) ->method('read') ->will($this->returnValue('y')); $this->Shell->stdin->expects($this->at(4)) ->method('read') ->will($this->returnValue('y')); $this->Shell->stdin->expects($this->at(5)) ->method('read') ->will($this->returnValue('0')); $result = $this->Shell->in('Just a test?', array('y', 'n'), 'n'); $this->assertEquals('n', $result); $result = $this->Shell->in('Just a test?', array('y', 'n'), 'n'); $this->assertEquals('Y', $result); $result = $this->Shell->in('Just a test?', 'y,n', 'n'); $this->assertEquals('y', $result); $result = $this->Shell->in('Just a test?', 'y/n', 'n'); $this->assertEquals('y', $result); $result = $this->Shell->in('Just a test?', 'y', 'y'); $this->assertEquals('y', $result); $result = $this->Shell->in('Just a test?', array(0, 1, 2), '0'); $this->assertEquals('0', $result); } /** * Test in() when not interactive. * * @return void */ public function testInNonInteractive() { $this->Shell->interactive = false; $result = $this->Shell->in('Just a test?', 'y/n', 'n'); $this->assertEquals('n', $result); } /** * testOut method * * @return void */ public function testOut() { $this->Shell->stdout->expects($this->at(0)) ->method('write') ->with("Just a test", 1); $this->Shell->stdout->expects($this->at(1)) ->method('write') ->with(array('Just', 'a', 'test'), 1); $this->Shell->stdout->expects($this->at(2)) ->method('write') ->with(array('Just', 'a', 'test'), 2); $this->Shell->stdout->expects($this->at(3)) ->method('write') ->with('', 1); $this->Shell->out('Just a test'); $this->Shell->out(array('Just', 'a', 'test')); $this->Shell->out(array('Just', 'a', 'test'), 2); $this->Shell->out(); } /** * test that verbose and quiet output levels work * * @return void */ public function testVerboseOutput() { $this->Shell->stdout->expects($this->at(0))->method('write') ->with('Verbose', 1); $this->Shell->stdout->expects($this->at(1))->method('write') ->with('Normal', 1); $this->Shell->stdout->expects($this->at(2))->method('write') ->with('Quiet', 1); $this->Shell->params['verbose'] = true; $this->Shell->params['quiet'] = false; $this->Shell->out('Verbose', 1, Shell::VERBOSE); $this->Shell->out('Normal', 1, Shell::NORMAL); $this->Shell->out('Quiet', 1, Shell::QUIET); } /** * test that verbose and quiet output levels work * * @return void */ public function testQuietOutput() { $this->Shell->stdout->expects($this->once())->method('write') ->with('Quiet', 1); $this->Shell->params['verbose'] = false; $this->Shell->params['quiet'] = true; $this->Shell->out('Verbose', 1, Shell::VERBOSE); $this->Shell->out('Normal', 1, Shell::NORMAL); $this->Shell->out('Quiet', 1, Shell::QUIET); } /** * Test overwriting. * * @return void */ public function testOverwrite() { $number = strlen('Some text I want to overwrite'); $this->Shell->stdout->expects($this->at(0)) ->method('write') ->with('Some text I want to overwrite', 0) ->will($this->returnValue($number)); $this->Shell->stdout->expects($this->at(1)) ->method('write') ->with(str_repeat("\x08", $number), 0); $this->Shell->stdout->expects($this->at(2)) ->method('write') ->with('Less text', 0) ->will($this->returnValue(9)); $this->Shell->stdout->expects($this->at(3)) ->method('write') ->with(str_repeat(' ', $number - 9), 0); $this->Shell->out('Some text I want to overwrite', 0); $this->Shell->overwrite('Less text'); } /** * testErr method * * @return void */ public function testErr() { $this->Shell->stderr->expects($this->at(0)) ->method('write') ->with("Just a test", 1); $this->Shell->stderr->expects($this->at(1)) ->method('write') ->with(array('Just', 'a', 'test'), 1); $this->Shell->stderr->expects($this->at(2)) ->method('write') ->with(array('Just', 'a', 'test'), 2); $this->Shell->stderr->expects($this->at(3)) ->method('write') ->with('', 1); $this->Shell->err('Just a test'); $this->Shell->err(array('Just', 'a', 'test')); $this->Shell->err(array('Just', 'a', 'test'), 2); $this->Shell->err(); } /** * testNl * * @return void */ public function testNl() { $newLine = "\n"; if (DS === '\\') { $newLine = "\r\n"; } $this->assertEquals($this->Shell->nl(), $newLine); $this->assertEquals($this->Shell->nl(true), $newLine); $this->assertEquals("", $this->Shell->nl(false)); $this->assertEquals($this->Shell->nl(2), $newLine . $newLine); $this->assertEquals($this->Shell->nl(1), $newLine); } /** * testHr * * @return void */ public function testHr() { $bar = '---------------------------------------------------------------'; $this->Shell->stdout->expects($this->at(0))->method('write')->with('', 0); $this->Shell->stdout->expects($this->at(1))->method('write')->with($bar, 1); $this->Shell->stdout->expects($this->at(2))->method('write')->with('', 0); $this->Shell->stdout->expects($this->at(3))->method('write')->with("", true); $this->Shell->stdout->expects($this->at(4))->method('write')->with($bar, 1); $this->Shell->stdout->expects($this->at(5))->method('write')->with("", true); $this->Shell->stdout->expects($this->at(6))->method('write')->with("", 2); $this->Shell->stdout->expects($this->at(7))->method('write')->with($bar, 1); $this->Shell->stdout->expects($this->at(8))->method('write')->with("", 2); $this->Shell->hr(); $this->Shell->hr(true); $this->Shell->hr(2); } /** * testError * * @return void */ public function testError() { $this->Shell->stderr->expects($this->at(0)) ->method('write') ->with("Error: Foo Not Found", 1); $this->Shell->stderr->expects($this->at(1)) ->method('write') ->with("Error: Foo Not Found", 1); $this->Shell->stderr->expects($this->at(2)) ->method('write') ->with("Searched all...", 1); $this->Shell->error('Foo Not Found'); $this->assertSame($this->Shell->stopped, 1); $this->Shell->stopped = null; $this->Shell->error('Foo Not Found', 'Searched all...'); $this->assertSame($this->Shell->stopped, 1); } /** * testLoadTasks method * * @return void */ public function testLoadTasks() { $this->assertTrue($this->Shell->loadTasks()); $this->Shell->tasks = null; $this->assertTrue($this->Shell->loadTasks()); $this->Shell->tasks = false; $this->assertTrue($this->Shell->loadTasks()); $this->Shell->tasks = true; $this->assertTrue($this->Shell->loadTasks()); $this->Shell->tasks = array(); $this->assertTrue($this->Shell->loadTasks()); $this->Shell->tasks = array('TestApple'); $this->assertTrue($this->Shell->loadTasks()); $this->assertInstanceOf('TestAppleTask', $this->Shell->TestApple); $this->Shell->tasks = 'TestBanana'; $this->assertTrue($this->Shell->loadTasks()); $this->assertInstanceOf('TestAppleTask', $this->Shell->TestApple); $this->assertInstanceOf('TestBananaTask', $this->Shell->TestBanana); unset($this->Shell->ShellTestApple, $this->Shell->TestBanana); $this->Shell->tasks = array('TestApple', 'TestBanana'); $this->assertTrue($this->Shell->loadTasks()); $this->assertInstanceOf('TestAppleTask', $this->Shell->TestApple); $this->assertInstanceOf('TestBananaTask', $this->Shell->TestBanana); } /** * test that __get() makes args and params references * * @return void */ public function testMagicGetArgAndParamReferences() { $this->Shell->tasks = array('TestApple'); $this->Shell->args = array('one'); $this->Shell->params = array('help' => false); $this->Shell->loadTasks(); $result = $this->Shell->TestApple; $this->Shell->args = array('one', 'two'); $this->assertSame($this->Shell->args, $result->args); $this->assertSame($this->Shell->params, $result->params); } /** * testShortPath method * * @return void */ public function testShortPath() { $path = $expected = DS . 'tmp' . DS . 'ab' . DS . 'cd'; $this->assertEquals($expected, $this->Shell->shortPath($path)); $path = $expected = DS . 'tmp' . DS . 'ab' . DS . 'cd' . DS; $this->assertEquals($expected, $this->Shell->shortPath($path)); $path = $expected = DS . 'tmp' . DS . 'ab' . DS . 'index.php'; $this->assertEquals($expected, $this->Shell->shortPath($path)); $path = DS . 'tmp' . DS . 'ab' . DS . DS . 'cd'; $expected = DS . 'tmp' . DS . 'ab' . DS . 'cd'; $this->assertEquals($expected, $this->Shell->shortPath($path)); $path = 'tmp' . DS . 'ab'; $expected = 'tmp' . DS . 'ab'; $this->assertEquals($expected, $this->Shell->shortPath($path)); $path = 'tmp' . DS . 'ab'; $expected = 'tmp' . DS . 'ab'; $this->assertEquals($expected, $this->Shell->shortPath($path)); $path = APP; $expected = DS . basename(APP) . DS; $this->assertEquals($expected, $this->Shell->shortPath($path)); $path = APP . 'index.php'; $expected = DS . basename(APP) . DS . 'index.php'; $this->assertEquals($expected, $this->Shell->shortPath($path)); } /** * testCreateFile method * * @return void */ public function testCreateFileNonInteractive() { $eol = PHP_EOL; $path = TMP . 'shell_test'; $file = $path . DS . 'file1.php'; new Folder($path, true); $this->Shell->interactive = false; $contents = "Shell->createFile($file, $contents); $this->assertTrue($result); $this->assertTrue(file_exists($file)); $this->assertEquals(file_get_contents($file), $contents); $contents = "Shell->createFile($file, $contents); $this->assertTrue($result); $this->assertTrue(file_exists($file)); $this->assertTextEquals(file_get_contents($file), $contents); } /** * test createFile when the shell is interactive. * * @return void */ public function testCreateFileInteractive() { $eol = PHP_EOL; $path = TMP . 'shell_test'; $file = $path . DS . 'file1.php'; new Folder($path, true); $this->Shell->interactive = true; $this->Shell->stdin->expects($this->at(0)) ->method('read') ->will($this->returnValue('n')); $this->Shell->stdin->expects($this->at(1)) ->method('read') ->will($this->returnValue('y')); $contents = "Shell->createFile($file, $contents); $this->assertTrue($result); $this->assertTrue(file_exists($file)); $this->assertEquals(file_get_contents($file), $contents); // no overwrite $contents = 'new contents'; $result = $this->Shell->createFile($file, $contents); $this->assertFalse($result); $this->assertTrue(file_exists($file)); $this->assertNotEquals($contents, file_get_contents($file)); // overwrite $contents = 'more new contents'; $result = $this->Shell->createFile($file, $contents); $this->assertTrue($result); $this->assertTrue(file_exists($file)); $this->assertEquals($contents, file_get_contents($file)); } /** * Test that you can't create files that aren't writable. * * @return void */ public function testCreateFileNoPermissions() { $this->skipIf(DIRECTORY_SEPARATOR === '\\', 'Cant perform operations using permissions on Windows.'); $path = TMP . 'shell_test'; $file = $path . DS . 'no_perms'; if (!is_dir($path)) { mkdir($path); } chmod($path, 0444); $this->Shell->createFile($file, 'testing'); $this->assertFalse(file_exists($file)); chmod($path, 0744); rmdir($path); } /** * test hasTask method * * @return void */ public function testHasTask() { $this->Shell->tasks = array('Extract', 'DbConfig'); $this->Shell->loadTasks(); $this->assertTrue($this->Shell->hasTask('extract')); $this->assertTrue($this->Shell->hasTask('Extract')); $this->assertFalse($this->Shell->hasTask('random')); $this->assertTrue($this->Shell->hasTask('db_config')); $this->assertTrue($this->Shell->hasTask('DbConfig')); } /** * test the hasMethod * * @return void */ public function testHasMethod() { $this->assertTrue($this->Shell->hasMethod('do_something')); $this->assertFalse($this->Shell->hasMethod('hr'), 'hr is callable'); $this->assertFalse($this->Shell->hasMethod('_secret'), '_secret is callable'); $this->assertFalse($this->Shell->hasMethod('no_access'), 'no_access is callable'); } /** * test run command calling main. * * @return void */ public function testRunCommandMain() { $Mock = $this->getMock('Shell', array('main', 'startup'), array(), '', false); $Mock->expects($this->once())->method('main')->will($this->returnValue(true)); $result = $Mock->runCommand(null, array()); $this->assertTrue($result); } /** * test run command calling a legit method. * * @return void */ public function testRunCommandWithMethod() { $Mock = $this->getMock('Shell', array('hit_me', 'startup'), array(), '', false); $Mock->expects($this->once())->method('hit_me')->will($this->returnValue(true)); $result = $Mock->runCommand('hit_me', array()); $this->assertTrue($result); } /** * test run command causing exception on Shell method. * * @return void */ public function testRunCommandBaseclassMethod() { $Mock = $this->getMock('Shell', array('startup', 'getOptionParser', 'out'), array(), '', false); $Parser = $this->getMock('ConsoleOptionParser', array(), array(), '', false); $Parser->expects($this->once())->method('help'); $Mock->expects($this->once())->method('getOptionParser') ->will($this->returnValue($Parser)); $Mock->expects($this->never())->method('hr'); $Mock->expects($this->once())->method('out'); $Mock->runCommand('hr', array()); } /** * test run command causing exception on Shell method. * * @return void */ public function testRunCommandMissingMethod() { $Mock = $this->getMock('Shell', array('startup', 'getOptionParser', 'out'), array(), '', false); $Parser = $this->getMock('ConsoleOptionParser', array(), array(), '', false); $Parser->expects($this->once())->method('help'); $Mock->expects($this->never())->method('idontexist'); $Mock->expects($this->once())->method('getOptionParser') ->will($this->returnValue($Parser)); $Mock->expects($this->once())->method('out'); $result = $Mock->runCommand('idontexist', array()); $this->assertFalse($result); } /** * test that a --help causes help to show. * * @return void */ public function testRunCommandTriggeringHelp() { $Parser = $this->getMock('ConsoleOptionParser', array(), array(), '', false); $Parser->expects($this->once())->method('parse') ->with(array('--help')) ->will($this->returnValue(array(array('help' => true), array()))); $Parser->expects($this->once())->method('help'); $Shell = $this->getMock('Shell', array('getOptionParser', 'out', 'startup', '_welcome'), array(), '', false); $Shell->expects($this->once())->method('getOptionParser') ->will($this->returnValue($Parser)); $Shell->expects($this->once())->method('out'); $Shell->runCommand(null, array('--help')); } /** * test that runCommand will call runCommand on the task. * * @return void */ public function testRunCommandHittingTask() { $Shell = $this->getMock('Shell', array('hasTask', 'startup'), array(), '', false); $task = $this->getMock('Shell', array('execute', 'runCommand'), array(), '', false); $task->expects($this->any()) ->method('runCommand') ->with('execute', array('one', 'value')); $Shell->expects($this->once())->method('startup'); $Shell->expects($this->any()) ->method('hasTask') ->will($this->returnValue(true)); $Shell->RunCommand = $task; $Shell->runCommand('run_command', array('run_command', 'one', 'value')); } /** * test wrapBlock wrapping text. * * @return void */ public function testWrapText() { $text = 'This is the song that never ends. This is the song that never ends. This is the song that never ends.'; $result = $this->Shell->wrapText($text, 33); $expected = <<assertTextEquals($expected, $result, 'Text not wrapped.'); $result = $this->Shell->wrapText($text, array('indent' => ' ', 'width' => 33)); $expected = <<assertTextEquals($expected, $result, 'Text not wrapped.'); } /** * Testing camel cased naming of tasks * * @return void */ public function testShellNaming() { $this->Shell->tasks = array('TestApple'); $this->Shell->loadTasks(); $expected = 'TestApple'; $this->assertEquals($expected, $this->Shell->TestApple->name); } /** * Test reading params * * @dataProvider paramReadingDataProvider */ public function testParamReading($toRead, $expected) { $this->Shell->params = array( 'key' => 'value', 'help' => false, 'emptykey' => '', 'truthy' => true ); $this->assertSame($expected, $this->Shell->param($toRead)); } /** * Data provider for testing reading values with Shell::param() * * @return array */ public function paramReadingDataProvider() { return array( array( 'key', 'value', ), array( 'help', false, ), array( 'emptykey', '', ), array( 'truthy', true, ), array( 'does_not_exist', null, ) ); } /** * Test that option parsers are created with the correct name/command. * * @return void */ public function testGetOptionParser() { $this->Shell->name = 'test'; $this->Shell->plugin = 'plugin'; $parser = $this->Shell->getOptionParser(); $this->assertEquals('plugin.test', $parser->command()); } /** * Test file and console and logging * * @return void */ public function testFileAndConsoleLogging() { // file logging $this->Shell->log_something(); $this->assertTrue(file_exists(LOGS . 'error.log')); unlink(LOGS . 'error.log'); $this->assertFalse(file_exists(LOGS . 'error.log')); // both file and console logging require_once CORE_TEST_CASES . DS . 'Log' . DS . 'Engine' . DS . 'ConsoleLogTest.php'; $mock = $this->getMock('ConsoleLog', array('write'), array( array('types' => 'error'), )); TestCakeLog::config('console', array( 'engine' => 'Console', 'stream' => 'php://stderr', )); TestCakeLog::replace('console', $mock); $mock->expects($this->once()) ->method('write') ->with('error', $this->Shell->testMessage); $this->Shell->log_something(); $this->assertTrue(file_exists(LOGS . 'error.log')); $contents = file_get_contents(LOGS . 'error.log'); $this->assertContains($this->Shell->testMessage, $contents); } /** * Tests that _useLogger works properly * * @return void */ public function testProtectedUseLogger() { CakeLog::drop('stdout'); CakeLog::drop('stderr'); $this->Shell->useLogger(true); $this->assertNotEmpty(CakeLog::stream('stdout')); $this->assertNotEmpty(CakeLog::stream('stderr')); $this->Shell->useLogger(false); $this->assertFalse(CakeLog::stream('stdout')); $this->assertFalse(CakeLog::stream('stderr')); } /** * Test file and console and logging quiet output * * @return void */ public function testQuietLog() { $output = $this->getMock('ConsoleOutput', array(), array(), '', false); $error = $this->getMock('ConsoleOutput', array(), array(), '', false); $in = $this->getMock('ConsoleInput', array(), array(), '', false); $this->Shell = $this->getMock('ShellTestShell', array('_useLogger'), array($output, $error, $in)); $this->Shell->expects($this->once())->method('_useLogger')->with(false); $this->Shell->runCommand('foo', array('--quiet')); } /** * Test getting an instance of a helper * * @return void */ public function testGetInstanceOfHelper() { $actual = $this->Shell->helper("progress"); $this->assertInstanceOf("ProgressShellHelper", $actual); } /** * Test getting an invalid helper * * @expectedException RunTimeException * @return void */ public function testGetInvalidHelper() { $this->Shell->helper("tomato"); } } cakephp-2.8.0/lib/Cake/Test/Case/Console/TaskCollectionTest.php000066400000000000000000000104071265552240500242400ustar00rootroot00000000000000getMock('Shell', array(), array(), '', false); $dispatcher = $this->getMock('ShellDispatcher', array(), array(), '', false); $this->Tasks = new TaskCollection($shell, $dispatcher); } /** * tearDown * * @return void */ public function tearDown() { unset($this->Tasks); parent::tearDown(); } /** * test triggering callbacks on loaded tasks * * @return void */ public function testLoad() { $result = $this->Tasks->load('DbConfig'); $this->assertInstanceOf('DbConfigTask', $result); $this->assertInstanceOf('DbConfigTask', $this->Tasks->DbConfig); $result = $this->Tasks->loaded(); $this->assertEquals(array('DbConfig'), $result, 'loaded() results are wrong.'); } /** * test load and enable = false * * @return void */ public function testLoadWithEnableFalse() { $result = $this->Tasks->load('DbConfig', array('enabled' => false)); $this->assertInstanceOf('DbConfigTask', $result); $this->assertInstanceOf('DbConfigTask', $this->Tasks->DbConfig); $this->assertFalse($this->Tasks->enabled('DbConfig'), 'DbConfigTask should be disabled'); } /** * test missingtask exception * * @expectedException MissingTaskException * @return void */ public function testLoadMissingTask() { $this->Tasks->load('ThisTaskShouldAlwaysBeMissing'); } /** * test loading a plugin helper. * * @return void */ public function testLoadPluginTask() { $dispatcher = $this->getMock('ShellDispatcher', array(), array(), '', false); $shell = $this->getMock('Shell', array(), array(), '', false); App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); CakePlugin::load('TestPlugin'); $this->Tasks = new TaskCollection($shell, $dispatcher); $result = $this->Tasks->load('TestPlugin.OtherTask'); $this->assertInstanceOf('OtherTaskTask', $result, 'Task class is wrong.'); $this->assertInstanceOf('OtherTaskTask', $this->Tasks->OtherTask, 'Class is wrong'); CakePlugin::unload(); } /** * test unload() * * @return void */ public function testUnload() { $this->Tasks->load('Extract'); $this->Tasks->load('DbConfig'); $result = $this->Tasks->loaded(); $this->assertEquals(array('Extract', 'DbConfig'), $result, 'loaded tasks is wrong'); $this->Tasks->unload('DbConfig'); $this->assertFalse(isset($this->Tasks->DbConfig)); $this->assertTrue(isset($this->Tasks->Extract)); $result = $this->Tasks->loaded(); $this->assertEquals(array('Extract'), $result, 'loaded tasks is wrong'); } /** * Tests loading as an alias * * @return void */ public function testLoadWithAlias() { $result = $this->Tasks->load('DbConfig', array('className' => 'DbConfigAliased')); $this->assertInstanceOf('DbConfigAliasedTask', $result); $this->assertInstanceOf('DbConfigAliasedTask', $this->Tasks->DbConfig); $result = $this->Tasks->loaded(); $this->assertEquals(array('DbConfig'), $result, 'loaded() results are wrong.'); $result = $this->Tasks->load('SomeTask', array('className' => 'TestPlugin.OtherTask')); $this->assertInstanceOf('OtherTaskTask', $result); $this->assertInstanceOf('OtherTaskTask', $this->Tasks->SomeTask); $result = $this->Tasks->loaded(); $this->assertEquals(array('DbConfig', 'SomeTask'), $result, 'loaded() results are wrong.'); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/000077500000000000000000000000001265552240500204705ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/000077500000000000000000000000001265552240500224325ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/Acl/000077500000000000000000000000001265552240500231315ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/Acl/DbAclTest.php000066400000000000000000000375051265552240500254610ustar00rootroot00000000000000 array('with' => 'PermissionTwoTest')); } /** * AcoTwoTest class * * @package Cake.Test.Case.Controller.Component.Acl */ class AcoTwoTest extends AclNodeTwoTestBase { /** * name property * * @var string */ public $name = 'AcoTwoTest'; /** * useTable property * * @var string */ public $useTable = 'aco_twos'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('AroTwoTest' => array('with' => 'PermissionTwoTest')); } /** * PermissionTwoTest class * * @package Cake.Test.Case.Controller.Component.Acl */ class PermissionTwoTest extends Permission { /** * name property * * @var string */ public $name = 'PermissionTwoTest'; /** * useTable property * * @var string */ public $useTable = 'aros_aco_twos'; /** * cacheQueries property * * @var bool */ public $cacheQueries = false; /** * belongsTo property * * @var array */ public $belongsTo = array('AroTwoTest' => array('foreignKey' => 'aro_id'), 'AcoTwoTest' => array('foreignKey' => 'aco_id')); /** * actsAs property * * @var mixed */ public $actsAs = null; } /** * DbAclTwoTest class * * @package Cake.Test.Case.Controller.Component.Acl */ class DbAclTwoTest extends DbAcl { /** * construct method */ public function __construct() { $this->Aro = new AroTwoTest(); $this->Aro->Permission = new PermissionTwoTest(); $this->Aco = new AcoTwoTest(); $this->Aro->Permission = new PermissionTwoTest(); $this->Permission = $this->Aro->Permission; $this->Permission->Aro = $this->Aro; $this->Permission->Aco = $this->Aco; } } /** * Test case for AclComponent using the DbAcl implementation. * * @package Cake.Test.Case.Controller.Component.Acl */ class DbAclTest extends CakeTestCase { /** * fixtures property * * @var array */ public $fixtures = array('core.aro_two', 'core.aco_two', 'core.aros_aco_two'); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); Configure::write('Acl.classname', 'DbAclTwoTest'); Configure::write('Acl.database', 'test'); $Collection = new ComponentCollection(); $this->Acl = new AclComponent($Collection); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Acl); } /** * testAclCreate method * * @return void */ public function testCreate() { $this->Acl->Aro->create(array('alias' => 'Chotchkey')); $this->assertTrue((bool)$this->Acl->Aro->save()); $parent = $this->Acl->Aro->id; $this->Acl->Aro->create(array('parent_id' => $parent, 'alias' => 'Joanna')); $this->assertTrue((bool)$this->Acl->Aro->save()); $this->Acl->Aro->create(array('parent_id' => $parent, 'alias' => 'Stapler')); $this->assertTrue((bool)$this->Acl->Aro->save()); $root = $this->Acl->Aco->node('ROOT'); $parent = $root[0]['AcoTwoTest']['id']; $this->Acl->Aco->create(array('parent_id' => $parent, 'alias' => 'Drinks')); $this->assertTrue((bool)$this->Acl->Aco->save()); $this->Acl->Aco->create(array('parent_id' => $parent, 'alias' => 'PiecesOfFlair')); $this->assertTrue((bool)$this->Acl->Aco->save()); } /** * testAclCreateWithParent method * * @return void */ public function testCreateWithParent() { $parent = $this->Acl->Aro->findByAlias('Peter', null, null, -1); $this->Acl->Aro->create(); $this->Acl->Aro->save(array( 'alias' => 'Subordinate', 'model' => 'User', 'foreign_key' => 7, 'parent_id' => $parent['AroTwoTest']['id'] )); $result = $this->Acl->Aro->findByAlias('Subordinate', null, null, -1); $this->assertEquals(16, $result['AroTwoTest']['lft']); $this->assertEquals(17, $result['AroTwoTest']['rght']); } /** * testDbAclAllow method * * @return void */ public function testAllow() { $this->assertFalse($this->Acl->check('Micheal', 'tpsReports', 'read')); $this->assertTrue($this->Acl->allow('Micheal', 'tpsReports', array('read', 'delete', 'update'))); $this->assertTrue($this->Acl->check('Micheal', 'tpsReports', 'update')); $this->assertTrue($this->Acl->check('Micheal', 'tpsReports', 'read')); $this->assertTrue($this->Acl->check('Micheal', 'tpsReports', 'delete')); $this->assertFalse($this->Acl->check('Micheal', 'tpsReports', 'create')); $this->assertTrue($this->Acl->allow('Micheal', 'ROOT/tpsReports', 'create')); $this->assertTrue($this->Acl->check('Micheal', 'tpsReports', 'create')); $this->assertTrue($this->Acl->check('Micheal', 'tpsReports', 'delete')); $this->assertTrue($this->Acl->allow('Micheal', 'printers', 'create')); // Michael no longer has his delete permission for tpsReports! $this->assertTrue($this->Acl->check('Micheal', 'tpsReports', 'delete')); $this->assertTrue($this->Acl->check('Micheal', 'printers', 'create')); $this->assertFalse($this->Acl->check('root/users/Samir', 'ROOT/tpsReports/view')); $this->assertTrue($this->Acl->allow('root/users/Samir', 'ROOT/tpsReports/view', '*')); $this->assertTrue($this->Acl->check('Samir', 'view', 'read')); $this->assertTrue($this->Acl->check('root/users/Samir', 'ROOT/tpsReports/view', 'update')); $this->assertFalse($this->Acl->check('root/users/Samir', 'ROOT/tpsReports/update', '*')); $this->assertTrue($this->Acl->allow('root/users/Samir', 'ROOT/tpsReports/update', '*')); $this->assertTrue($this->Acl->check('Samir', 'update', 'read')); $this->assertTrue($this->Acl->check('root/users/Samir', 'ROOT/tpsReports/update', 'update')); // Samir should still have his tpsReports/view permissions, but does not $this->assertTrue($this->Acl->check('root/users/Samir', 'ROOT/tpsReports/view', 'update')); $this->assertFalse($this->Acl->allow('Lumbergh', 'ROOT/tpsReports/DoesNotExist', 'create')); } /** * Test that allow() with an invalid permission name triggers an error. * * @expectedException CakeException * @return void */ public function testAllowInvalidPermission() { $this->assertFalse($this->Acl->allow('Micheal', 'tpsReports', 'derp')); } /** * testAllowInvalidNode method * * @return void */ public function testAllowInvalidNode() { $this->assertFalse($this->Acl->allow('Homer', 'tpsReports', 'create')); } /** * testDbAclCheck method * * @return void */ public function testCheck() { $this->assertTrue($this->Acl->check('Samir', 'print', 'read')); $this->assertTrue($this->Acl->check('Lumbergh', 'current', 'read')); $this->assertFalse($this->Acl->check('Milton', 'smash', 'read')); $this->assertFalse($this->Acl->check('Milton', 'current', 'update')); $this->assertFalse($this->Acl->check(null, 'printers', 'create')); $this->assertFalse($this->Acl->check('managers', null, 'read')); $this->assertTrue($this->Acl->check('Bobs', 'ROOT/tpsReports/view/current', 'read')); $this->assertFalse($this->Acl->check('Samir', 'ROOT/tpsReports/update', 'read')); $this->assertFalse($this->Acl->check('root/users/Milton', 'smash', 'delete')); } /** * testCheckInvalidNode method * * @return void */ public function testCheckInvalidNode() { $this->assertFalse($this->Acl->check('WRONG', 'tpsReports', 'read')); } /** * testCheckInvalidPermission method * * @return void */ public function testCheckInvalidPermission() { $this->assertFalse($this->Acl->check('Lumbergh', 'smash', 'foobar')); } /** * testCheckMissingPermission method * * @return void */ public function testCheckMissingPermission() { $this->assertFalse($this->Acl->check('users', 'NonExistent', 'read')); } /** * testDbAclCascadingDeny function * * Setup the acl permissions such that Bobs inherits from admin. * deny Admin delete access to a specific resource, check the permissions are inherited. * * @return void */ public function testAclCascadingDeny() { $this->Acl->inherit('Bobs', 'ROOT', '*'); $this->assertTrue($this->Acl->check('admin', 'tpsReports', 'delete')); $this->assertTrue($this->Acl->check('Bobs', 'tpsReports', 'delete')); $this->Acl->deny('admin', 'tpsReports', 'delete'); $this->assertFalse($this->Acl->check('admin', 'tpsReports', 'delete')); $this->assertFalse($this->Acl->check('Bobs', 'tpsReports', 'delete')); } /** * testDbAclDeny method * * @return void */ public function testDeny() { $this->assertTrue($this->Acl->check('Micheal', 'smash', 'delete')); $this->Acl->deny('Micheal', 'smash', 'delete'); $this->assertFalse($this->Acl->check('Micheal', 'smash', 'delete')); $this->assertTrue($this->Acl->check('Micheal', 'smash', 'read')); $this->assertTrue($this->Acl->check('Micheal', 'smash', 'create')); $this->assertTrue($this->Acl->check('Micheal', 'smash', 'update')); $this->assertFalse($this->Acl->check('Micheal', 'smash', '*')); $this->assertTrue($this->Acl->check('Samir', 'refill', '*')); $this->Acl->deny('Samir', 'refill', '*'); $this->assertFalse($this->Acl->check('Samir', 'refill', 'create')); $this->assertFalse($this->Acl->check('Samir', 'refill', 'update')); $this->assertFalse($this->Acl->check('Samir', 'refill', 'read')); $this->assertFalse($this->Acl->check('Samir', 'refill', 'delete')); $result = $this->Acl->Aro->Permission->find('all', array('conditions' => array('AroTwoTest.alias' => 'Samir'))); $expected = '-1'; $this->assertEquals($expected, $result[0]['PermissionTwoTest']['_delete']); $this->assertFalse($this->Acl->deny('Lumbergh', 'ROOT/tpsReports/DoesNotExist', 'create')); } /** * testAclNodeLookup method * * @return void */ public function testAclNodeLookup() { $result = $this->Acl->Aro->node('root/users/Samir'); $expected = array( array('AroTwoTest' => array('id' => '7', 'parent_id' => '4', 'model' => 'User', 'foreign_key' => 3, 'alias' => 'Samir')), array('AroTwoTest' => array('id' => '4', 'parent_id' => '1', 'model' => 'Group', 'foreign_key' => 3, 'alias' => 'users')), array('AroTwoTest' => array('id' => '1', 'parent_id' => null, 'model' => null, 'foreign_key' => null, 'alias' => 'root')) ); $this->assertEquals($expected, $result); $result = $this->Acl->Aco->node('ROOT/tpsReports/view/current'); $expected = array( array('AcoTwoTest' => array('id' => '4', 'parent_id' => '3', 'model' => null, 'foreign_key' => null, 'alias' => 'current')), array('AcoTwoTest' => array('id' => '3', 'parent_id' => '2', 'model' => null, 'foreign_key' => null, 'alias' => 'view')), array('AcoTwoTest' => array('id' => '2', 'parent_id' => '1', 'model' => null, 'foreign_key' => null, 'alias' => 'tpsReports')), array('AcoTwoTest' => array('id' => '1', 'parent_id' => null, 'model' => null, 'foreign_key' => null, 'alias' => 'ROOT')), ); $this->assertEquals($expected, $result); } /** * testDbInherit method * * @return void */ public function testInherit() { //parent doesn't have access inherit should still deny $this->assertFalse($this->Acl->check('Milton', 'smash', 'delete')); $this->Acl->inherit('Milton', 'smash', 'delete'); $this->assertFalse($this->Acl->check('Milton', 'smash', 'delete')); //inherit parent $this->assertFalse($this->Acl->check('Milton', 'smash', 'read')); $this->Acl->inherit('Milton', 'smash', 'read'); $this->assertTrue($this->Acl->check('Milton', 'smash', 'read')); } /** * testDbGrant method * * @return void */ public function testGrant() { $this->assertFalse($this->Acl->check('Samir', 'tpsReports', 'create')); $this->Acl->allow('Samir', 'tpsReports', 'create'); $this->assertTrue($this->Acl->check('Samir', 'tpsReports', 'create')); $this->assertFalse($this->Acl->check('Micheal', 'view', 'read')); $this->Acl->allow('Micheal', 'view', array('read', 'create', 'update')); $this->assertTrue($this->Acl->check('Micheal', 'view', 'read')); $this->assertTrue($this->Acl->check('Micheal', 'view', 'create')); $this->assertTrue($this->Acl->check('Micheal', 'view', 'update')); $this->assertFalse($this->Acl->check('Micheal', 'view', 'delete')); $this->assertFalse($this->Acl->allow('Peter', 'ROOT/tpsReports/DoesNotExist', 'create')); } /** * testDbRevoke method * * @return void */ public function testRevoke() { $this->assertTrue($this->Acl->check('Bobs', 'tpsReports', 'read')); $this->Acl->deny('Bobs', 'tpsReports', 'read'); $this->assertFalse($this->Acl->check('Bobs', 'tpsReports', 'read')); $this->assertTrue($this->Acl->check('users', 'printers', 'read')); $this->Acl->deny('users', 'printers', 'read'); $this->assertFalse($this->Acl->check('users', 'printers', 'read')); $this->assertFalse($this->Acl->check('Samir', 'printers', 'read')); $this->assertFalse($this->Acl->check('Peter', 'printers', 'read')); $this->Acl->deny('Bobs', 'ROOT/printers/DoesNotExist', 'create'); } /** * debug function - to help editing/creating test cases for the ACL component * * To check the overall ACL status at any time call $this->_debug(); * Generates a list of the current aro and aco structures and a grid dump of the permissions that are defined * Only designed to work with the db based ACL * * @param bool $treesToo * @return void */ protected function _debug($printTreesToo = false) { $this->Acl->Aro->displayField = 'alias'; $this->Acl->Aco->displayField = 'alias'; $aros = $this->Acl->Aro->find('list', array('order' => 'lft')); $acos = $this->Acl->Aco->find('list', array('order' => 'lft')); $rights = array('*', 'create', 'read', 'update', 'delete'); $permissions['Aros v Acos >'] = $acos; foreach ($aros as $aro) { $row = array(); foreach ($acos as $aco) { $perms = ''; foreach ($rights as $right) { if ($this->Acl->check($aro, $aco, $right)) { if ($right === '*') { $perms .= '****'; break; } $perms .= $right[0]; } elseif ($right !== '*') { $perms .= ' '; } } $row[] = $perms; } $permissions[$aro] = $row; } foreach ($permissions as $key => $values) { array_unshift($values, $key); $values = array_map(array(&$this, '_pad'), $values); $permissions[$key] = implode(' ', $values); } $permissions = array_map(array(&$this, '_pad'), $permissions); array_unshift($permissions, 'Current Permissions :'); if ($printTreesToo) { debug(array('aros' => $this->Acl->Aro->generateTreeList(), 'acos' => $this->Acl->Aco->generateTreeList())); } debug(implode("\r\n", $permissions)); } /** * pad function * Used by debug to format strings used in the data dump * * @param string $string * @param int $len * @return void */ protected function _pad($string = '', $len = 14) { return str_pad($string, $len); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/Acl/IniAclTest.php000066400000000000000000000035641265552240500256510ustar00rootroot00000000000000config = $Ini->readConfigFile($iniFile); $this->assertFalse($Ini->check('admin', 'ads')); $this->assertTrue($Ini->check('admin', 'posts')); $this->assertTrue($Ini->check('jenny', 'posts')); $this->assertTrue($Ini->check('jenny', 'ads')); $this->assertTrue($Ini->check('paul', 'posts')); $this->assertFalse($Ini->check('paul', 'ads')); $this->assertFalse($Ini->check('nobody', 'comments')); } /** * check should accept a user array. * * @return void */ public function testCheckArray() { $iniFile = CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'acl.ini.php'; $Ini = new IniAcl(); $Ini->config = $Ini->readConfigFile($iniFile); $Ini->userPath = 'User.username'; $user = array( 'User' => array('username' => 'admin') ); $this->assertTrue($Ini->check($user, 'posts')); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/Acl/PhpAclTest.php000066400000000000000000000333151265552240500256560ustar00rootroot00000000000000PhpAcl = new PhpAcl(); $this->Acl = new AclComponent($Collection, array( 'adapter' => array( 'config' => CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'acl.php', ), )); } /** * Test role inheritance * * @return void */ public function testRoleInheritance() { $roles = $this->Acl->Aro->roles('User/peter'); $this->assertEquals(array('Role/accounting'), $roles[0]); $this->assertEquals(array('User/peter'), $roles[1]); $roles = $this->Acl->Aro->roles('hardy'); $this->assertEquals(array('Role/database_manager', 'Role/data_acquirer'), $roles[0]); $this->assertEquals(array('Role/accounting', 'Role/data_analyst'), $roles[1]); $this->assertEquals(array('Role/accounting_manager', 'Role/reports'), $roles[2]); $this->assertEquals(array('User/hardy'), $roles[3]); } /** * Test adding a role * * @return void */ public function testAddRole() { $this->assertEquals(array(array(PhpAro::DEFAULT_ROLE)), $this->Acl->Aro->roles('foobar')); $this->Acl->Aro->addRole(array('User/foobar' => 'Role/accounting')); $this->assertEquals(array(array('Role/accounting'), array('User/foobar')), $this->Acl->Aro->roles('foobar')); } /** * Test resolving ARO * * @return void */ public function testAroResolve() { $this->Acl->Aro->map = array( 'User' => 'FooModel/nickname', 'Role' => 'FooModel/role', ); $this->assertEquals('Role/default', $this->Acl->Aro->resolve('Foo.bar')); $this->assertEquals('User/hardy', $this->Acl->Aro->resolve('FooModel/hardy')); $this->assertEquals('User/hardy', $this->Acl->Aro->resolve('hardy')); $this->assertEquals('User/hardy', $this->Acl->Aro->resolve(array('FooModel' => array('nickname' => 'hardy')))); $this->assertEquals('Role/admin', $this->Acl->Aro->resolve(array('FooModel' => array('role' => 'admin')))); $this->assertEquals('Role/admin', $this->Acl->Aro->resolve('Role/admin')); $this->assertEquals('Role/admin', $this->Acl->Aro->resolve('admin')); $this->assertEquals('Role/admin', $this->Acl->Aro->resolve('FooModel/admin')); $this->assertEquals('Role/accounting', $this->Acl->Aro->resolve('accounting')); $this->assertEquals(PhpAro::DEFAULT_ROLE, $this->Acl->Aro->resolve('bla')); $this->assertEquals(PhpAro::DEFAULT_ROLE, $this->Acl->Aro->resolve(array('FooModel' => array('role' => 'hardy')))); } /** * test correct resolution of defined aliases * * @return void */ public function testAroAliases() { $this->Acl->Aro->map = array( 'User' => 'User/username', 'Role' => 'User/group_id', ); $this->Acl->Aro->aliases = array( 'Role/1' => 'Role/admin', 'Role/24' => 'Role/accounting', ); $user = array( 'User' => array( 'username' => 'unknown_user', 'group_id' => '1', ), ); // group/1 $this->assertEquals('Role/admin', $this->Acl->Aro->resolve($user)); // group/24 $this->assertEquals('Role/accounting', $this->Acl->Aro->resolve('Role/24')); $this->assertEquals('Role/accounting', $this->Acl->Aro->resolve('24')); // check department $user = array( 'User' => array( 'username' => 'foo', 'group_id' => '25', ), ); $this->Acl->Aro->addRole(array('Role/IT' => null)); $this->Acl->Aro->addAlias(array('Role/25' => 'Role/IT')); $this->Acl->allow('Role/IT', '/rules/debugging/*'); $this->assertEquals(array(array('Role/IT')), $this->Acl->Aro->roles($user)); $this->assertTrue($this->Acl->check($user, '/rules/debugging/stats/pageload')); $this->assertTrue($this->Acl->check($user, '/rules/debugging/sql/queries')); // Role/default is allowed users dashboard, but not Role/IT $this->assertFalse($this->Acl->check($user, '/controllers/users/dashboard')); $this->assertFalse($this->Acl->check($user, '/controllers/invoices/send')); // wee add an more specific entry for user foo to also inherit from Role/accounting $this->Acl->Aro->addRole(array('User/foo' => 'Role/IT, Role/accounting')); $this->assertTrue($this->Acl->check($user, '/controllers/invoices/send')); } /** * test check method * * @return void */ public function testCheck() { $this->assertTrue($this->Acl->check('jan', '/controllers/users/Dashboard')); $this->assertTrue($this->Acl->check('some_unknown_role', '/controllers/users/Dashboard')); $this->assertTrue($this->Acl->check('Role/admin', 'foo/bar')); $this->assertTrue($this->Acl->check('role/admin', '/foo/bar')); $this->assertTrue($this->Acl->check('jan', 'foo/bar')); $this->assertTrue($this->Acl->check('user/jan', 'foo/bar')); $this->assertTrue($this->Acl->check('Role/admin', 'controllers/bar')); $this->assertTrue($this->Acl->check(array('User' => array('username' => 'jan')), '/controllers/bar/bll')); $this->assertTrue($this->Acl->check('Role/database_manager', 'controllers/db/create')); $this->assertTrue($this->Acl->check('User/db_manager_2', 'controllers/db/create')); $this->assertFalse($this->Acl->check('db_manager_2', '/controllers/users/Dashboard')); // inheritance: hardy -> reports -> data_analyst -> database_manager $this->assertTrue($this->Acl->check('User/hardy', 'controllers/db/create')); $this->assertFalse($this->Acl->check('User/jeff', 'controllers/db/create')); $this->assertTrue($this->Acl->check('Role/database_manager', 'controllers/db/select')); $this->assertTrue($this->Acl->check('User/db_manager_2', 'controllers/db/select')); $this->assertFalse($this->Acl->check('User/jeff', 'controllers/db/select')); $this->assertTrue($this->Acl->check('Role/database_manager', 'controllers/db/drop')); $this->assertTrue($this->Acl->check('User/db_manager_1', 'controllers/db/drop')); $this->assertFalse($this->Acl->check('db_manager_2', 'controllers/db/drop')); $this->assertTrue($this->Acl->check('db_manager_2', 'controllers/invoices/edit')); $this->assertFalse($this->Acl->check('database_manager', 'controllers/invoices/edit')); $this->assertFalse($this->Acl->check('db_manager_1', 'controllers/invoices/edit')); // Role/manager is allowed /controllers/*/*_manager $this->assertTrue($this->Acl->check('stan', 'controllers/invoices/manager_edit')); $this->assertTrue($this->Acl->check('Role/manager', 'controllers/baz/manager_foo')); $this->assertFalse($this->Acl->check('User/stan', 'custom/foo/manager_edit')); $this->assertFalse($this->Acl->check('stan', 'bar/baz/manager_foo')); $this->assertFalse($this->Acl->check('Role/accounting', 'bar/baz/manager_foo')); $this->assertFalse($this->Acl->check('accounting', 'controllers/baz/manager_foo')); $this->assertTrue($this->Acl->check('User/stan', 'controllers/articles/edit')); $this->assertTrue($this->Acl->check('stan', 'controllers/articles/add')); $this->assertTrue($this->Acl->check('stan', 'controllers/articles/publish')); $this->assertFalse($this->Acl->check('User/stan', 'controllers/articles/delete')); $this->assertFalse($this->Acl->check('accounting', 'controllers/articles/edit')); $this->assertFalse($this->Acl->check('accounting', 'controllers/articles/add')); $this->assertFalse($this->Acl->check('role/accounting', 'controllers/articles/publish')); } /** * lhs of defined rules are case insensitive * * @return void */ public function testCheckIsCaseInsensitive() { $this->assertTrue($this->Acl->check('hardy', 'controllers/forms/new')); $this->assertTrue($this->Acl->check('Role/data_acquirer', 'controllers/forms/new')); $this->assertTrue($this->Acl->check('hardy', 'controllers/FORMS/NEW')); $this->assertTrue($this->Acl->check('Role/data_acquirer', 'controllers/FORMS/NEW')); } /** * allow should work in-memory * * @return void */ public function testAllow() { $this->assertFalse($this->Acl->check('jeff', 'foo/bar')); $this->Acl->allow('jeff', 'foo/bar'); $this->assertTrue($this->Acl->check('jeff', 'foo/bar')); $this->assertFalse($this->Acl->check('peter', 'foo/bar')); $this->assertFalse($this->Acl->check('hardy', 'foo/bar')); $this->Acl->allow('Role/accounting', 'foo/bar'); $this->assertTrue($this->Acl->check('peter', 'foo/bar')); $this->assertTrue($this->Acl->check('hardy', 'foo/bar')); $this->assertFalse($this->Acl->check('Role/reports', 'foo/bar')); } /** * deny should work in-memory * * @return void */ public function testDeny() { $this->assertTrue($this->Acl->check('stan', 'controllers/baz/manager_foo')); $this->Acl->deny('stan', 'controllers/baz/manager_foo'); $this->assertFalse($this->Acl->check('stan', 'controllers/baz/manager_foo')); $this->assertTrue($this->Acl->check('Role/manager', 'controllers/baz/manager_foo')); $this->assertTrue($this->Acl->check('stan', 'controllers/baz/manager_bar')); $this->assertTrue($this->Acl->check('stan', 'controllers/baz/manager_foooooo')); } /** * test that a deny rule wins over an equally specific allow rule * * @return void */ public function testDenyRuleIsStrongerThanAllowRule() { $this->assertFalse($this->Acl->check('peter', 'baz/bam')); $this->Acl->allow('peter', 'baz/bam'); $this->assertTrue($this->Acl->check('peter', 'baz/bam')); $this->Acl->deny('peter', 'baz/bam'); $this->assertFalse($this->Acl->check('peter', 'baz/bam')); $this->assertTrue($this->Acl->check('stan', 'controllers/reports/foo')); // stan is denied as he's sales and sales is denied /controllers/*/delete $this->assertFalse($this->Acl->check('stan', 'controllers/reports/delete')); $this->Acl->allow('stan', 'controllers/reports/delete'); $this->assertFalse($this->Acl->check('Role/sales', 'controllers/reports/delete')); $this->assertTrue($this->Acl->check('stan', 'controllers/reports/delete')); $this->Acl->deny('stan', 'controllers/reports/delete'); $this->assertFalse($this->Acl->check('stan', 'controllers/reports/delete')); // there is already an equally specific deny rule that will win $this->Acl->allow('stan', 'controllers/reports/delete'); $this->assertFalse($this->Acl->check('stan', 'controllers/reports/delete')); } /** * test that an invalid configuration throws exception * * @return void */ public function testInvalidConfigWithAroMissing() { $this->setExpectedException( 'AclException', '"roles" section not found in configuration' ); $config = array('aco' => array('allow' => array('foo' => ''))); $this->PhpAcl->build($config); } public function testInvalidConfigWithAcosMissing() { $this->setExpectedException( 'AclException', 'Neither "allow" nor "deny" rules were provided in configuration.' ); $config = array( 'roles' => array('Role/foo' => null), ); $this->PhpAcl->build($config); } /** * test resolving of ACOs * * @return void */ public function testAcoResolve() { $this->assertEquals(array('foo', 'bar'), $this->Acl->Aco->resolve('foo/bar')); $this->assertEquals(array('foo', 'bar'), $this->Acl->Aco->resolve('foo/bar')); $this->assertEquals(array('foo', 'bar', 'baz'), $this->Acl->Aco->resolve('foo/bar/baz')); $this->assertEquals(array('foo', '*-bar', '?-baz'), $this->Acl->Aco->resolve('foo/*-bar/?-baz')); $this->assertEquals(array('foo', 'bar', '[a-f0-9]{24}', '*_bla', 'bla'), $this->Acl->Aco->resolve('foo/bar/[a-f0-9]{24}/*_bla/bla')); // multiple slashes will be squashed to a single, trimmed and then exploded $this->assertEquals(array('foo', 'bar'), $this->Acl->Aco->resolve('foo//bar')); $this->assertEquals(array('foo', 'bar'), $this->Acl->Aco->resolve('//foo///bar/')); $this->assertEquals(array('foo', 'bar'), $this->Acl->Aco->resolve('/foo//bar//')); $this->assertEquals(array('foo', 'bar'), $this->Acl->Aco->resolve('/foo // bar')); $this->assertEquals(array(), $this->Acl->Aco->resolve('/////')); } /** * test that declaring cyclic dependencies should give an error when building the tree * * @return void */ public function testAroDeclarationContainsCycles() { $config = array( 'roles' => array( 'Role/a' => null, 'Role/b' => 'User/b', 'User/a' => 'Role/a, Role/b', 'User/b' => 'User/a', ), 'rules' => array( 'allow' => array( '*' => 'Role/a', ), ), ); $this->expectError('PHPUnit_Framework_Error', 'cycle detected' /* ... */); $this->PhpAcl->build($config); } /** * test that with policy allow, only denies count * * @return void */ public function testPolicy() { // allow by default $this->Acl->settings['adapter']['policy'] = PhpAcl::ALLOW; $this->Acl->adapter($this->PhpAcl); $this->assertTrue($this->Acl->check('Role/sales', 'foo')); $this->assertTrue($this->Acl->check('Role/sales', 'controllers/bla/create')); $this->assertTrue($this->Acl->check('Role/default', 'foo')); // undefined user, undefined aco $this->assertTrue($this->Acl->check('foobar', 'foo/bar')); // deny rule: Role.sales -> controllers.*.delete $this->assertFalse($this->Acl->check('Role/sales', 'controllers/bar/delete')); $this->assertFalse($this->Acl->check('Role/sales', 'controllers/bar', 'delete')); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/AclComponentTest.php000066400000000000000000000046571265552240500264010ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Controller.Component * @since CakePHP(tm) v 1.2.0.5435 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('AclComponent', 'Controller/Component'); class_exists('AclComponent'); /** * Test Case for AclComponent * * @package Cake.Test.Case.Controller.Component */ class AclComponentTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); if (!class_exists('MockAclImplementation', false)) { $this->getMock('AclInterface', array(), array(), 'MockAclImplementation'); } Configure::write('Acl.classname', 'MockAclImplementation'); $Collection = new ComponentCollection(); $this->Acl = new AclComponent($Collection); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Acl); } /** * test that constructor throws an exception when Acl.classname is a * non-existent class * * @expectedException CakeException * @return void */ public function testConstrutorException() { Configure::write('Acl.classname', 'AclClassNameThatDoesNotExist'); $Collection = new ComponentCollection(); new AclComponent($Collection); } /** * test that adapter() allows control of the internal implementation AclComponent uses. * * @return void */ public function testAdapter() { $Adapter = $this->getMock('AclInterface'); $Adapter->expects($this->once())->method('initialize')->with($this->Acl); $this->assertNull($this->Acl->adapter($Adapter)); $this->assertEquals($this->Acl->adapter(), $Adapter, 'Returned object is different %s'); } /** * test that adapter() whines when the class does not implement AclInterface * * @expectedException CakeException * @return void */ public function testAdapterException() { $thing = new StdClass(); $this->Acl->adapter($thing); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/Auth/000077500000000000000000000000001265552240500233335ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/Auth/ActionsAuthorizeTest.php000066400000000000000000000112531265552240500302010ustar00rootroot00000000000000controller = $this->getMock('Controller', array(), array(), '', false); $this->Acl = $this->getMock('AclComponent', array(), array(), '', false); $this->Collection = $this->getMock('ComponentCollection'); $this->auth = new ActionsAuthorize($this->Collection); $this->auth->settings['actionPath'] = '/controllers'; } /** * setup the mock acl. * * @return void */ protected function _mockAcl() { $this->Collection->expects($this->any()) ->method('load') ->with('Acl') ->will($this->returnValue($this->Acl)); } /** * test failure * * @return void */ public function testAuthorizeFailure() { $user = array( 'User' => array( 'id' => 1, 'user' => 'mariano' ) ); $request = new CakeRequest('/posts/index', false); $request->addParams(array( 'plugin' => null, 'controller' => 'posts', 'action' => 'index' )); $this->_mockAcl(); $this->Acl->expects($this->once()) ->method('check') ->with($user, 'controllers/Posts/index') ->will($this->returnValue(false)); $this->assertFalse($this->auth->authorize($user['User'], $request)); } /** * test isAuthorized working. * * @return void */ public function testAuthorizeSuccess() { $user = array( 'User' => array( 'id' => 1, 'user' => 'mariano' ) ); $request = new CakeRequest('/posts/index', false); $request->addParams(array( 'plugin' => null, 'controller' => 'posts', 'action' => 'index' )); $this->_mockAcl(); $this->Acl->expects($this->once()) ->method('check') ->with($user, 'controllers/Posts/index') ->will($this->returnValue(true)); $this->assertTrue($this->auth->authorize($user['User'], $request)); } /** * testAuthorizeSettings * * @return void */ public function testAuthorizeSettings() { $request = new CakeRequest('/posts/index', false); $request->addParams(array( 'plugin' => null, 'controller' => 'posts', 'action' => 'index' )); $this->_mockAcl(); $this->auth->settings['userModel'] = 'TestPlugin.TestPluginAuthUser'; $user = array( 'id' => 1, 'user' => 'mariano' ); $expected = array('TestPlugin.TestPluginAuthUser' => array('id' => 1, 'user' => 'mariano')); $this->Acl->expects($this->once()) ->method('check') ->with($expected, 'controllers/Posts/index') ->will($this->returnValue(true)); $this->assertTrue($this->auth->authorize($user, $request)); } /** * test action() * * @return void */ public function testActionMethod() { $request = new CakeRequest('/posts/index', false); $request->addParams(array( 'plugin' => null, 'controller' => 'posts', 'action' => 'index' )); $result = $this->auth->action($request); $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 = new CakeRequest('/posts/index', false); $request->addParams(array( 'plugin' => null, 'controller' => 'posts', 'action' => 'index' )); $result = $this->auth->action($request); $this->assertEquals('controllers/Posts/index', $result); } /** * test action() and plugins * * @return void */ public function testActionWithPlugin() { $request = new CakeRequest('/debug_kit/posts/index', false); $request->addParams(array( 'plugin' => 'debug_kit', 'controller' => 'posts', 'action' => 'index' )); $result = $this->auth->action($request); $this->assertEquals('controllers/DebugKit/Posts/index', $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/Auth/BasicAuthenticateTest.php000066400000000000000000000216651265552240500302760ustar00rootroot00000000000000Collection = $this->getMock('ComponentCollection'); $this->auth = new BasicAuthenticate($this->Collection, array( 'fields' => array('username' => 'user', 'password' => 'password'), 'userModel' => 'User', 'realm' => 'localhost', 'recursive' => 0 )); $password = Security::hash('password', null, true); $User = ClassRegistry::init('User'); $User->updateAll(array('password' => $User->getDataSource()->value($password))); $this->response = $this->getMock('CakeResponse'); } /** * test applying settings in the constructor * * @return void */ public function testConstructor() { $object = new BasicAuthenticate($this->Collection, array( 'userModel' => 'AuthUser', 'fields' => array('username' => 'user', 'password' => 'password') )); $this->assertEquals('AuthUser', $object->settings['userModel']); $this->assertEquals(array('username' => 'user', 'password' => 'password'), $object->settings['fields']); $this->assertEquals(env('SERVER_NAME'), $object->settings['realm']); } /** * test the authenticate method * * @return void */ public function testAuthenticateNoData() { $request = new CakeRequest('posts/index', false); $this->response->expects($this->never()) ->method('header'); $this->assertFalse($this->auth->getUser($request)); } /** * test the authenticate method * * @return void */ public function testAuthenticateNoUsername() { $request = new CakeRequest('posts/index', false); $_SERVER['PHP_AUTH_PW'] = 'foobar'; $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * test the authenticate method * * @return void */ public function testAuthenticateNoPassword() { $request = new CakeRequest('posts/index', false); $_SERVER['PHP_AUTH_USER'] = 'mariano'; $_SERVER['PHP_AUTH_PW'] = null; $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * test the authenticate method * * @return void */ public function testAuthenticateInjection() { $request = new CakeRequest('posts/index', false); $request->addParams(array('pass' => array(), 'named' => array())); $_SERVER['PHP_AUTH_USER'] = '> 1'; $_SERVER['PHP_AUTH_PW'] = "' OR 1 = 1"; $this->assertFalse($this->auth->getUser($request)); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * Test that username of 0 works. * * @return void */ public function testAuthenticateUsernameZero() { $User = ClassRegistry::init('User'); $User->updateAll(array('user' => $User->getDataSource()->value('0')), array('user' => 'mariano')); $request = new CakeRequest('posts/index', false); $request->data = array('User' => array( 'user' => '0', 'password' => 'password' )); $_SERVER['PHP_AUTH_USER'] = '0'; $_SERVER['PHP_AUTH_PW'] = 'password'; $expected = array( 'id' => 1, 'user' => '0', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ); $this->assertEquals($expected, $this->auth->authenticate($request, $this->response)); } /** * test that challenge headers are sent when no credentials are found. * * @return void */ public function testAuthenticateChallenge() { $request = new CakeRequest('posts/index', false); $request->addParams(array('pass' => array(), 'named' => array())); try { $this->auth->unauthenticated($request, $this->response); } catch (UnauthorizedException $e) { } $this->assertNotEmpty($e); $expected = array('WWW-Authenticate: Basic realm="localhost"'); $this->assertEquals($expected, $e->responseHeader()); } /** * test authenticate success * * @return void */ public function testAuthenticateSuccess() { $request = new CakeRequest('posts/index', false); $request->addParams(array('pass' => array(), 'named' => array())); $_SERVER['PHP_AUTH_USER'] = 'mariano'; $_SERVER['PHP_AUTH_PW'] = 'password'; $result = $this->auth->authenticate($request, $this->response); $expected = array( 'id' => 1, 'user' => 'mariano', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ); $this->assertEquals($expected, $result); } /** * test contain success * * @return void */ public function testAuthenticateContainSuccess() { $User = ClassRegistry::init('User'); $User->bindModel(array('hasMany' => array('Article'))); $User->Behaviors->load('Containable'); $this->auth->settings['contain'] = 'Article'; $request = new CakeRequest('posts/index', false); $request->addParams(array('pass' => array(), 'named' => array())); $_SERVER['PHP_AUTH_USER'] = 'mariano'; $_SERVER['PHP_AUTH_PW'] = 'password'; $result = $this->auth->authenticate($request, $this->response); $expected = array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ); $this->assertEquals($expected, $result['Article'][0]); } /** * test userFields success * * @return void */ public function testAuthenticateUserFieldsSuccess() { $this->auth->settings['userFields'] = array('id', 'user'); $request = new CakeRequest('posts/index', false); $request->addParams(array('pass' => array(), 'named' => array())); $_SERVER['PHP_AUTH_USER'] = 'mariano'; $_SERVER['PHP_AUTH_PW'] = 'password'; $result = $this->auth->authenticate($request, $this->response); $expected = array( 'id' => 1, 'user' => 'mariano', ); $this->assertEquals($expected, $result); } /** * test userFields and related models success * * @return void */ public function testAuthenticateUserFieldsRelatedModelsSuccess() { $User = ClassRegistry::init('User'); $User->bindModel(array('hasOne' => array( 'Article' => array( 'order' => 'Article.id ASC' ) ))); $this->auth->settings['recursive'] = 0; $this->auth->settings['userFields'] = array('Article.id', 'Article.title'); $request = new CakeRequest('posts/index', false); $request->addParams(array('pass' => array(), 'named' => array())); $_SERVER['PHP_AUTH_USER'] = 'mariano'; $_SERVER['PHP_AUTH_PW'] = 'password'; $result = $this->auth->authenticate($request, $this->response); $expected = array( 'id' => 1, 'title' => 'First Article', ); $this->assertEquals($expected, $result['Article']); } /** * test scope failure. * * @expectedException UnauthorizedException * @expectedExceptionCode 401 * @return void */ public function testAuthenticateFailReChallenge() { $this->auth->settings['scope'] = array('user' => 'nate'); $request = new CakeRequest('posts/index', false); $request->addParams(array('pass' => array(), 'named' => array())); $_SERVER['PHP_AUTH_USER'] = 'mariano'; $_SERVER['PHP_AUTH_PW'] = 'password'; $this->auth->unauthenticated($request, $this->response); } /** * testAuthenticateWithBlowfish * * @return void */ public function testAuthenticateWithBlowfish() { $hash = Security::hash('password', 'blowfish'); $this->skipIf(strpos($hash, '$2a$') === false, 'Skipping blowfish tests as hashing is not working'); $request = new CakeRequest('posts/index', false); $request->addParams(array('pass' => array(), 'named' => array())); $_SERVER['PHP_AUTH_USER'] = 'mariano'; $_SERVER['PHP_AUTH_PW'] = 'password'; $User = ClassRegistry::init('User'); $User->updateAll( array('password' => $User->getDataSource()->value($hash)), array('User.user' => 'mariano') ); $this->auth->settings['passwordHasher'] = 'Blowfish'; $result = $this->auth->authenticate($request, $this->response); $expected = array( 'id' => 1, 'user' => 'mariano', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ); $this->assertEquals($expected, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/Auth/BlowfishAuthenticateTest.php000066400000000000000000000136121265552240500310230ustar00rootroot00000000000000Collection = $this->getMock('ComponentCollection'); $this->auth = new BlowfishAuthenticate($this->Collection, array( 'fields' => array('username' => 'user', 'password' => 'password'), 'userModel' => 'User' )); $password = Security::hash('password', 'blowfish'); $User = ClassRegistry::init('User'); $User->updateAll(array('password' => $User->getDataSource()->value($password))); $this->response = $this->getMock('CakeResponse'); $hash = Security::hash('password', 'blowfish'); $this->skipIf(strpos($hash, '$2a$') === false, 'Skipping blowfish tests as hashing is not working'); } /** * test applying settings in the constructor * * @return void */ public function testConstructor() { $Object = new BlowfishAuthenticate($this->Collection, array( 'userModel' => 'AuthUser', 'fields' => array('username' => 'user', 'password' => 'password') )); $this->assertEquals('AuthUser', $Object->settings['userModel']); $this->assertEquals(array('username' => 'user', 'password' => 'password'), $Object->settings['fields']); } /** * testAuthenticateNoData method * * @return void */ public function testAuthenticateNoData() { $request = new CakeRequest('posts/index', false); $request->data = array(); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * testAuthenticateNoUsername method * * @return void */ public function testAuthenticateNoUsername() { $request = new CakeRequest('posts/index', false); $request->data = array('User' => array('password' => 'foobar')); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * testAuthenticateNoPassword method * * @return void */ public function testAuthenticateNoPassword() { $request = new CakeRequest('posts/index', false); $request->data = array('User' => array('user' => 'mariano')); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * testAuthenticatePasswordIsFalse method * * @return void */ public function testAuthenticatePasswordIsFalse() { $request = new CakeRequest('posts/index', false); $request->data = array( 'User' => array( 'user' => 'mariano', 'password' => null )); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * testAuthenticateInjection method * * @return void */ public function testAuthenticateInjection() { $request = new CakeRequest('posts/index', false); $request->data = array('User' => array( 'user' => '> 1', 'password' => "' OR 1 = 1" )); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * testAuthenticateSuccess method * * @return void */ public function testAuthenticateSuccess() { $request = new CakeRequest('posts/index', false); $request->data = array('User' => array( 'user' => 'mariano', 'password' => 'password' )); $result = $this->auth->authenticate($request, $this->response); $expected = array( 'id' => 1, 'user' => 'mariano', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', ); $this->assertEquals($expected, $result); } /** * testAuthenticateScopeFail method * * @return void */ public function testAuthenticateScopeFail() { $this->auth->settings['scope'] = array('user' => 'nate'); $request = new CakeRequest('posts/index', false); $request->data = array('User' => array( 'user' => 'mariano', 'password' => 'password' )); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * testPluginModel method * * @return void */ public function testPluginModel() { Cache::delete('object_map', '_cake_core_'); App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); $PluginModel = ClassRegistry::init('TestPlugin.TestPluginAuthUser'); $user['id'] = 1; $user['username'] = 'gwoo'; $user['password'] = Security::hash('password', 'blowfish'); $PluginModel->save($user, false); $this->auth->settings['userModel'] = 'TestPlugin.TestPluginAuthUser'; $this->auth->settings['fields']['username'] = 'username'; $request = new CakeRequest('posts/index', false); $request->data = array('TestPluginAuthUser' => array( 'username' => 'gwoo', 'password' => 'password' )); $result = $this->auth->authenticate($request, $this->response); $expected = array( 'id' => 1, 'username' => 'gwoo', 'created' => '2007-03-17 01:16:23' ); $this->assertEquals(static::date(), $result['updated']); unset($result['updated']); $this->assertEquals($expected, $result); CakePlugin::unload(); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/Auth/ControllerAuthorizeTest.php000066400000000000000000000050511265552240500307230ustar00rootroot00000000000000controller = $this->getMock('Controller', array('isAuthorized'), array(), '', false); $this->components = $this->getMock('ComponentCollection'); $this->components->expects($this->any()) ->method('getController') ->will($this->returnValue($this->controller)); $this->auth = new ControllerAuthorize($this->components); } /** * testControllerTypeError * * @expectedException PHPUnit_Framework_Error * @throws PHPUnit_Framework_Error * @return void */ public function testControllerTypeError() { try { $this->auth->controller(new StdClass()); } catch (Throwable $t) { throw new PHPUnit_Framework_Error($t); } } /** * testControllerErrorOnMissingMethod * * @expectedException CakeException * @return void */ public function testControllerErrorOnMissingMethod() { $this->auth->controller(new Controller()); } /** * test failure * * @return void */ public function testAuthorizeFailure() { $user = array(); $request = new CakeRequest('/posts/index', false); $this->assertFalse($this->auth->authorize($user, $request)); } /** * test isAuthorized working. * * @return void */ public function testAuthorizeSuccess() { $user = array('User' => array('username' => 'mark')); $request = new CakeRequest('/posts/index', false); $this->controller->expects($this->once()) ->method('isAuthorized') ->with($user) ->will($this->returnValue(true)); $this->assertTrue($this->auth->authorize($user, $request)); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/Auth/CrudAuthorizeTest.php000066400000000000000000000107511265552240500275000ustar00rootroot00000000000000Acl = $this->getMock('AclComponent', array(), array(), '', false); $this->Components = $this->getMock('ComponentCollection'); $this->auth = new CrudAuthorize($this->Components); } /** * setup the mock acl. * * @return void */ protected function _mockAcl() { $this->Components->expects($this->any()) ->method('load') ->with('Acl') ->will($this->returnValue($this->Acl)); } /** * test authorize() without a mapped action, ensure an error is generated. * * @expectedException PHPUnit_Framework_Error_Warning * @return void */ public function testAuthorizeNoMappedAction() { $request = new CakeRequest('/posts/foobar', false); $request->addParams(array( 'controller' => 'posts', 'action' => 'foobar' )); $user = array('User' => array('user' => 'mark')); $this->auth->authorize($user, $request); } /** * test check() passing * * @return void */ public function testAuthorizeCheckSuccess() { $request = new CakeRequest('posts/index', false); $request->addParams(array( 'controller' => 'posts', 'action' => 'index' )); $user = array('User' => array('user' => 'mark')); $this->_mockAcl(); $this->Acl->expects($this->once()) ->method('check') ->with($user, 'Posts', 'read') ->will($this->returnValue(true)); $this->assertTrue($this->auth->authorize($user['User'], $request)); } /** * test check() failing * * @return void */ public function testAuthorizeCheckFailure() { $request = new CakeRequest('posts/index', false); $request->addParams(array( 'controller' => 'posts', 'action' => 'index' )); $user = array('User' => array('user' => 'mark')); $this->_mockAcl(); $this->Acl->expects($this->once()) ->method('check') ->with($user, 'Posts', 'read') ->will($this->returnValue(false)); $this->assertFalse($this->auth->authorize($user['User'], $request)); } /** * test getting actionMap * * @return void */ public function testMapActionsGet() { $result = $this->auth->mapActions(); $expected = array( 'create' => 'create', 'read' => 'read', 'update' => 'update', 'delete' => 'delete', 'index' => 'read', 'add' => 'create', 'edit' => 'update', 'view' => 'read', 'remove' => 'delete' ); $this->assertEquals($expected, $result); } /** * test adding into mapActions * * @return void */ public function testMapActionsSet() { $map = array( 'create' => array('generate'), 'read' => array('listing', 'show'), 'update' => array('update'), 'random' => 'custom' ); $result = $this->auth->mapActions($map); $this->assertNull($result); $result = $this->auth->mapActions(); $expected = array( 'add' => 'create', 'create' => 'create', 'read' => 'read', 'index' => 'read', 'edit' => 'update', 'view' => 'read', 'delete' => 'delete', 'remove' => 'delete', 'generate' => 'create', 'listing' => 'read', 'show' => 'read', 'update' => 'update', 'random' => 'custom', ); $this->assertEquals($expected, $result); } /** * test prefix routes getting auto mapped. * * @return void */ public function testAutoPrefixMapActions() { Configure::write('Routing.prefixes', array('admin', 'manager')); Router::reload(); $auth = new CrudAuthorize($this->Components); $this->assertTrue(isset($auth->settings['actionMap']['admin_index'])); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/Auth/DigestAuthenticateTest.php000066400000000000000000000201661265552240500304670ustar00rootroot00000000000000Collection = $this->getMock('ComponentCollection'); $this->server = $_SERVER; $this->auth = new DigestAuthenticate($this->Collection, array( 'fields' => array('username' => 'user', 'password' => 'password'), 'userModel' => 'User', 'realm' => 'localhost', 'nonce' => 123, 'opaque' => '123abc' )); $password = DigestAuthenticate::password('mariano', 'cake', 'localhost'); $User = ClassRegistry::init('User'); $User->updateAll(array('password' => $User->getDataSource()->value($password))); $_SERVER['REQUEST_METHOD'] = 'GET'; $this->response = $this->getMock('CakeResponse'); } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); $_SERVER = $this->server; } /** * test applying settings in the constructor * * @return void */ public function testConstructor() { $object = new DigestAuthenticate($this->Collection, array( 'userModel' => 'AuthUser', 'fields' => array('username' => 'user', 'password' => 'password'), 'nonce' => 123456 )); $this->assertEquals('AuthUser', $object->settings['userModel']); $this->assertEquals(array('username' => 'user', 'password' => 'password'), $object->settings['fields']); $this->assertEquals(123456, $object->settings['nonce']); $this->assertEquals(env('SERVER_NAME'), $object->settings['realm']); } /** * test the authenticate method * * @return void */ public function testAuthenticateNoData() { $request = new CakeRequest('posts/index', false); $this->response->expects($this->never()) ->method('header'); $this->assertFalse($this->auth->getUser($request, $this->response)); } /** * test the authenticate method * * @expectedException UnauthorizedException * @expectedExceptionCode 401 * @return void */ public function testAuthenticateWrongUsername() { $request = new CakeRequest('posts/index', false); $request->addParams(array('pass' => array(), 'named' => array())); $_SERVER['PHP_AUTH_DIGEST'] = <<auth->unauthenticated($request, $this->response); } /** * test that challenge headers are sent when no credentials are found. * * @return void */ public function testAuthenticateChallenge() { $request = new CakeRequest('posts/index', false); $request->addParams(array('pass' => array(), 'named' => array())); try { $this->auth->unauthenticated($request, $this->response); } catch (UnauthorizedException $e) { } $this->assertNotEmpty($e); $expected = array('WWW-Authenticate: Digest realm="localhost",qop="auth",nonce="123",opaque="123abc"'); $this->assertEquals($expected, $e->responseHeader()); } /** * test authenticate success * * @return void */ public function testAuthenticateSuccess() { $request = new CakeRequest('posts/index', false); $request->addParams(array('pass' => array(), 'named' => array())); $_SERVER['PHP_AUTH_DIGEST'] = <<auth->authenticate($request, $this->response); $expected = array( 'id' => 1, 'user' => 'mariano', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ); $this->assertEquals($expected, $result); } /** * test scope failure. * * @expectedException UnauthorizedException * @expectedExceptionCode 401 * @return void */ public function testAuthenticateFailReChallenge() { $this->auth->settings['scope'] = array('user' => 'nate'); $request = new CakeRequest('posts/index', false); $request->addParams(array('pass' => array(), 'named' => array())); $_SERVER['PHP_AUTH_DIGEST'] = <<auth->unauthenticated($request, $this->response); } /** * testParseDigestAuthData method * * @return void */ public function testParseAuthData() { $digest = << 'Mufasa', 'realm' => 'testrealm@host.com', 'nonce' => 'dcd98b7102dd2f0e8b11d0f600bfb0c093', 'uri' => '/dir/index.html?query=string&value=some%20value', 'qop' => 'auth', 'nc' => '00000001', 'cnonce' => '0a4f113b', 'response' => '6629fae49393a05397450978507c4ef1', 'opaque' => '5ccc069c403ebaf9f0171e9517f40e41' ); $result = $this->auth->parseAuthData($digest); $this->assertSame($expected, $result); $result = $this->auth->parseAuthData(''); $this->assertNull($result); } /** * Test parsing a full URI. While not part of the spec some mobile clients will do it wrong. * * @return void */ public function testParseAuthDataFullUri() { $digest = <<auth->parseAuthData($digest); $this->assertSame($expected, $result['uri']); } /** * test parsing digest information with email addresses * * @return void */ public function testParseAuthEmailAddress() { $digest = << 'mark@example.com', 'realm' => 'testrealm@host.com', 'nonce' => 'dcd98b7102dd2f0e8b11d0f600bfb0c093', 'uri' => '/dir/index.html', 'qop' => 'auth', 'nc' => '00000001', 'cnonce' => '0a4f113b', 'response' => '6629fae49393a05397450978507c4ef1', 'opaque' => '5ccc069c403ebaf9f0171e9517f40e41' ); $result = $this->auth->parseAuthData($digest); $this->assertSame($expected, $result); } /** * test password hashing * * @return void */ public function testPassword() { $result = DigestAuthenticate::password('mark', 'password', 'localhost'); $expected = md5('mark:localhost:password'); $this->assertEquals($expected, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/Auth/FormAuthenticateTest.php000066400000000000000000000222721265552240500301530ustar00rootroot00000000000000Collection = $this->getMock('ComponentCollection'); $this->auth = new FormAuthenticate($this->Collection, array( 'fields' => array('username' => 'user', 'password' => 'password'), 'userModel' => 'User' )); $password = Security::hash('password', null, true); $User = ClassRegistry::init('User'); $User->updateAll(array('password' => $User->getDataSource()->value($password))); $this->response = $this->getMock('CakeResponse'); } /** * test applying settings in the constructor * * @return void */ public function testConstructor() { $object = new FormAuthenticate($this->Collection, array( 'userModel' => 'AuthUser', 'fields' => array('username' => 'user', 'password' => 'password') )); $this->assertEquals('AuthUser', $object->settings['userModel']); $this->assertEquals(array('username' => 'user', 'password' => 'password'), $object->settings['fields']); } /** * test the authenticate method * * @return void */ public function testAuthenticateNoData() { $request = new CakeRequest('posts/index', false); $request->data = array(); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * test the authenticate method * * @return void */ public function testAuthenticateNoUsername() { $request = new CakeRequest('posts/index', false); $request->data = array('User' => array('password' => 'foobar')); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * test the authenticate method * * @return void */ public function testAuthenticateNoPassword() { $request = new CakeRequest('posts/index', false); $request->data = array('User' => array('user' => 'mariano')); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * test authenticate password is false method * * @return void */ public function testAuthenticatePasswordIsFalse() { $request = new CakeRequest('posts/index', false); $request->data = array( 'User' => array( 'user' => 'mariano', 'password' => null )); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * Test for password as empty string with _checkFields() call skipped * Refs https://github.com/cakephp/cakephp/pull/2441 * * @return void */ public function testAuthenticatePasswordIsEmptyString() { $request = new CakeRequest('posts/index', false); $request->data = array( 'User' => array( 'user' => 'mariano', 'password' => '' )); $this->auth = $this->getMock( 'FormAuthenticate', array('_checkFields'), array( $this->Collection, array( 'fields' => array('username' => 'user', 'password' => 'password'), 'userModel' => 'User' ) ) ); // Simulate that check for ensuring password is not empty is missing. $this->auth->expects($this->once()) ->method('_checkFields') ->will($this->returnValue(true)); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * test authenticate field is not string * * @return void */ public function testAuthenticateFieldsAreNotString() { $request = new CakeRequest('posts/index', false); $request->data = array( 'User' => array( 'user' => array('mariano', 'phpnut'), 'password' => 'my password' )); $this->assertFalse($this->auth->authenticate($request, $this->response)); $request->data = array( 'User' => array( 'user' => array(), 'password' => 'my password' )); $this->assertFalse($this->auth->authenticate($request, $this->response)); $request->data = array( 'User' => array( 'user' => 'mariano', 'password' => array('password1', 'password2') )); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * test the authenticate method * * @return void */ public function testAuthenticateInjection() { $request = new CakeRequest('posts/index', false); $request->data = array( 'User' => array( 'user' => '> 1', 'password' => "' OR 1 = 1" )); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * test authenticate success * * @return void */ public function testAuthenticateSuccess() { $request = new CakeRequest('posts/index', false); $request->data = array('User' => array( 'user' => 'mariano', 'password' => 'password' )); $result = $this->auth->authenticate($request, $this->response); $expected = array( 'id' => 1, 'user' => 'mariano', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ); $this->assertEquals($expected, $result); } /** * test scope failure. * * @return void */ public function testAuthenticateScopeFail() { $this->auth->settings['scope'] = array('user' => 'nate'); $request = new CakeRequest('posts/index', false); $request->data = array('User' => array( 'user' => 'mariano', 'password' => 'password' )); $this->assertFalse($this->auth->authenticate($request, $this->response)); } /** * Test that username of 0 works. * * @return void */ public function testAuthenticateUsernameZero() { $User = ClassRegistry::init('User'); $User->updateAll(array('user' => $User->getDataSource()->value('0')), array('user' => 'mariano')); $request = new CakeRequest('posts/index', false); $request->data = array('User' => array( 'user' => '0', 'password' => 'password' )); $expected = array( 'id' => 1, 'user' => '0', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ); $this->assertEquals($expected, $this->auth->authenticate($request, $this->response)); } /** * test a model in a plugin. * * @return void */ public function testPluginModel() { Cache::delete('object_map', '_cake_core_'); App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), ), App::RESET); CakePlugin::load('TestPlugin'); $PluginModel = ClassRegistry::init('TestPlugin.TestPluginAuthUser'); $user['id'] = 1; $user['username'] = 'gwoo'; $user['password'] = Security::hash(Configure::read('Security.salt') . 'cake'); $PluginModel->save($user, false); $this->auth->settings['userModel'] = 'TestPlugin.TestPluginAuthUser'; $this->auth->settings['fields']['username'] = 'username'; $request = new CakeRequest('posts/index', false); $request->data = array('TestPluginAuthUser' => array( 'username' => 'gwoo', 'password' => 'cake' )); $result = $this->auth->authenticate($request, $this->response); $expected = array( 'id' => 1, 'username' => 'gwoo', 'created' => '2007-03-17 01:16:23' ); $this->assertEquals(static::date(), $result['updated']); unset($result['updated']); $this->assertEquals($expected, $result); CakePlugin::unload(); } /** * test password hasher settings * * @return void */ public function testPasswordHasherSettings() { $this->auth->settings['passwordHasher'] = array( 'className' => 'Simple', 'hashType' => 'md5' ); $passwordHasher = $this->auth->passwordHasher(); $result = $passwordHasher->config(); $this->assertEquals('md5', $result['hashType']); $hash = Security::hash('mypass', 'md5', true); $User = ClassRegistry::init('User'); $User->updateAll( array('password' => $User->getDataSource()->value($hash)), array('User.user' => 'mariano') ); $request = new CakeRequest('posts/index', false); $request->data = array('User' => array( 'user' => 'mariano', 'password' => 'mypass' )); $result = $this->auth->authenticate($request, $this->response); $expected = array( 'id' => 1, 'user' => 'mariano', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ); $this->assertEquals($expected, $result); $this->auth = new FormAuthenticate($this->Collection, array( 'fields' => array('username' => 'user', 'password' => 'password'), 'userModel' => 'User' )); $this->auth->settings['passwordHasher'] = array( 'className' => 'Simple', 'hashType' => 'sha1' ); $this->assertFalse($this->auth->authenticate($request, $this->response)); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/AuthComponentTest.php000066400000000000000000001426041265552240500265760ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Controller.Component * @since CakePHP(tm) v 1.2.0.5347 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Controller', 'Controller'); App::uses('AuthComponent', 'Controller/Component'); App::uses('AclComponent', 'Controller/Component'); App::uses('BaseAuthenticate', 'Controller/Component/Auth'); App::uses('FormAuthenticate', 'Controller/Component/Auth'); App::uses('CakeEvent', 'Event'); /** * TestFormAuthenticate class * * @package Cake.Test.Case.Controller.Component */ class TestBaseAuthenticate extends BaseAuthenticate { /** * Implemented events * * @return array of events => callbacks. */ public function implementedEvents() { return array( 'Auth.afterIdentify' => 'afterIdentify' ); } public $afterIdentifyCallable = null; /** * Test function to be used in event dispatching * * @return void */ public function afterIdentify($event) { call_user_func($this->afterIdentifyCallable, $event); } /** * Authenticate a user based on the request information. * * @param CakeRequest $request Request to get authentication information from. * @param CakeResponse $response A response object that can have headers added. * @return mixed Either false on failure, or an array of user data on success. */ public function authenticate(CakeRequest $request, CakeResponse $response) { return array( 'id' => 1, 'username' => 'mark' ); } } /** * TestAuthComponent class * * @package Cake.Test.Case.Controller.Component */ class TestAuthComponent extends AuthComponent { /** * testStop property * * @var bool */ public $testStop = false; /** * Helper method to add/set an authenticate object instance * * @param int $index The index at which to add/set the object * @param object $object The object to add/set * @return void */ public function setAuthenticateObject($index, $object) { $this->_authenticateObjects[$index] = $object; } /** * Helper method to get an authenticate object instance * * @param int $index The index at which to get the object * @return object $object */ public function getAuthenticateObject($index) { $this->constructAuthenticate(); return isset($this->_authenticateObjects[$index]) ? $this->_authenticateObjects[$index] : null; } /** * Helper method to add/set an authorize object instance * * @param int $index The index at which to add/set the object * @param Object $object The object to add/set * @return void */ public function setAuthorizeObject($index, $object) { $this->_authorizeObjects[$index] = $object; } /** * stop method * * @return void */ protected function _stop($status = 0) { $this->testStop = true; } public static function clearUser() { static::$_user = array(); } } /** * AuthUser class * * @package Cake.Test.Case.Controller.Component */ class AuthUser extends CakeTestModel { /** * useDbConfig property * * @var string */ public $useDbConfig = 'test'; } /** * AuthTestController class * * @package Cake.Test.Case.Controller.Component */ class AuthTestController extends Controller { /** * uses property * * @var array */ public $uses = array('AuthUser'); /** * components property * * @var array */ public $components = array('Session', 'Flash', 'Auth'); /** * testUrl property * * @var mixed */ public $testUrl = null; /** * construct method */ public function __construct($request, $response) { $request->addParams(Router::parse('/auth_test')); $request->here = '/auth_test'; $request->webroot = '/'; Router::setRequestInfo($request); parent::__construct($request, $response); } /** * login method * * @return void */ public function login() { } /** * admin_login method * * @return void */ public function admin_login() { } /** * admin_add method * * @return void */ public function admin_add() { } /** * logout method * * @return void */ public function logout() { } /** * add method * * @return void */ public function add() { echo "add"; } /** * add method * * @return void */ public function camelCase() { echo "camelCase"; } /** * redirect method * * @param string|array $url * @param mixed $status * @param mixed $exit * @return void */ public function redirect($url, $status = null, $exit = true) { $this->testUrl = Router::url($url); return false; } /** * isAuthorized method * * @return void */ public function isAuthorized() { } } /** * AjaxAuthController class * * @package Cake.Test.Case.Controller.Component */ class AjaxAuthController extends Controller { /** * components property * * @var array */ public $components = array('Session', 'TestAuth'); /** * uses property * * @var array */ public $uses = array(); /** * testUrl property * * @var mixed */ public $testUrl = null; /** * beforeFilter method * * @return void */ public function beforeFilter() { $this->TestAuth->ajaxLogin = 'test_element'; $this->TestAuth->userModel = 'AuthUser'; $this->TestAuth->RequestHandler->ajaxLayout = 'ajax2'; } /** * add method * * @return void */ public function add() { if ($this->TestAuth->testStop !== true) { echo 'Added Record'; } } /** * redirect method * * @param string|array $url * @param mixed $status * @param mixed $exit * @return void */ public function redirect($url, $status = null, $exit = true) { $this->testUrl = Router::url($url); return false; } } /** * Mock class used to test event dispatching * * @package Cake.Test.Case.Event */ class AuthEventTestListener { public $callStack = array(); /** * Test function to be used in event dispatching * * @return void */ public function listenerFunction() { $this->callStack[] = __FUNCTION__; } } /** * AuthComponentTest class * * @package Cake.Test.Case.Controller.Component */ class AuthComponentTest extends CakeTestCase { /** * name property * * @var string */ public $name = 'Auth'; /** * fixtures property * * @var array */ public $fixtures = array('core.auth_user'); /** * initialized property * * @var bool */ public $initialized = false; /** * setUp method * * @return void */ public function setUp() { parent::setUp(); Configure::write('Security.salt', 'YJfIxfs2guVoUubWDYhG93b0qyJfIxfs2guwvniR2G0FgaC9mi'); Configure::write('Security.cipherSeed', 770011223369876); $request = new CakeRequest(null, false); $this->Controller = new AuthTestController($request, $this->getMock('CakeResponse')); $collection = new ComponentCollection(); $collection->init($this->Controller); $this->Auth = new TestAuthComponent($collection); $this->Auth->request = $request; $this->Auth->response = $this->getMock('CakeResponse'); AuthComponent::$sessionKey = 'Auth.User'; $this->Controller->Components->init($this->Controller); $this->initialized = true; Router::reload(); Router::connect('/:controller/:action/*'); $User = ClassRegistry::init('AuthUser'); $User->updateAll(array('password' => $User->getDataSource()->value(Security::hash('cake', null, true)))); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); TestAuthComponent::clearUser(); $this->Auth->Session->delete('Auth'); $this->Auth->Session->delete('Message.auth'); unset($this->Controller, $this->Auth); } /** * testNoAuth method * * @return void */ public function testNoAuth() { $this->assertFalse($this->Auth->isAuthorized()); } /** * testIsErrorOrTests * * @return void */ public function testIsErrorOrTests() { $this->Controller->Auth->initialize($this->Controller); $this->Controller->name = 'CakeError'; $this->assertTrue($this->Controller->Auth->startup($this->Controller)); $this->Controller->name = 'Post'; $this->Controller->request['action'] = 'thisdoesnotexist'; $this->assertTrue($this->Controller->Auth->startup($this->Controller)); $this->Controller->scaffold = null; $this->Controller->request['action'] = 'index'; $this->assertFalse($this->Controller->Auth->startup($this->Controller)); } /** * testLogin method * * @return void */ public function testLogin() { $AuthLoginFormAuthenticate = $this->getMock('FormAuthenticate', array(), array(), '', false); $this->Auth->authenticate = array( 'AuthLoginForm' => array( 'userModel' => 'AuthUser' ) ); $this->Auth->Session = $this->getMock('SessionComponent', array('renew'), array(), '', false); $this->Auth->setAuthenticateObject(0, $AuthLoginFormAuthenticate); $this->Auth->request->data = array( 'AuthUser' => array( 'username' => 'mark', 'password' => Security::hash('cake', null, true) ) ); $user = array( 'id' => 1, 'username' => 'mark' ); $AuthLoginFormAuthenticate->expects($this->once()) ->method('authenticate') ->with($this->Auth->request) ->will($this->returnValue($user)); $this->Auth->Session->expects($this->once()) ->method('renew'); $result = $this->Auth->login(); $this->assertTrue($result); $this->assertTrue($this->Auth->loggedIn()); $this->assertEquals($user, $this->Auth->user()); } /** * testLogin afterIdentify event method * * @return void */ public function testLoginAfterIdentify() { $this->Auth->authenticate = array( 'TestBase', ); $user = array( 'id' => 1, 'username' => 'mark' ); $auth = $this->Auth->getAuthenticateObject(0); $listener = $this->getMock('AuthEventTestListener'); $auth->afterIdentifyCallable = array($listener, 'listenerFunction'); $event = new CakeEvent('Auth.afterIdentify', $this->Auth, array('user' => $user)); $listener->expects($this->once())->method('listenerFunction')->with($event); $result = $this->Auth->login(); $this->assertTrue($result); $this->assertTrue($this->Auth->loggedIn()); $this->assertEquals($user, $this->Auth->user()); } /** * testRedirectVarClearing method * * @return void */ public function testRedirectVarClearing() { $this->Controller->request['controller'] = 'auth_test'; $this->Controller->request['action'] = 'admin_add'; $this->Controller->here = '/auth_test/admin_add'; $this->assertNull($this->Auth->Session->read('Auth.redirect')); $this->Auth->authenticate = array('Form'); $this->Auth->startup($this->Controller); $this->assertEquals('/auth_test/admin_add', $this->Auth->Session->read('Auth.redirect')); $this->Auth->Session->write('Auth.User', array('username' => 'admad')); $this->Auth->startup($this->Controller); $this->assertNull($this->Auth->Session->read('Auth.redirect')); } /** * testAuthorizeFalse method * * @return void */ public function testAuthorizeFalse() { $this->AuthUser = new AuthUser(); $user = $this->AuthUser->find(); $this->Auth->Session->write('Auth.User', $user['AuthUser']); $this->Controller->Auth->userModel = 'AuthUser'; $this->Controller->Auth->authorize = false; $this->Controller->request->addParams(Router::parse('auth_test/add')); $this->Controller->Auth->initialize($this->Controller); $result = $this->Controller->Auth->startup($this->Controller); $this->assertTrue($result); $this->Auth->Session->delete('Auth'); $result = $this->Controller->Auth->startup($this->Controller); $this->assertFalse($result); $this->assertTrue($this->Auth->Session->check('Message.auth')); $this->Controller->request->addParams(Router::parse('auth_test/camelCase')); $result = $this->Controller->Auth->startup($this->Controller); $this->assertFalse($result); } /** * @expectedException CakeException * @return void */ public function testIsAuthorizedMissingFile() { $this->Controller->Auth->authorize = 'Missing'; $this->Controller->Auth->isAuthorized(array('User' => array('id' => 1))); } /** * test that isAuthorized calls methods correctly * * @return void */ public function testIsAuthorizedDelegation() { $AuthMockOneAuthorize = $this->getMock('BaseAuthorize', array('authorize'), array(), '', false); $AuthMockTwoAuthorize = $this->getMock('BaseAuthorize', array('authorize'), array(), '', false); $AuthMockThreeAuthorize = $this->getMock('BaseAuthorize', array('authorize'), array(), '', false); $this->Auth->setAuthorizeObject(0, $AuthMockOneAuthorize); $this->Auth->setAuthorizeObject(1, $AuthMockTwoAuthorize); $this->Auth->setAuthorizeObject(2, $AuthMockThreeAuthorize); $request = $this->Auth->request; $AuthMockOneAuthorize->expects($this->once()) ->method('authorize') ->with(array('User'), $request) ->will($this->returnValue(false)); $AuthMockTwoAuthorize->expects($this->once()) ->method('authorize') ->with(array('User'), $request) ->will($this->returnValue(true)); $AuthMockThreeAuthorize->expects($this->never()) ->method('authorize'); $this->assertTrue($this->Auth->isAuthorized(array('User'), $request)); } /** * test that isAuthorized will use the session user if none is given. * * @return void */ public function testIsAuthorizedUsingUserInSession() { $AuthMockFourAuthorize = $this->getMock('BaseAuthorize', array('authorize'), array(), '', false); $this->Auth->authorize = array('AuthMockFour'); $this->Auth->setAuthorizeObject(0, $AuthMockFourAuthorize); $user = array('user' => 'mark'); $this->Auth->Session->write('Auth.User', $user); $request = $this->Controller->request; $AuthMockFourAuthorize->expects($this->once()) ->method('authorize') ->with($user, $request) ->will($this->returnValue(true)); $this->assertTrue($this->Auth->isAuthorized(null, $request)); } /** * test that loadAuthorize resets the loaded objects each time. * * @return void */ public function testLoadAuthorizeResets() { $this->Controller->Auth->authorize = array( 'Controller' ); $result = $this->Controller->Auth->constructAuthorize(); $this->assertEquals(1, count($result)); $result = $this->Controller->Auth->constructAuthorize(); $this->assertEquals(1, count($result)); } /** * @expectedException CakeException * @return void */ public function testLoadAuthenticateNoFile() { $this->Controller->Auth->authenticate = 'Missing'; $this->Controller->Auth->identify($this->Controller->request, $this->Controller->response); } /** * test the * key with authenticate * * @return void */ public function testAllConfigWithAuthorize() { $this->Controller->Auth->authorize = array( AuthComponent::ALL => array('actionPath' => 'controllers/'), 'Actions' ); $objects = $this->Controller->Auth->constructAuthorize(); $result = $objects[0]; $this->assertEquals('controllers/', $result->settings['actionPath']); } /** * test that loadAuthorize resets the loaded objects each time. * * @return void */ public function testLoadAuthenticateResets() { $this->Controller->Auth->authenticate = array( 'Form' ); $result = $this->Controller->Auth->constructAuthenticate(); $this->assertEquals(1, count($result)); $result = $this->Controller->Auth->constructAuthenticate(); $this->assertEquals(1, count($result)); } /** * test the * key with authenticate * * @return void */ public function testAllConfigWithAuthenticate() { $this->Controller->Auth->authenticate = array( AuthComponent::ALL => array('userModel' => 'AuthUser'), 'Form' ); $objects = $this->Controller->Auth->constructAuthenticate(); $result = $objects[0]; $this->assertEquals('AuthUser', $result->settings['userModel']); } /** * test defining the same Authenticate object but with different password hashers * * @return void */ public function testSameAuthenticateWithDifferentHashers() { $this->Controller->Auth->authenticate = array( 'FormSimple' => array('className' => 'Form', 'passwordHasher' => 'Simple'), 'FormBlowfish' => array('className' => 'Form', 'passwordHasher' => 'Blowfish'), ); $objects = $this->Controller->Auth->constructAuthenticate(); $this->assertEquals(2, count($objects)); $this->assertInstanceOf('FormAuthenticate', $objects[0]); $this->assertInstanceOf('FormAuthenticate', $objects[1]); $this->assertInstanceOf('SimplePasswordHasher', $objects[0]->passwordHasher()); $this->assertInstanceOf('BlowfishPasswordHasher', $objects[1]->passwordHasher()); } /** * Tests that deny always takes precedence over allow * * @return void */ public function testAllowDenyAll() { $this->Controller->Auth->initialize($this->Controller); $this->Controller->Auth->allow(); $this->Controller->Auth->deny('add', 'camelCase'); $this->Controller->request['action'] = 'delete'; $this->assertTrue($this->Controller->Auth->startup($this->Controller)); $this->Controller->request['action'] = 'add'; $this->assertFalse($this->Controller->Auth->startup($this->Controller)); $this->Controller->request['action'] = 'camelCase'; $this->assertFalse($this->Controller->Auth->startup($this->Controller)); $this->Controller->Auth->allow(); $this->Controller->Auth->deny(array('add', 'camelCase')); $this->Controller->request['action'] = 'delete'; $this->assertTrue($this->Controller->Auth->startup($this->Controller)); $this->Controller->request['action'] = 'camelCase'; $this->assertFalse($this->Controller->Auth->startup($this->Controller)); $this->Controller->Auth->allow('*'); $this->Controller->Auth->deny(); $this->Controller->request['action'] = 'camelCase'; $this->assertFalse($this->Controller->Auth->startup($this->Controller)); $this->Controller->request['action'] = 'add'; $this->assertFalse($this->Controller->Auth->startup($this->Controller)); $this->Controller->Auth->allow('camelCase'); $this->Controller->Auth->deny(); $this->Controller->request['action'] = 'camelCase'; $this->assertFalse($this->Controller->Auth->startup($this->Controller)); $this->Controller->request['action'] = 'login'; $this->assertFalse($this->Controller->Auth->startup($this->Controller)); $this->Controller->Auth->deny(); $this->Controller->Auth->allow(null); $this->Controller->request['action'] = 'camelCase'; $this->assertTrue($this->Controller->Auth->startup($this->Controller)); $this->Controller->Auth->allow(); $this->Controller->Auth->deny(null); $this->Controller->request['action'] = 'camelCase'; $this->assertFalse($this->Controller->Auth->startup($this->Controller)); } /** * test that deny() converts camel case inputs to lowercase. * * @return void */ public function testDenyWithCamelCaseMethods() { $this->Controller->Auth->initialize($this->Controller); $this->Controller->Auth->allow(); $this->Controller->Auth->deny('add', 'camelCase'); $url = '/auth_test/camelCase'; $this->Controller->request->addParams(Router::parse($url)); $this->Controller->request->query['url'] = Router::normalize($url); $this->assertFalse($this->Controller->Auth->startup($this->Controller)); $url = '/auth_test/CamelCase'; $this->Controller->request->addParams(Router::parse($url)); $this->Controller->request->query['url'] = Router::normalize($url); $this->assertFalse($this->Controller->Auth->startup($this->Controller)); } /** * test that allow() and allowedActions work with camelCase method names. * * @return void */ public function testAllowedActionsWithCamelCaseMethods() { $url = '/auth_test/camelCase'; $this->Controller->request->addParams(Router::parse($url)); $this->Controller->request->query['url'] = Router::normalize($url); $this->Controller->Auth->initialize($this->Controller); $this->Controller->Auth->loginAction = array('controller' => 'AuthTest', 'action' => 'login'); $this->Controller->Auth->userModel = 'AuthUser'; $this->Controller->Auth->allow(); $result = $this->Controller->Auth->startup($this->Controller); $this->assertTrue($result, 'startup() should return true, as action is allowed. %s'); $url = '/auth_test/camelCase'; $this->Controller->request->addParams(Router::parse($url)); $this->Controller->request->query['url'] = Router::normalize($url); $this->Controller->Auth->initialize($this->Controller); $this->Controller->Auth->loginAction = array('controller' => 'AuthTest', 'action' => 'login'); $this->Controller->Auth->userModel = 'AuthUser'; $this->Controller->Auth->allowedActions = array('delete', 'camelCase', 'add'); $result = $this->Controller->Auth->startup($this->Controller); $this->assertTrue($result, 'startup() should return true, as action is allowed. %s'); $this->Controller->Auth->allowedActions = array('delete', 'add'); $result = $this->Controller->Auth->startup($this->Controller); $this->assertFalse($result, 'startup() should return false, as action is not allowed. %s'); $url = '/auth_test/delete'; $this->Controller->request->addParams(Router::parse($url)); $this->Controller->request->query['url'] = Router::normalize($url); $this->Controller->Auth->initialize($this->Controller); $this->Controller->Auth->loginAction = array('controller' => 'AuthTest', 'action' => 'login'); $this->Controller->Auth->userModel = 'AuthUser'; $this->Controller->Auth->allow(array('delete', 'add')); $result = $this->Controller->Auth->startup($this->Controller); $this->assertTrue($result, 'startup() should return true, as action is allowed. %s'); } public function testAllowedActionsSetWithAllowMethod() { $url = '/auth_test/action_name'; $this->Controller->request->addParams(Router::parse($url)); $this->Controller->request->query['url'] = Router::normalize($url); $this->Controller->Auth->initialize($this->Controller); $this->Controller->Auth->allow('action_name', 'anotherAction'); $this->assertEquals(array('action_name', 'anotherAction'), $this->Controller->Auth->allowedActions); } /** * testLoginRedirect method * * @return void */ public function testLoginRedirect() { $_SERVER['HTTP_REFERER'] = false; $_ENV['HTTP_REFERER'] = false; putenv('HTTP_REFERER='); $this->Auth->Session->write('Auth', array( 'AuthUser' => array('id' => '1', 'username' => 'nate') )); $this->Auth->request->addParams(Router::parse('users/login')); $this->Auth->request->url = 'users/login'; $this->Auth->initialize($this->Controller); $this->Auth->loginRedirect = array( 'controller' => 'pages', 'action' => 'display', 'welcome' ); $this->Auth->startup($this->Controller); $expected = Router::normalize($this->Auth->loginRedirect); $this->assertEquals($expected, $this->Auth->redirectUrl()); $this->Auth->Session->delete('Auth'); //empty referer no session $_SERVER['HTTP_REFERER'] = false; $_ENV['HTTP_REFERER'] = false; putenv('HTTP_REFERER='); $url = '/posts/view/1'; $this->Auth->Session->write('Auth', array( 'AuthUser' => array('id' => '1', 'username' => 'nate')) ); $this->Controller->testUrl = null; $this->Auth->request->addParams(Router::parse($url)); array_push($this->Controller->methods, 'view', 'edit', 'index'); $this->Auth->initialize($this->Controller); $this->Auth->authorize = 'controller'; $this->Auth->loginAction = array( 'controller' => 'AuthTest', 'action' => 'login' ); $this->Auth->startup($this->Controller); $expected = Router::normalize('/AuthTest/login'); $this->assertEquals($expected, $this->Controller->testUrl); $this->Auth->Session->delete('Auth'); $_SERVER['HTTP_REFERER'] = $_ENV['HTTP_REFERER'] = Router::url('/admin', true); $this->Auth->Session->write('Auth', array( 'AuthUser' => array('id' => '1', 'username' => 'nate') )); $this->Auth->request->params['action'] = 'login'; $this->Auth->request->url = 'auth_test/login'; $this->Auth->initialize($this->Controller); $this->Auth->loginAction = 'auth_test/login'; $this->Auth->loginRedirect = false; $this->Auth->startup($this->Controller); $expected = Router::normalize('/admin'); $this->assertEquals($expected, $this->Auth->redirectUrl()); // Ticket #4750 // Named Parameters $this->Controller->request = $this->Auth->request; $this->Auth->Session->delete('Auth'); $url = '/posts/index/year:2008/month:feb'; $this->Auth->request->addParams(Router::parse($url)); $this->Auth->request->url = $this->Auth->request->here = Router::normalize($url); $this->Auth->initialize($this->Controller); $this->Auth->loginAction = array('controller' => 'AuthTest', 'action' => 'login'); $this->Auth->startup($this->Controller); $expected = Router::normalize('posts/index/year:2008/month:feb'); $this->assertEquals($expected, $this->Auth->Session->read('Auth.redirect')); // Passed Arguments $this->Auth->Session->delete('Auth'); $url = '/posts/view/1'; $this->Auth->request->addParams(Router::parse($url)); $this->Auth->request->url = $this->Auth->request->here = Router::normalize($url); $this->Auth->initialize($this->Controller); $this->Auth->loginAction = array('controller' => 'AuthTest', 'action' => 'login'); $this->Auth->startup($this->Controller); $expected = Router::normalize('posts/view/1'); $this->assertEquals($expected, $this->Auth->Session->read('Auth.redirect')); // QueryString parameters $_back = $_GET; $_GET = array( 'print' => 'true', 'refer' => 'menu' ); $this->Auth->Session->delete('Auth'); $url = '/posts/index/29'; $this->Auth->request->addParams(Router::parse($url)); $this->Auth->request->url = $this->Auth->request->here = Router::normalize($url); $this->Auth->request->query = $_GET; $this->Auth->initialize($this->Controller); $this->Auth->loginAction = array('controller' => 'AuthTest', 'action' => 'login'); $this->Auth->startup($this->Controller); $expected = Router::normalize('posts/index/29?print=true&refer=menu'); $this->assertEquals($expected, $this->Auth->Session->read('Auth.redirect')); // Different base urls. $appConfig = Configure::read('App'); $_GET = array(); Configure::write('App', array( 'dir' => APP_DIR, 'webroot' => WEBROOT_DIR, 'base' => false, 'baseUrl' => '/cake/index.php' )); $this->Auth->Session->delete('Auth'); $url = '/posts/add'; $this->Auth->request = $this->Controller->request = new CakeRequest($url); $this->Auth->request->addParams(Router::parse($url)); $this->Auth->request->url = Router::normalize($url); $this->Auth->initialize($this->Controller); $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login'); $this->Auth->startup($this->Controller); $expected = Router::normalize('/posts/add'); $this->assertEquals($expected, $this->Auth->Session->read('Auth.redirect')); $this->Auth->Session->delete('Auth'); Configure::write('App', $appConfig); $_GET = $_back; // External Authed Action $_SERVER['HTTP_REFERER'] = 'http://webmail.example.com/view/message'; $this->Auth->Session->delete('Auth'); $url = '/posts/edit/1'; $request = new CakeRequest($url); $request->query = array(); $this->Auth->request = $this->Controller->request = $request; $this->Auth->request->addParams(Router::parse($url)); $this->Auth->request->url = $this->Auth->request->here = Router::normalize($url); $this->Auth->initialize($this->Controller); $this->Auth->loginAction = array('controller' => 'AuthTest', 'action' => 'login'); $this->Auth->startup($this->Controller); $expected = Router::normalize('/posts/edit/1'); $this->assertEquals($expected, $this->Auth->Session->read('Auth.redirect')); // External Direct Login Link $_SERVER['HTTP_REFERER'] = 'http://webmail.example.com/view/message'; $this->Auth->Session->delete('Auth'); $url = '/AuthTest/login'; $this->Auth->request = $this->Controller->request = new CakeRequest($url); $this->Auth->request->addParams(Router::parse($url)); $this->Auth->request->url = Router::normalize($url); $this->Auth->initialize($this->Controller); $this->Auth->loginAction = array('controller' => 'AuthTest', 'action' => 'login'); $this->Auth->startup($this->Controller); $expected = Router::normalize('/'); $this->assertEquals($expected, $this->Auth->Session->read('Auth.redirect')); $this->Auth->Session->delete('Auth'); } /** * testNoLoginRedirectForAuthenticatedUser method * * @return void */ public function testNoLoginRedirectForAuthenticatedUser() { $this->Controller->request['controller'] = 'auth_test'; $this->Controller->request['action'] = 'login'; $this->Controller->here = '/auth_test/login'; $this->Auth->request->url = 'auth_test/login'; $this->Auth->Session->write('Auth.User.id', '1'); $this->Auth->authenticate = array('Form'); $this->getMock('BaseAuthorize', array('authorize'), array(), 'NoLoginRedirectMockAuthorize', false); $this->Auth->authorize = array('NoLoginRedirectMockAuthorize'); $this->Auth->loginAction = array('controller' => 'auth_test', 'action' => 'login'); $return = $this->Auth->startup($this->Controller); $this->assertTrue($return); $this->assertNull($this->Controller->testUrl); } /** * Default to loginRedirect, if set, on authError. * * @return void */ public function testDefaultToLoginRedirect() { $_SERVER['HTTP_REFERER'] = false; $_ENV['HTTP_REFERER'] = false; putenv('HTTP_REFERER='); $url = '/party/on'; $this->Auth->request = $CakeRequest = new CakeRequest($url); $this->Auth->request->addParams(Router::parse($url)); $this->Auth->authorize = array('Controller'); $this->Auth->login(array('username' => 'mariano', 'password' => 'cake')); $this->Auth->loginRedirect = array( 'controller' => 'something', 'action' => 'else', ); $CakeResponse = new CakeResponse(); $Controller = $this->getMock( 'Controller', array('on', 'redirect'), array($CakeRequest, $CakeResponse) ); $expected = Router::url($this->Auth->loginRedirect); $Controller->expects($this->once()) ->method('redirect') ->with($this->equalTo($expected)); $this->Auth->startup($Controller); } /** * testRedirectToUnauthorizedRedirect * * @return void */ public function testRedirectToUnauthorizedRedirect() { $url = '/party/on'; $this->Auth->request = $CakeRequest = new CakeRequest($url); $this->Auth->request->addParams(Router::parse($url)); $this->Auth->authorize = array('Controller'); $this->Auth->login(array('username' => 'admad', 'password' => 'cake')); $this->Auth->unauthorizedRedirect = array( 'controller' => 'no_can_do', 'action' => 'jack' ); $CakeResponse = new CakeResponse(); $Controller = $this->getMock( 'Controller', array('on', 'redirect'), array($CakeRequest, $CakeResponse) ); $this->Auth->Flash = $this->getMock( 'FlashComponent', array('set'), array($Controller->Components) ); $expected = array( 'controller' => 'no_can_do', 'action' => 'jack' ); $Controller->expects($this->once()) ->method('redirect') ->with($this->equalTo($expected)); $this->Auth->Flash->expects($this->once()) ->method('set'); $this->Auth->startup($Controller); } /** * testRedirectToUnauthorizedRedirectSuppressedAuthError * * @return void */ public function testRedirectToUnauthorizedRedirectSuppressedAuthError() { $url = '/party/on'; $this->Auth->request = $CakeRequest = new CakeRequest($url); $this->Auth->request->addParams(Router::parse($url)); $this->Auth->authorize = array('Controller'); $this->Auth->login(array('username' => 'admad', 'password' => 'cake')); $this->Auth->unauthorizedRedirect = array( 'controller' => 'no_can_do', 'action' => 'jack' ); $this->Auth->authError = false; $CakeResponse = new CakeResponse(); $Controller = $this->getMock( 'Controller', array('on', 'redirect'), array($CakeRequest, $CakeResponse) ); $this->Auth->Flash = $this->getMock( 'FlashComponent', array('set'), array($Controller->Components) ); $expected = array( 'controller' => 'no_can_do', 'action' => 'jack' ); $Controller->expects($this->once()) ->method('redirect') ->with($this->equalTo($expected)); $this->Auth->Flash->expects($this->never()) ->method('set'); $this->Auth->startup($Controller); } /** * Throw ForbiddenException if AuthComponent::$unauthorizedRedirect set to false * @expectedException ForbiddenException * @return void */ public function testForbiddenException() { $url = '/party/on'; $this->Auth->request = $CakeRequest = new CakeRequest($url); $this->Auth->request->addParams(Router::parse($url)); $this->Auth->authorize = array('Controller'); $this->Auth->authorize = array('Controller'); $this->Auth->unauthorizedRedirect = false; $this->Auth->login(array('username' => 'baker', 'password' => 'cake')); $CakeResponse = new CakeResponse(); $Controller = $this->getMock( 'Controller', array('on', 'redirect'), array($CakeRequest, $CakeResponse) ); $this->Auth->startup($Controller); } /** * Test that no redirects or authorization tests occur on the loginAction * * @return void */ public function testNoRedirectOnLoginAction() { $controller = $this->getMock('Controller'); $controller->methods = array('login'); $url = '/AuthTest/login'; $this->Auth->request = $controller->request = new CakeRequest($url); $this->Auth->request->addParams(Router::parse($url)); $this->Auth->loginAction = array('controller' => 'AuthTest', 'action' => 'login'); $this->Auth->authorize = array('Controller'); $controller->expects($this->never()) ->method('redirect'); $this->Auth->startup($controller); } /** * Ensure that no redirect is performed when a 404 is reached * And the user doesn't have a session. * * @return void */ public function testNoRedirectOn404() { $this->Auth->Session->delete('Auth'); $this->Auth->initialize($this->Controller); $this->Auth->request->addParams(Router::parse('auth_test/something_totally_wrong')); $result = $this->Auth->startup($this->Controller); $this->assertTrue($result, 'Auth redirected a missing action %s'); } /** * testAdminRoute method * * @return void */ public function testAdminRoute() { $pref = Configure::read('Routing.prefixes'); Configure::write('Routing.prefixes', array('admin')); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; $url = '/admin/auth_test/add'; $this->Auth->request->addParams(Router::parse($url)); $this->Auth->request->query['url'] = ltrim($url, '/'); $this->Auth->request->base = ''; Router::setRequestInfo($this->Auth->request); $this->Auth->initialize($this->Controller); $this->Auth->loginAction = array( 'admin' => true, 'controller' => 'auth_test', 'action' => 'login' ); $this->Auth->startup($this->Controller); $this->assertEquals('/admin/auth_test/login', $this->Controller->testUrl); Configure::write('Routing.prefixes', $pref); } /** * testAjaxLogin method * * @return void */ public function testAjaxLogin() { App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; App::uses('Dispatcher', 'Routing'); $Response = new CakeResponse(); ob_start(); $Dispatcher = new Dispatcher(); $Dispatcher->dispatch(new CakeRequest('/ajax_auth/add'), $Response, array('return' => 1)); $result = ob_get_clean(); $this->assertEquals(403, $Response->statusCode()); $this->assertEquals("Ajax!\nthis is the test element", str_replace("\r\n", "\n", $result)); unset($_SERVER['HTTP_X_REQUESTED_WITH']); } /** * testAjaxLoginResponseCode * * @return void */ public function testAjaxLoginResponseCode() { App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; $url = '/ajax_auth/add'; $this->Auth->request->addParams(Router::parse($url)); $this->Auth->request->query['url'] = ltrim($url, '/'); $this->Auth->request->base = ''; $this->Auth->ajaxLogin = 'test_element'; Router::setRequestInfo($this->Auth->request); $this->Controller->response = $this->getMock('CakeResponse', array('_sendHeader')); $this->Controller->response->expects($this->at(0)) ->method('_sendHeader') ->with('HTTP/1.1 403 Forbidden', null); $this->Auth->initialize($this->Controller); ob_start(); $result = $this->Auth->startup($this->Controller); ob_end_clean(); $this->assertFalse($result); $this->assertEquals('this is the test element', $this->Controller->response->body()); $this->assertArrayNotHasKey('Location', $this->Controller->response->header()); $this->assertNull($this->Controller->testUrl, 'redirect() not called'); unset($_SERVER['HTTP_X_REQUESTED_WITH']); } /** * test ajax login with no element * * @return void */ public function testAjaxLoginResponseCodeNoElement() { $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; $url = '/ajax_auth/add'; $this->Auth->request->addParams(Router::parse($url)); $this->Auth->request->query['url'] = ltrim($url, '/'); $this->Auth->request->base = ''; $this->Auth->ajaxLogin = false; Router::setRequestInfo($this->Auth->request); $this->Controller->response = $this->getMock('CakeResponse', array('_sendHeader')); $this->Controller->response->expects($this->at(0)) ->method('_sendHeader') ->with('HTTP/1.1 403 Forbidden', null); $this->Auth->initialize($this->Controller); $this->Auth->startup($this->Controller); $this->assertArrayNotHasKey('Location', $this->Controller->response->header()); $this->assertNull($this->Controller->testUrl, 'redirect() not called'); unset($_SERVER['HTTP_X_REQUESTED_WITH']); } /** * testLoginActionRedirect method * * @return void */ public function testLoginActionRedirect() { $admin = Configure::read('Routing.prefixes'); Configure::write('Routing.prefixes', array('admin')); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; $url = '/admin/auth_test/login'; $this->Auth->request->addParams(Router::parse($url)); $this->Auth->request->url = ltrim($url, '/'); Router::setRequestInfo(array( array( 'pass' => array(), 'action' => 'admin_login', 'plugin' => null, 'controller' => 'auth_test', 'admin' => true, ), array( 'base' => null, 'here' => $url, 'webroot' => '/', 'passedArgs' => array(), ) )); $this->Auth->initialize($this->Controller); $this->Auth->loginAction = array('admin' => true, 'controller' => 'auth_test', 'action' => 'login'); $this->Auth->startup($this->Controller); $this->assertNull($this->Controller->testUrl); Configure::write('Routing.prefixes', $admin); } /** * Stateless auth methods like Basic should populate data that can be * accessed by $this->user(). * * @return void */ public function testStatelessAuthWorksWithUser() { $_SERVER['PHP_AUTH_USER'] = 'mariano'; $_SERVER['PHP_AUTH_PW'] = 'cake'; $url = '/auth_test/add'; $this->Auth->request->addParams(Router::parse($url)); $this->Auth->authenticate = array( 'Basic' => array('userModel' => 'AuthUser') ); $this->Auth->startup($this->Controller); $result = $this->Auth->user(); $this->assertEquals('mariano', $result['username']); $result = $this->Auth->user('username'); $this->assertEquals('mariano', $result); } /** * test $settings in Controller::$components * * @return void */ public function testComponentSettings() { $request = new CakeRequest(null, false); $this->Controller = new AuthTestController($request, $this->getMock('CakeResponse')); $this->Controller->components = array( 'Auth' => array( 'loginAction' => array('controller' => 'people', 'action' => 'login'), 'logoutRedirect' => array('controller' => 'people', 'action' => 'login'), ), 'Session' ); $this->Controller->Components->init($this->Controller); $this->Controller->Components->trigger('initialize', array(&$this->Controller)); Router::reload(); $expected = array( 'loginAction' => array('controller' => 'people', 'action' => 'login'), 'logoutRedirect' => array('controller' => 'people', 'action' => 'login'), ); $this->assertEquals($expected['loginAction'], $this->Controller->Auth->loginAction); $this->assertEquals($expected['logoutRedirect'], $this->Controller->Auth->logoutRedirect); } /** * test that logout deletes the session variables. and returns the correct URL * * @return void */ public function testLogout() { $this->Auth->Session->write('Auth.User.id', '1'); $this->Auth->Session->write('Auth.redirect', '/users/login'); $this->Auth->logoutRedirect = '/'; $result = $this->Auth->logout(); $this->assertEquals('/', $result); $this->assertNull($this->Auth->Session->read('Auth.AuthUser')); $this->assertNull($this->Auth->Session->read('Auth.redirect')); } /** * Logout should trigger a logout method on authentication objects. * * @return void */ public function testLogoutTrigger() { $LogoutTriggerMockAuthenticate = $this->getMock('BaseAuthenticate', array('authenticate', 'logout'), array(), '', false); $this->Auth->authenticate = array('LogoutTriggerMock'); $this->Auth->setAuthenticateObject(0, $LogoutTriggerMockAuthenticate); $LogoutTriggerMockAuthenticate->expects($this->once()) ->method('logout'); $this->Auth->logout(); } /** * Test mapActions as a getter * * @return void */ public function testMapActions() { $MapActionMockAuthorize = $this->getMock( 'BaseAuthorize', array('authorize'), array(), '', false ); $this->Auth->authorize = array('MapActionAuthorize'); $this->Auth->setAuthorizeObject(0, $MapActionMockAuthorize); $actions = array('my_action' => 'create'); $this->Auth->mapActions($actions); $actions = array( 'create' => array('my_other_action'), 'update' => array('updater') ); $this->Auth->mapActions($actions); $actions = $this->Auth->mapActions(); $result = $actions['my_action']; $expected = 'create'; $this->assertEquals($expected, $result); $result = $actions['my_other_action']; $expected = 'create'; $this->assertEquals($expected, $result); $result = $actions['updater']; $expected = 'update'; $this->assertEquals($expected, $result); } /** * test mapActions loading and delegating to authorize objects. * * @return void */ public function testMapActionsDelegation() { $MapActionMockAuthorize = $this->getMock('BaseAuthorize', array('authorize', 'mapActions'), array(), '', false); $this->Auth->authorize = array('MapActionMock'); $this->Auth->setAuthorizeObject(0, $MapActionMockAuthorize); $MapActionMockAuthorize->expects($this->once()) ->method('mapActions') ->with(array('create' => array('my_action'))); $this->Auth->mapActions(array('create' => array('my_action'))); } /** * test logging in with a request. * * @return void */ public function testLoginWithRequestData() { $RequestLoginMockAuthenticate = $this->getMock('FormAuthenticate', array(), array(), '', false); $request = new CakeRequest('users/login', false); $user = array('username' => 'mark', 'role' => 'admin'); $this->Auth->request = $request; $this->Auth->authenticate = array('RequestLoginMock'); $this->Auth->setAuthenticateObject(0, $RequestLoginMockAuthenticate); $RequestLoginMockAuthenticate->expects($this->once()) ->method('authenticate') ->with($request) ->will($this->returnValue($user)); $this->assertTrue($this->Auth->login()); $this->assertEquals($user['username'], $this->Auth->user('username')); } /** * test login() with user data * * @return void */ public function testLoginWithUserData() { $this->assertFalse($this->Auth->loggedIn()); $user = array( 'username' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ); $this->assertTrue($this->Auth->login($user)); $this->assertTrue($this->Auth->loggedIn()); $this->assertEquals($user['username'], $this->Auth->user('username')); } /** * test flash settings. * * @return void */ public function testFlashSettings() { $this->Auth->Flash = $this->getMock('FlashComponent', array(), array(), '', false); $this->Auth->Flash->expects($this->once()) ->method('set') ->with('Auth failure', array('element' => 'custom', 'params' => array(1), 'key' => 'auth-key')); $this->Auth->flash = array( 'element' => 'custom', 'params' => array(1), 'key' => 'auth-key' ); $this->Auth->flash('Auth failure'); } /** * test the various states of Auth::redirect() * * @return void */ public function testRedirectSet() { $value = array('controller' => 'users', 'action' => 'home'); $result = $this->Auth->redirectUrl($value); $this->assertEquals('/users/home', $result); $this->assertEquals($value, $this->Auth->Session->read('Auth.redirect')); } /** * test redirect using Auth.redirect from the session. * * @return void */ public function testRedirectSessionRead() { $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login'); $this->Auth->Session->write('Auth.redirect', '/users/home'); $result = $this->Auth->redirectUrl(); $this->assertEquals('/users/home', $result); $this->assertFalse($this->Auth->Session->check('Auth.redirect')); } /** * test redirectUrl with duplicate base. * * @return void */ public function testRedirectSessionReadDuplicateBase() { $this->Auth->request->webroot = '/waves/'; $this->Auth->request->base = '/waves'; Router::setRequestInfo($this->Auth->request); $this->Auth->Session->write('Auth.redirect', '/waves/add'); $result = $this->Auth->redirectUrl(); $this->assertEquals('/waves/add', $result); } /** * test that redirect does not return loginAction if that is what's stored in Auth.redirect. * instead loginRedirect should be used. * * @return void */ public function testRedirectSessionReadEqualToLoginAction() { $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login'); $this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'home'); $this->Auth->Session->write('Auth.redirect', array('controller' => 'users', 'action' => 'login')); $result = $this->Auth->redirectUrl(); $this->assertEquals('/users/home', $result); $this->assertFalse($this->Auth->Session->check('Auth.redirect')); } /** * test that the returned URL doesn't contain the base URL. * * @see https://cakephp.lighthouseapp.com/projects/42648/tickets/3922-authcomponentredirecturl-prepends-appbaseurl * * @return void This test method doesn't return anything. */ public function testRedirectUrlWithBaseSet() { $App = Configure::read('App'); Configure::write('App', array( 'dir' => APP_DIR, 'webroot' => WEBROOT_DIR, 'base' => false, 'baseUrl' => '/cake/index.php' )); $url = '/users/login'; $this->Auth->request = $this->Controller->request = new CakeRequest($url); $this->Auth->request->addParams(Router::parse($url)); $this->Auth->request->url = Router::normalize($url); Router::setRequestInfo($this->Auth->request); $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login'); $this->Auth->loginRedirect = array('controller' => 'users', 'action' => 'home'); $result = $this->Auth->redirectUrl(); $this->assertEquals('/users/home', $result); $this->assertFalse($this->Auth->Session->check('Auth.redirect')); Configure::write('App', $App); Router::reload(); } /** * test password hashing * * @return void */ public function testPassword() { $result = $this->Auth->password('password'); $expected = Security::hash('password', null, true); $this->assertEquals($expected, $result); } /** * testUser method * * @return void */ public function testUser() { $data = array( 'User' => array( 'id' => '2', 'username' => 'mark', 'group_id' => 1, 'Group' => array( 'id' => '1', 'name' => 'Members' ), 'is_admin' => false, )); $this->Auth->Session->write('Auth', $data); $result = $this->Auth->user(); $this->assertEquals($data['User'], $result); $result = $this->Auth->user('username'); $this->assertEquals($data['User']['username'], $result); $result = $this->Auth->user('Group.name'); $this->assertEquals($data['User']['Group']['name'], $result); $result = $this->Auth->user('invalid'); $this->assertEquals(null, $result); $result = $this->Auth->user('Company.invalid'); $this->assertEquals(null, $result); $result = $this->Auth->user('is_admin'); $this->assertFalse($result); } /** * testStatelessAuthNoRedirect method * * @expectedException UnauthorizedException * @expectedExceptionCode 401 * @return void */ public function testStatelessAuthNoRedirect() { if (CakeSession::id()) { session_destroy(); CakeSession::$id = null; } $_SESSION = null; AuthComponent::$sessionKey = false; $this->Auth->authenticate = array('Basic'); $this->Controller->request['action'] = 'admin_add'; $this->Auth->startup($this->Controller); } /** * testStatelessAuthNoSessionStart method * * @return void */ public function testStatelessAuthNoSessionStart() { if (CakeSession::id()) { session_destroy(); CakeSession::$id = null; } $_SESSION = null; $_SERVER['PHP_AUTH_USER'] = 'mariano'; $_SERVER['PHP_AUTH_PW'] = 'cake'; AuthComponent::$sessionKey = false; $this->Auth->authenticate = array( 'Basic' => array('userModel' => 'AuthUser') ); $this->Controller->request['action'] = 'admin_add'; $result = $this->Auth->startup($this->Controller); $this->assertTrue($result); $this->assertNull(CakeSession::id()); } /** * testStatelessAuthRedirect method * * @return void */ public function testStatelessFollowedByStatefulAuth() { $this->Auth->authenticate = array('Basic', 'Form'); $this->Controller->request['action'] = 'admin_add'; $this->Auth->response->expects($this->never())->method('statusCode'); $this->Auth->response->expects($this->never())->method('send'); $result = $this->Auth->startup($this->Controller); $this->assertFalse($result); $this->assertEquals('/users/login', $this->Controller->testUrl); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/CookieComponentTest.php000066400000000000000000000531261265552240500271060ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Controller.Component * @since CakePHP(tm) v 1.2.0.5435 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Component', 'Controller'); App::uses('Controller', 'Controller'); App::uses('CookieComponent', 'Controller/Component'); /** * CookieComponentTestController class * * @package Cake.Test.Case.Controller.Component */ class CookieComponentTestController extends Controller { /** * components property * * @var array */ public $components = array('Cookie'); /** * beforeFilter method * * @return void */ public function beforeFilter() { $this->Cookie->name = 'CakeTestCookie'; $this->Cookie->time = 10; $this->Cookie->path = '/'; $this->Cookie->domain = ''; $this->Cookie->secure = false; $this->Cookie->key = 'somerandomhaskey'; } } /** * CookieComponentTest class * * @package Cake.Test.Case.Controller.Component */ class CookieComponentTest extends CakeTestCase { /** * Controller property * * @var CookieComponentTestController */ public $Controller; /** * start * * @return void */ public function setUp() { parent::setUp(); $_COOKIE = array(); $this->Controller = new CookieComponentTestController(new CakeRequest(), new CakeResponse()); $this->Controller->constructClasses(); $this->Cookie = $this->Controller->Cookie; $this->Cookie->name = 'CakeTestCookie'; $this->Cookie->time = 10; $this->Cookie->path = '/'; $this->Cookie->domain = ''; $this->Cookie->secure = false; $this->Cookie->key = 'somerandomhaskey'; $this->Cookie->startup($this->Controller); } /** * end * * @return void */ public function tearDown() { parent::tearDown(); $this->Cookie->destroy(); } /** * sets up some default cookie data. * * @return void */ protected function _setCookieData() { $this->Cookie->write(array('Encrytped_array' => array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'))); $this->Cookie->write(array('Encrytped_multi_cookies.name' => 'CakePHP')); $this->Cookie->write(array('Encrytped_multi_cookies.version' => '1.2.0.x')); $this->Cookie->write(array('Encrytped_multi_cookies.tag' => 'CakePHP Rocks!')); $this->Cookie->write(array('Plain_array' => array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!')), null, false); $this->Cookie->write(array('Plain_multi_cookies.name' => 'CakePHP'), null, false); $this->Cookie->write(array('Plain_multi_cookies.version' => '1.2.0.x'), null, false); $this->Cookie->write(array('Plain_multi_cookies.tag' => 'CakePHP Rocks!'), null, false); } /** * test that initialize sets settings from components array * * @return void */ public function testSettings() { $settings = array( 'time' => '5 days', 'path' => '/' ); $Cookie = new CookieComponent(new ComponentCollection(), $settings); $this->assertEquals($Cookie->time, $settings['time']); $this->assertEquals($Cookie->path, $settings['path']); } /** * testCookieName * * @return void */ public function testCookieName() { $this->assertEquals('CakeTestCookie', $this->Cookie->name); } /** * testReadEncryptedCookieData * * @return void */ public function testReadEncryptedCookieData() { $this->_setCookieData(); $data = $this->Cookie->read('Encrytped_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); } /** * testReadPlainCookieData * * @return void */ public function testReadPlainCookieData() { $this->_setCookieData(); $data = $this->Cookie->read('Plain_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); } /** * test read() after switching the cookie name. * * @return void */ public function testReadWithNameSwitch() { $_COOKIE = array( 'CakeTestCookie' => array( 'key' => 'value' ), 'OtherTestCookie' => array( 'key' => 'other value' ) ); $this->assertEquals('value', $this->Cookie->read('key')); $this->Cookie->name = 'OtherTestCookie'; $this->assertEquals('other value', $this->Cookie->read('key')); } /** * test a simple write() * * @return void */ public function testWriteSimple() { $this->Cookie->write('Testing', 'value'); $result = $this->Cookie->read('Testing'); $this->assertEquals('value', $result); } /** * test write() encrypted data with falsey value * * @return void */ public function testWriteWithFalseyValue() { $this->Cookie->type('aes'); $this->Cookie->key = 'qSI232qs*&sXOw!adre@34SAv!@*(XSL#$%)asGb$@11~_+!@#HKis~#^'; $this->Cookie->write('Testing'); $result = $this->Cookie->read('Testing'); $this->assertNull($result); $this->Cookie->write('Testing', ''); $result = $this->Cookie->read('Testing'); $this->assertEquals('', $result); $this->Cookie->write('Testing', false); $result = $this->Cookie->read('Testing'); $this->assertFalse($result); $this->Cookie->write('Testing', 1); $result = $this->Cookie->read('Testing'); $this->assertEquals(1, $result); $this->Cookie->write('Testing', '0'); $result = $this->Cookie->read('Testing'); $this->assertSame('0', $result); $this->Cookie->write('Testing', 0); $result = $this->Cookie->read('Testing'); $this->assertSame(0, $result); } /** * test that two write() calls use the expiry. * * @return void */ public function testWriteMultipleShareExpiry() { $this->Cookie->write('key1', 'value1', false); $this->Cookie->write('key2', 'value2', false); $name = $this->Cookie->name . '[key1]'; $result = $this->Controller->response->cookie($name); $this->assertWithinMargin(time() + 10, $result['expire'], 2, 'Expiry time is wrong'); $name = $this->Cookie->name . '[key2]'; $result = $this->Controller->response->cookie($name); $this->assertWithinMargin(time() + 10, $result['expire'], 2, 'Expiry time is wrong'); } /** * test write with distant future cookies * * @return void */ public function testWriteFarFuture() { $this->Cookie->write('Testing', 'value', false, '+90 years'); $future = new DateTime('now'); $future->modify('+90 years'); $expected = array( 'name' => $this->Cookie->name . '[Testing]', 'value' => 'value', 'path' => '/', 'domain' => '', 'secure' => false, 'httpOnly' => false); $result = $this->Controller->response->cookie($this->Cookie->name . '[Testing]'); $this->assertEquals($future->format('U'), $result['expire'], '', 3); unset($result['expire']); $this->assertEquals($expected, $result); } /** * test write with httpOnly cookies * * @return void */ public function testWriteHttpOnly() { $this->Cookie->httpOnly = true; $this->Cookie->secure = false; $this->Cookie->write('Testing', 'value', false); $expected = array( 'name' => $this->Cookie->name . '[Testing]', 'value' => 'value', 'expire' => time() + 10, 'path' => '/', 'domain' => '', 'secure' => false, 'httpOnly' => true); $result = $this->Controller->response->cookie($this->Cookie->name . '[Testing]'); $this->assertEquals($expected, $result); } /** * test delete with httpOnly * * @return void */ public function testDeleteHttpOnly() { $this->Cookie->httpOnly = true; $this->Cookie->secure = false; $this->Cookie->delete('Testing', false); $expected = array( 'name' => $this->Cookie->name . '[Testing]', 'value' => '', 'expire' => time() - 42000, 'path' => '/', 'domain' => '', 'secure' => false, 'httpOnly' => true); $result = $this->Controller->response->cookie($this->Cookie->name . '[Testing]'); $this->assertEquals($expected, $result); } /** * testWritePlainCookieArray * * @return void */ public function testWritePlainCookieArray() { $this->Cookie->write(array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'), null, false); $this->assertEquals('CakePHP', $this->Cookie->read('name')); $this->assertEquals('1.2.0.x', $this->Cookie->read('version')); $this->assertEquals('CakePHP Rocks!', $this->Cookie->read('tag')); $this->Cookie->delete('name'); $this->Cookie->delete('version'); $this->Cookie->delete('tag'); } /** * test writing values that are not scalars * * @return void */ public function testWriteArrayValues() { $this->Cookie->secure = false; $this->Cookie->write('Testing', array(1, 2, 3), false); $expected = array( 'name' => $this->Cookie->name . '[Testing]', 'value' => '[1,2,3]', 'path' => '/', 'domain' => '', 'secure' => false, 'httpOnly' => false); $result = $this->Controller->response->cookie($this->Cookie->name . '[Testing]'); $this->assertWithinMargin($result['expire'], time() + 10, 1); unset($result['expire']); $this->assertEquals($expected, $result); } /** * Test that writing mixed arrays results in the correct data. * * @return void */ public function testWriteMixedArray() { $this->Cookie->encrypt = false; $this->Cookie->write('User', array('name' => 'mark'), false); $this->Cookie->write('User.email', 'mark@example.com', false); $expected = array( 'name' => $this->Cookie->name . '[User]', 'value' => '{"name":"mark","email":"mark@example.com"}', 'path' => '/', 'domain' => '', 'secure' => false, 'httpOnly' => false ); $result = $this->Controller->response->cookie($this->Cookie->name . '[User]'); unset($result['expire']); $this->assertEquals($expected, $result); $this->Cookie->write('User.email', 'mark@example.com', false); $this->Cookie->write('User', array('name' => 'mark'), false); $expected = array( 'name' => $this->Cookie->name . '[User]', 'value' => '{"name":"mark"}', 'path' => '/', 'domain' => '', 'secure' => false, 'httpOnly' => false ); $result = $this->Controller->response->cookie($this->Cookie->name . '[User]'); unset($result['expire']); $this->assertEquals($expected, $result); } /** * testReadingCookieValue * * @return void */ public function testReadingCookieValue() { $this->_setCookieData(); $data = $this->Cookie->read(); $expected = array( 'Encrytped_array' => array( 'name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'), 'Encrytped_multi_cookies' => array( 'name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'), 'Plain_array' => array( 'name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'), 'Plain_multi_cookies' => array( 'name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!')); $this->assertEquals($expected, $data); } /** * testDeleteCookieValue * * @return void */ public function testDeleteCookieValue() { $this->_setCookieData(); $this->Cookie->delete('Encrytped_multi_cookies.name'); $data = $this->Cookie->read('Encrytped_multi_cookies'); $expected = array('version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); $this->Cookie->delete('Encrytped_array'); $data = $this->Cookie->read('Encrytped_array'); $this->assertNull($data); $this->Cookie->delete('Plain_multi_cookies.name'); $data = $this->Cookie->read('Plain_multi_cookies'); $expected = array('version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); $this->Cookie->delete('Plain_array'); $data = $this->Cookie->read('Plain_array'); $this->assertNull($data); } /** * testReadingCookieArray * * @return void */ public function testReadingCookieArray() { $this->_setCookieData(); $data = $this->Cookie->read('Encrytped_array.name'); $expected = 'CakePHP'; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_array.version'); $expected = '1.2.0.x'; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_array.tag'); $expected = 'CakePHP Rocks!'; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_multi_cookies.name'); $expected = 'CakePHP'; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_multi_cookies.version'); $expected = '1.2.0.x'; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_multi_cookies.tag'); $expected = 'CakePHP Rocks!'; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_array.name'); $expected = 'CakePHP'; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_array.version'); $expected = '1.2.0.x'; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_array.tag'); $expected = 'CakePHP Rocks!'; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_multi_cookies.name'); $expected = 'CakePHP'; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_multi_cookies.version'); $expected = '1.2.0.x'; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_multi_cookies.tag'); $expected = 'CakePHP Rocks!'; $this->assertEquals($expected, $data); } /** * testReadingCookieDataOnStartup * * @return void */ public function testReadingCookieDataOnStartup() { $data = $this->Cookie->read('Encrytped_array'); $this->assertNull($data); $data = $this->Cookie->read('Encrytped_multi_cookies'); $this->assertNull($data); $data = $this->Cookie->read('Plain_array'); $this->assertNull($data); $data = $this->Cookie->read('Plain_multi_cookies'); $this->assertNull($data); $_COOKIE['CakeTestCookie'] = array( 'Encrytped_array' => $this->_encrypt(array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!')), 'Encrytped_multi_cookies' => array( 'name' => $this->_encrypt('CakePHP'), 'version' => $this->_encrypt('1.2.0.x'), 'tag' => $this->_encrypt('CakePHP Rocks!')), 'Plain_array' => '{"name":"CakePHP","version":"1.2.0.x","tag":"CakePHP Rocks!"}', 'Plain_multi_cookies' => array( 'name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!')); $this->Cookie->startup(new CookieComponentTestController()); $data = $this->Cookie->read('Encrytped_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); $this->Cookie->destroy(); unset($_COOKIE['CakeTestCookie']); } /** * testReadingCookieDataWithoutStartup * * @return void */ public function testReadingCookieDataWithoutStartup() { $data = $this->Cookie->read('Encrytped_array'); $expected = null; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_multi_cookies'); $expected = null; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_array'); $expected = null; $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_multi_cookies'); $expected = null; $this->assertEquals($expected, $data); $_COOKIE['CakeTestCookie'] = array( 'Encrytped_array' => $this->_encrypt(array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!')), 'Encrytped_multi_cookies' => array( 'name' => $this->_encrypt('CakePHP'), 'version' => $this->_encrypt('1.2.0.x'), 'tag' => $this->_encrypt('CakePHP Rocks!')), 'Plain_array' => '{"name":"CakePHP","version":"1.2.0.x","tag":"CakePHP Rocks!"}', 'Plain_multi_cookies' => array( 'name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!')); $data = $this->Cookie->read('Encrytped_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!'); $this->assertEquals($expected, $data); $this->Cookie->destroy(); unset($_COOKIE['CakeTestCookie']); } /** * Test Reading legacy cookie values. * * @return void */ public function testReadLegacyCookieValue() { $_COOKIE['CakeTestCookie'] = array( 'Legacy' => array('value' => $this->_oldImplode(array(1, 2, 3))) ); $result = $this->Cookie->read('Legacy.value'); $expected = array(1, 2, 3); $this->assertEquals($expected, $result); } /** * Test reading empty values. * * @return void */ public function testReadEmpty() { $_COOKIE['CakeTestCookie'] = array( 'JSON' => '{"name":"value"}', 'Empty' => '', 'String' => '{"somewhat:"broken"}', 'Array' => '{}' ); $this->assertEquals(array('name' => 'value'), $this->Cookie->read('JSON')); $this->assertEquals('value', $this->Cookie->read('JSON.name')); $this->assertEquals('', $this->Cookie->read('Empty')); $this->assertEquals('{"somewhat:"broken"}', $this->Cookie->read('String')); $this->assertEquals(array(), $this->Cookie->read('Array')); } /** * test that no error is issued for non array data. * * @return void */ public function testNoErrorOnNonArrayData() { $this->Cookie->destroy(); $_COOKIE['CakeTestCookie'] = 'kaboom'; $this->assertNull($this->Cookie->read('value')); } /** * testCheck method * * @return void */ public function testCheck() { $this->Cookie->write('CookieComponentTestCase', 'value'); $this->assertTrue($this->Cookie->check('CookieComponentTestCase')); $this->assertFalse($this->Cookie->check('NotExistingCookieComponentTestCase')); } /** * testCheckingSavedEmpty method * * @return void */ public function testCheckingSavedEmpty() { $this->Cookie->write('CookieComponentTestCase', 0); $this->assertTrue($this->Cookie->check('CookieComponentTestCase')); $this->Cookie->write('CookieComponentTestCase', '0'); $this->assertTrue($this->Cookie->check('CookieComponentTestCase')); $this->Cookie->write('CookieComponentTestCase', false); $this->assertTrue($this->Cookie->check('CookieComponentTestCase')); $this->Cookie->write('CookieComponentTestCase', null); $this->assertFalse($this->Cookie->check('CookieComponentTestCase')); } /** * testCheckKeyWithSpaces method * * @return void */ public function testCheckKeyWithSpaces() { $this->Cookie->write('CookieComponent Test', "test"); $this->assertTrue($this->Cookie->check('CookieComponent Test')); $this->Cookie->delete('CookieComponent Test'); $this->Cookie->write('CookieComponent Test.Test Case', "test"); $this->assertTrue($this->Cookie->check('CookieComponent Test.Test Case')); } /** * testCheckEmpty * * @return void */ public function testCheckEmpty() { $this->assertFalse($this->Cookie->check()); } /** * test that deleting a top level keys kills the child elements too. * * @return void */ public function testDeleteRemovesChildren() { $_COOKIE['CakeTestCookie'] = array( 'User' => array('email' => 'example@example.com', 'name' => 'mark'), 'other' => 'value' ); $this->assertEquals('mark', $this->Cookie->read('User.name')); $this->Cookie->delete('User'); $this->assertNull($this->Cookie->read('User.email')); $this->Cookie->destroy(); } /** * Test deleting recursively with keys that don't exist. * * @return void */ public function testDeleteChildrenNotExist() { $this->assertNull($this->Cookie->delete('NotFound')); $this->assertNull($this->Cookie->delete('Not.Found')); } /** * Helper method for generating old style encoded cookie values. * * @return string. */ protected function _oldImplode(array $array) { $string = ''; foreach ($array as $key => $value) { $string .= ',' . $key . '|' . $value; } return substr($string, 1); } /** * Implode method to keep keys are multidimensional arrays * * @param array $array Map of key and values * @return string String in the form key1|value1,key2|value2 */ protected function _implode(array $array) { return json_encode($array); } /** * encrypt method * * @param array|string $value * @return string */ protected function _encrypt($value) { if (is_array($value)) { $value = $this->_implode($value); } return "Q2FrZQ==." . base64_encode(Security::cipher($value, $this->Cookie->key)); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/EmailComponentTest.php000066400000000000000000000765041265552240500267310ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Controller.Component * @since CakePHP(tm) v 1.2.0.5347 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Controller', 'Controller'); App::uses('EmailComponent', 'Controller/Component'); App::uses('AbstractTransport', 'Network/Email'); /** * EmailTestComponent class * * @package Cake.Test.Case.Controller.Component */ class EmailTestComponent extends EmailComponent { /** * Convenience method for testing. * * @return string */ public function strip($content, $message = false) { return parent::_strip($content, $message); } } /** * DebugCompTransport class * * @package Cake.Test.Case.Controller.Component */ class DebugCompTransport extends AbstractTransport { /** * Last email * * @var string */ public static $lastEmail = null; /** * Send mail * * @params object $email CakeEmail * @return bool */ public function send(CakeEmail $email) { $email->addHeaders(array('Date' => EmailComponentTest::$sentDate)); $headers = $email->getHeaders(array_fill_keys(array('from', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc', 'subject'), true)); $to = $headers['To']; $subject = $headers['Subject']; unset($headers['To'], $headers['Subject']); $message = implode("\n", $email->message()); $last = '
';
		$last .= sprintf("%s %s\n", 'To:', $to);
		$last .= sprintf("%s %s\n", 'From:', $headers['From']);
		$last .= sprintf("%s %s\n", 'Subject:', $subject);
		$last .= sprintf("%s\n\n%s", 'Header:', $this->_headersToString($headers, "\n"));
		$last .= sprintf("%s\n\n%s", 'Message:', $message);
		$last .= '
'; static::$lastEmail = $last; return true; } } /** * EmailTestController class * * @package Cake.Test.Case.Controller.Component */ class EmailTestController extends Controller { /** * uses property * * @var mixed */ public $uses = null; /** * components property * * @var array */ public $components = array('Session', 'EmailTest'); } /** * EmailTest class * * @package Cake.Test.Case.Controller.Component */ class EmailComponentTest extends CakeTestCase { /** * Controller property * * @var EmailTestController */ public $Controller; /** * name property * * @var string */ public $name = 'Email'; /** * sentDate * * @var string */ public static $sentDate = null; /** * setUp method * * @return void */ public function setUp() { parent::setUp(); Configure::write('App.encoding', 'UTF-8'); $this->Controller = new EmailTestController(); $this->Controller->Components->init($this->Controller); $this->Controller->EmailTest->initialize($this->Controller, array()); static::$sentDate = date(DATE_RFC2822); App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); } /** * testSendFormats method * * @return void */ public function testSendFormats() { $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake SMTP test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $this->Controller->EmailTest->messageId = false; $date = static::$sentDate; $message = <<To: postmaster@example.com From: noreply@example.com Subject: Cake SMTP test Header: From: noreply@example.com Reply-To: noreply@example.com X-Mailer: CakePHP Email Component Date: $date MIME-Version: 1.0 Content-Type: {CONTENTTYPE} Content-Transfer-Encoding: 8bitMessage: This is the body of the message MSGBLOC; $this->Controller->EmailTest->sendAs = 'text'; $expected = str_replace('{CONTENTTYPE}', 'text/plain; charset=UTF-8', $message); $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $this->assertTextEquals($expected, DebugCompTransport::$lastEmail); $this->Controller->EmailTest->sendAs = 'html'; $expected = str_replace('{CONTENTTYPE}', 'text/html; charset=UTF-8', $message); $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $this->assertTextEquals($expected, DebugCompTransport::$lastEmail); } /** * testTemplates method * * @return void */ public function testTemplates() { ClassRegistry::flush(); $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake SMTP test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->delivery = 'DebugComp'; $this->Controller->EmailTest->messageId = false; $date = static::$sentDate; $header = <<Controller->EmailTest->layout = 'default'; $this->Controller->EmailTest->template = 'default'; $this->Controller->set('title_for_layout', 'Email Test'); $text = << Email Test

This is the body of the message

This email was sent using the CakePHP Framework

HTMLBLOC; $this->Controller->EmailTest->sendAs = 'text'; $expected = '
' . str_replace('{CONTENTTYPE}', 'text/plain; charset=UTF-8', $header) . $text . "\n" . '
'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $this->assertTextEquals($expected, DebugCompTransport::$lastEmail); $this->Controller->EmailTest->sendAs = 'html'; $expected = '
' . str_replace('{CONTENTTYPE}', 'text/html; charset=UTF-8', $header) . $html . "\n" . '
'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $this->assertTextEquals($expected, DebugCompTransport::$lastEmail); $this->Controller->EmailTest->sendAs = 'both'; $expected = str_replace('{CONTENTTYPE}', 'multipart/alternative; boundary="{boundary}"', $header); $expected .= "--{boundary}\n" . 'Content-Type: text/plain; charset=UTF-8' . "\n" . 'Content-Transfer-Encoding: 8bit' . "\n\n" . $text . "\n\n" . '--{boundary}' . "\n" . 'Content-Type: text/html; charset=UTF-8' . "\n" . 'Content-Transfer-Encoding: 8bit' . "\n\n" . $html . "\n\n\n" . '--{boundary}--' . "\n"; $expected = '
' . $expected . '
'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $this->assertTextEquals( $expected, preg_replace('/[a-z0-9]{32}/i', '{boundary}', DebugCompTransport::$lastEmail) ); $html = << Email Test

This is the body of the message

This email was sent using the CakePHP Framework

HTMLBLOC; $this->Controller->EmailTest->sendAs = 'html'; $expected = '
' . str_replace('{CONTENTTYPE}', 'text/html; charset=UTF-8', $header) . $html . '
'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message', 'default', 'thin')); $this->assertTextEquals($expected, DebugCompTransport::$lastEmail); } /** * test that elements used in email templates get helpers. * * @return void */ public function testTemplateNestedElements() { $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake SMTP test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->delivery = 'DebugComp'; $this->Controller->EmailTest->messageId = false; $this->Controller->EmailTest->layout = 'default'; $this->Controller->EmailTest->template = 'nested_element'; $this->Controller->EmailTest->sendAs = 'html'; $this->Controller->helpers = array('Html'); $this->Controller->EmailTest->send(); $result = DebugCompTransport::$lastEmail; $this->assertRegExp('/Test/', $result); $this->assertRegExp('/http\:\/\/example\.com/', $result); } /** * test send with null properties * * @return void */ public function testSendNullProperties() { $this->Controller->EmailTest->to = 'test@example.com'; $this->Controller->EmailTest->from = 'test@example.com'; $this->Controller->EmailTest->subject = null; $this->Controller->EmailTest->replyTo = null; $this->Controller->EmailTest->messageId = null; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $this->assertTrue($this->Controller->EmailTest->send(null)); $result = DebugCompTransport::$lastEmail; $this->assertRegExp('/To: test@example.com\n/', $result); $this->assertRegExp('/Subject: \n/', $result); $this->assertRegExp('/From: test@example.com\n/', $result); $this->assertRegExp('/Date: ' . preg_quote(static::$sentDate) . '\n/', $result); $this->assertRegExp('/X-Mailer: CakePHP Email Component\n/', $result); $this->assertRegExp('/Content-Type: text\/plain; charset=UTF-8\n/', $result); $this->assertRegExp('/Content-Transfer-Encoding: 8bitMessage:\n/', $result); } /** * testSendDebug method * * @return void */ public function testSendDebug() { $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->cc = 'cc@example.com'; $this->Controller->EmailTest->bcc = 'bcc@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $result = DebugCompTransport::$lastEmail; $this->assertRegExp('/To: postmaster@example.com\n/', $result); $this->assertRegExp('/Subject: Cake Debug Test\n/', $result); $this->assertRegExp('/Reply-To: noreply@example.com\n/', $result); $this->assertRegExp('/From: noreply@example.com\n/', $result); $this->assertRegExp('/Cc: cc@example.com\n/', $result); $this->assertRegExp('/Bcc: bcc@example.com\n/', $result); $this->assertRegExp('/Date: ' . preg_quote(static::$sentDate) . '\n/', $result); $this->assertRegExp('/X-Mailer: CakePHP Email Component\n/', $result); $this->assertRegExp('/Content-Type: text\/plain; charset=UTF-8\n/', $result); $this->assertRegExp('/Content-Transfer-Encoding: 8bitMessage:\n/', $result); $this->assertRegExp('/This is the body of the message/', $result); } /** * test send with delivery = debug and not using sessions. * * @return void */ public function testSendDebugWithNoSessions() { $session = $this->Controller->Session; unset($this->Controller->Session); $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $this->Controller->EmailTest->send('This is the body of the message'); $result = DebugCompTransport::$lastEmail; $this->assertRegExp('/To: postmaster@example.com\n/', $result); $this->assertRegExp('/Subject: Cake Debug Test\n/', $result); $this->assertRegExp('/Reply-To: noreply@example.com\n/', $result); $this->assertRegExp('/From: noreply@example.com\n/', $result); $this->assertRegExp('/Date: ' . preg_quote(static::$sentDate) . '\n/', $result); $this->assertRegExp('/X-Mailer: CakePHP Email Component\n/', $result); $this->assertRegExp('/Content-Type: text\/plain; charset=UTF-8\n/', $result); $this->assertRegExp('/Content-Transfer-Encoding: 8bitMessage:\n/', $result); $this->assertRegExp('/This is the body of the message/', $result); $this->Controller->Session = $session; } /** * testMessageRetrievalWithoutTemplate method * * @return void */ public function testMessageRetrievalWithoutTemplate() { App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->layout = 'default'; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $text = $html = "This is the body of the message\n"; $this->Controller->EmailTest->sendAs = 'both'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $this->assertTextEquals($this->Controller->EmailTest->textMessage, $text); $this->assertTextEquals($this->Controller->EmailTest->htmlMessage, $html); $this->Controller->EmailTest->sendAs = 'text'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $this->assertTextEquals($this->Controller->EmailTest->textMessage, $text); $this->assertNull($this->Controller->EmailTest->htmlMessage); $this->Controller->EmailTest->sendAs = 'html'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $this->assertNull($this->Controller->EmailTest->textMessage); $this->assertTextEquals($this->Controller->EmailTest->htmlMessage, $html); } /** * testMessageRetrievalWithTemplate method * * @return void */ public function testMessageRetrievalWithTemplate() { App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); $this->Controller->set('value', 22091985); $this->Controller->set('title_for_layout', 'EmailTest'); $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->layout = 'default'; $this->Controller->EmailTest->template = 'custom'; $this->Controller->EmailTest->delivery = 'DebugComp'; $text = << EmailTest

Here is your value: 22091985

This email was sent using the CakePHP Framework

HTMLBLOC; $this->Controller->EmailTest->sendAs = 'both'; $this->assertTrue($this->Controller->EmailTest->send()); $this->assertTextEquals($this->Controller->EmailTest->textMessage, $text); $this->assertTextEquals($this->Controller->EmailTest->htmlMessage, $html); $this->Controller->EmailTest->sendAs = 'text'; $this->assertTrue($this->Controller->EmailTest->send()); $this->assertTextEquals($this->Controller->EmailTest->textMessage, $text); $this->assertNull($this->Controller->EmailTest->htmlMessage); $this->Controller->EmailTest->sendAs = 'html'; $this->assertTrue($this->Controller->EmailTest->send()); $this->assertNull($this->Controller->EmailTest->textMessage); $this->assertTextEquals($this->Controller->EmailTest->htmlMessage, $html); } /** * testMessageRetrievalWithHelper method * * @return void */ public function testMessageRetrievalWithHelper() { App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); $timestamp = time(); $this->Controller->set('time', $timestamp); $this->Controller->set('title_for_layout', 'EmailTest'); $this->Controller->helpers = array('Time'); $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->layout = 'default'; $this->Controller->EmailTest->template = 'custom_helper'; $this->Controller->EmailTest->sendAs = 'text'; $this->Controller->EmailTest->delivery = 'DebugComp'; $this->assertTrue($this->Controller->EmailTest->send()); $this->assertTrue((bool)strpos($this->Controller->EmailTest->textMessage, 'Right now: ' . date('Y-m-d\TH:i:s\Z', $timestamp))); } /** * testContentArray method * * @return void */ public function testSendContentArray() { $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $content = array('First line', 'Second line', 'Third line'); $this->assertTrue($this->Controller->EmailTest->send($content)); $result = DebugCompTransport::$lastEmail; $this->assertRegExp('/To: postmaster@example.com\n/', $result); $this->assertRegExp('/Subject: Cake Debug Test\n/', $result); $this->assertRegExp('/Reply-To: noreply@example.com\n/', $result); $this->assertRegExp('/From: noreply@example.com\n/', $result); $this->assertRegExp('/X-Mailer: CakePHP Email Component\n/', $result); $this->assertRegExp('/Content-Type: text\/plain; charset=UTF-8\n/', $result); $this->assertRegExp('/Content-Transfer-Encoding: 8bitMessage:\n/', $result); $this->assertRegExp('/First line\n/', $result); $this->assertRegExp('/Second line\n/', $result); $this->assertRegExp('/Third line\n/', $result); } /** * test setting a custom date. * * @return void */ public function testDateProperty() { $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->date = static::$sentDate = 'Today!'; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $this->assertTrue($this->Controller->EmailTest->send('test message')); $result = DebugCompTransport::$lastEmail; $this->assertRegExp('/Date: Today!\n/', $result); } /** * testContentStripping method * * @return void */ public function testContentStripping() { $content = "Previous content\n--alt-\nContent-TypeContent-Type:: text/html; charsetcharset==utf-8\nContent-Transfer-Encoding: 8bit"; $content .= "\n\n

My own html content

"; $result = $this->Controller->EmailTest->strip($content, true); $expected = "Previous content\n--alt-\n text/html; utf-8\n 8bit\n\n

My own html content

"; $this->assertEquals($expected, $result); $content = '

Some HTML content with an email link'; $result = $this->Controller->EmailTest->strip($content, true); $expected = $content; $this->assertEquals($expected, $result); $content = '

Some HTML content with an '; $content .= 'email link'; $result = $this->Controller->EmailTest->strip($content, true); $expected = $content; $this->assertEquals($expected, $result); } /** * test that the _encode() will set mb_internal_encoding. * * @return void */ public function testEncodeSettingInternalCharset() { $this->skipIf(!function_exists('mb_internal_encoding'), 'Missing mb_* functions, cannot run test.'); $restore = mb_internal_encoding(); mb_internal_encoding('ISO-8859-1'); $this->Controller->charset = 'UTF-8'; $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'ู‡ุฐู‡ ุฑุณุงู„ุฉ ุจุนู†ูˆุงู† ุทูˆูŠู„ ู…ุฑุณู„ ู„ู„ู…ุณุชู„ู…'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $this->Controller->EmailTest->sendAs = 'text'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $subject = '=?UTF-8?B?2YfYsNmHINix2LPYp9mE2Kkg2KjYudmG2YjYp9mGINi32YjZitmEINmF2LE=?=' . "\r\n" . ' =?UTF-8?B?2LPZhCDZhNmE2YXYs9iq2YTZhQ==?='; preg_match('/Subject: (.*)Header:/s', DebugCompTransport::$lastEmail, $matches); $this->assertEquals(trim($matches[1]), $subject); $result = mb_internal_encoding(); $this->assertEquals('ISO-8859-1', $result); mb_internal_encoding($restore); } /** * testMultibyte method * * @return void */ public function testMultibyte() { $this->Controller->charset = 'UTF-8'; $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'ู‡ุฐู‡ ุฑุณุงู„ุฉ ุจุนู†ูˆุงู† ุทูˆูŠู„ ู…ุฑุณู„ ู„ู„ู…ุณุชู„ู…'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $subject = '=?UTF-8?B?2YfYsNmHINix2LPYp9mE2Kkg2KjYudmG2YjYp9mGINi32YjZitmEINmF2LE=?=' . "\r\n" . ' =?UTF-8?B?2LPZhCDZhNmE2YXYs9iq2YTZhQ==?='; $this->Controller->EmailTest->sendAs = 'text'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); preg_match('/Subject: (.*)Header:/s', DebugCompTransport::$lastEmail, $matches); $this->assertEquals(trim($matches[1]), $subject); $this->Controller->EmailTest->sendAs = 'html'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); preg_match('/Subject: (.*)Header:/s', DebugCompTransport::$lastEmail, $matches); $this->assertEquals(trim($matches[1]), $subject); $this->Controller->EmailTest->sendAs = 'both'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); preg_match('/Subject: (.*)Header:/s', DebugCompTransport::$lastEmail, $matches); $this->assertEquals(trim($matches[1]), $subject); } /** * undocumented function * * @return void */ public function testSendWithAttachments() { $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Attachment Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $this->Controller->EmailTest->attachments = array( __FILE__, 'some-name.php' => __FILE__ ); $body = '

This is the body of the message

'; $this->Controller->EmailTest->sendAs = 'text'; $this->assertTrue($this->Controller->EmailTest->send($body)); $msg = DebugCompTransport::$lastEmail; $this->assertRegExp('/' . preg_quote('Content-Disposition: attachment; filename="EmailComponentTest.php"') . '/', $msg); $this->assertRegExp('/' . preg_quote('Content-Disposition: attachment; filename="some-name.php"') . '/', $msg); } /** * testSendAsIsNotIgnoredIfAttachmentsPresent method * * @return void */ public function testSendAsIsNotIgnoredIfAttachmentsPresent() { $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Attachment Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $this->Controller->EmailTest->attachments = array(__FILE__); $body = '

This is the body of the message

'; $this->Controller->EmailTest->sendAs = 'html'; $this->assertTrue($this->Controller->EmailTest->send($body)); $msg = DebugCompTransport::$lastEmail; $this->assertNotRegExp('/text\/plain/', $msg); $this->assertRegExp('/text\/html/', $msg); $this->Controller->EmailTest->sendAs = 'text'; $this->assertTrue($this->Controller->EmailTest->send($body)); $msg = DebugCompTransport::$lastEmail; $this->assertRegExp('/text\/plain/', $msg); $this->assertNotRegExp('/text\/html/', $msg); $this->Controller->EmailTest->sendAs = 'both'; $this->assertTrue($this->Controller->EmailTest->send($body)); $msg = DebugCompTransport::$lastEmail; $this->assertRegExp('/text\/plain/', $msg); $this->assertRegExp('/text\/html/', $msg); $this->assertRegExp('/multipart\/alternative/', $msg); } /** * testNoDoubleNewlinesInHeaders function * * @return void */ public function testNoDoubleNewlinesInHeaders() { $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Attachment Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $body = '

This is the body of the message

'; $this->Controller->EmailTest->sendAs = 'both'; $this->assertTrue($this->Controller->EmailTest->send($body)); $msg = DebugCompTransport::$lastEmail; $this->assertNotRegExp('/\n\nContent-Transfer-Encoding/', $msg); $this->assertRegExp('/\nContent-Transfer-Encoding/', $msg); } /** * testReset method * * @return void */ public function testReset() { $this->Controller->EmailTest->template = 'default'; $this->Controller->EmailTest->to = 'test.recipient@example.com'; $this->Controller->EmailTest->from = 'test.sender@example.com'; $this->Controller->EmailTest->replyTo = 'test.replyto@example.com'; $this->Controller->EmailTest->return = 'test.return@example.com'; $this->Controller->EmailTest->cc = array('cc1@example.com', 'cc2@example.com'); $this->Controller->EmailTest->bcc = array('bcc1@example.com', 'bcc2@example.com'); $this->Controller->EmailTest->date = 'Today!'; $this->Controller->EmailTest->subject = 'Test subject'; $this->Controller->EmailTest->additionalParams = 'X-additional-header'; $this->Controller->EmailTest->delivery = 'smtp'; $this->Controller->EmailTest->smtpOptions['host'] = 'blah'; $this->Controller->EmailTest->smtpOptions['timeout'] = 0.2; $this->Controller->EmailTest->attachments = array('attachment1', 'attachment2'); $this->Controller->EmailTest->textMessage = 'This is the body of the message'; $this->Controller->EmailTest->htmlMessage = 'This is the body of the message'; $this->Controller->EmailTest->messageId = false; try { $this->Controller->EmailTest->send('Should not work'); $this->fail('No exception'); } catch (SocketException $e) { $this->assertTrue(true, 'SocketException raised'); } $this->Controller->EmailTest->reset(); $this->assertNull($this->Controller->EmailTest->template); $this->assertSame($this->Controller->EmailTest->to, array()); $this->assertNull($this->Controller->EmailTest->from); $this->assertNull($this->Controller->EmailTest->replyTo); $this->assertNull($this->Controller->EmailTest->return); $this->assertSame($this->Controller->EmailTest->cc, array()); $this->assertSame($this->Controller->EmailTest->bcc, array()); $this->assertNull($this->Controller->EmailTest->date); $this->assertNull($this->Controller->EmailTest->subject); $this->assertNull($this->Controller->EmailTest->additionalParams); $this->assertNull($this->Controller->EmailTest->smtpError); $this->assertSame($this->Controller->EmailTest->attachments, array()); $this->assertNull($this->Controller->EmailTest->textMessage); $this->assertTrue($this->Controller->EmailTest->messageId); $this->assertEquals('mail', $this->Controller->EmailTest->delivery); } public function testPluginCustomViewClass() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); $this->Controller->view = 'TestPlugin.Email'; $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'CustomViewClass test'; $this->Controller->EmailTest->delivery = 'DebugComp'; $body = 'Body of message'; $this->assertTrue($this->Controller->EmailTest->send($body)); $result = DebugCompTransport::$lastEmail; $this->assertRegExp('/Body of message/', $result); } /** * testStartup method * * @return void */ public function testStartup() { $this->assertNull($this->Controller->EmailTest->startup($this->Controller)); } /** * testMessageId method * * @return void */ public function testMessageId() { $this->Controller->EmailTest->to = 'postmaster@example.com'; $this->Controller->EmailTest->from = 'noreply@example.com'; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $result = DebugCompTransport::$lastEmail; $host = env('HTTP_HOST') ? env('HTTP_HOST') : php_uname('n'); $this->assertRegExp('/Message-ID: \<[a-f0-9]{8}[a-f0-9]{4}[a-f0-9]{4}[a-f0-9]{4}[a-f0-9]{12}@' . $host . '\>\n/', $result); $this->Controller->EmailTest->messageId = '<22091985.998877@example.com>'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $result = DebugCompTransport::$lastEmail; $this->assertRegExp('/Message-ID: <22091985.998877@example.com>\n/', $result); $this->Controller->EmailTest->messageId = false; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $result = DebugCompTransport::$lastEmail; $this->assertNotRegExp('/Message-ID:/', $result); } /** * Make sure from/to are not double encoded when UTF-8 is present * * @return void */ public function testEncodingFrom() { $this->Controller->EmailTest->to = 'TeรŸt '; $this->Controller->EmailTest->from = 'TeรŸt '; $this->Controller->EmailTest->subject = 'Cake Debug Test'; $this->Controller->EmailTest->replyTo = 'noreply@example.com'; $this->Controller->EmailTest->template = null; $this->Controller->EmailTest->delivery = 'DebugComp'; $this->assertTrue($this->Controller->EmailTest->send('This is the body of the message')); $result = DebugCompTransport::$lastEmail; $this->assertContains('From: =?UTF-8?B?VGXDn3Qg?= ', $result); $this->assertContains('To: =?UTF-8?B?VGXDn3Qg?= ', $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/FlashComponentTest.php000066400000000000000000000113761265552240500267330ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Controller.Component * @since CakePHP(tm) v 2.7.0-dev * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('FlashComponent', 'Controller/Component'); App::uses('ComponentCollection', 'Controller'); /** * FlashComponentTest class * * @package Cake.Test.Case.Controller.Component */ class FlashComponentTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->Components = new ComponentCollection(); $this->Flash = new FlashComponent($this->Components); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); CakeSession::destroy(); } /** * testSet method * * @return void */ public function testSet() { $this->assertNull(CakeSession::read('Message.flash')); $this->Flash->set('This is a test message'); $expected = array( 'message' => 'This is a test message', 'key' => 'flash', 'element' => 'Flash/default', 'params' => array() ); $result = CakeSession::read('Message.flash'); $this->assertEquals($expected, $result); $this->Flash->set('This is a test message', array( 'element' => 'test', 'params' => array('foo' => 'bar') )); $expected = array( 'message' => 'This is a test message', 'key' => 'flash', 'element' => 'Flash/test', 'params' => array('foo' => 'bar') ); $result = CakeSession::read('Message.flash'); $this->assertEquals($expected, $result); $this->Flash->set('This is a test message', array('element' => 'MyPlugin.alert')); $expected = array( 'message' => 'This is a test message', 'key' => 'flash', 'element' => 'MyPlugin.Flash/alert', 'params' => array() ); $result = CakeSession::read('Message.flash'); $this->assertEquals($expected, $result); $this->Flash->set('This is a test message', array('key' => 'foobar')); $expected = array( 'message' => 'This is a test message', 'key' => 'foobar', 'element' => 'Flash/default', 'params' => array() ); $result = CakeSession::read('Message.foobar'); $this->assertEquals($expected, $result); } /** * testSetWithException method * * @return void */ public function testSetWithException() { $this->assertNull(CakeSession::read('Message.flash')); $this->Flash->set(new Exception('This is a test message', 404)); $expected = array( 'message' => 'This is a test message', 'key' => 'flash', 'element' => 'Flash/default', 'params' => array('code' => 404) ); $result = CakeSession::read('Message.flash'); $this->assertEquals($expected, $result); } /** * testSetWithComponentConfiguration method * * @return void */ public function testSetWithComponentConfiguration() { $this->assertNull(CakeSession::read('Message.flash')); $FlashWithSettings = $this->Components->load('Flash', array('element' => 'test')); $FlashWithSettings->set('This is a test message'); $expected = array( 'message' => 'This is a test message', 'key' => 'flash', 'element' => 'Flash/test', 'params' => array() ); $result = CakeSession::read('Message.flash'); $this->assertEquals($expected, $result); } /** * Test magic call method. * * @return void */ public function testCall() { $this->assertNull(CakeSession::read('Message.flash')); $this->Flash->success('It worked'); $expected = array( 'message' => 'It worked', 'key' => 'flash', 'element' => 'Flash/success', 'params' => array() ); $result = CakeSession::read('Message.flash'); $this->assertEquals($expected, $result); $this->Flash->alert('It worked', array('plugin' => 'MyPlugin')); $expected = array( 'message' => 'It worked', 'key' => 'flash', 'element' => 'MyPlugin.Flash/alert', 'params' => array() ); $result = CakeSession::read('Message.flash'); $this->assertEquals($expected, $result); $this->Flash->error('It did not work', array('element' => 'error_thing')); $expected = array( 'message' => 'It did not work', 'key' => 'flash', 'element' => 'Flash/error', 'params' => array() ); $result = CakeSession::read('Message.flash'); $this->assertEquals($expected, $result, 'Element is ignored in magic call.'); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/PaginatorComponentTest.php000066400000000000000000001311041265552240500276120ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Controller.Component * @since CakePHP(tm) v 2.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Controller', 'Controller'); App::uses('PaginatorComponent', 'Controller/Component'); App::uses('CakeRequest', 'Network'); App::uses('CakeResponse', 'Network'); /** * PaginatorTestController class * * @package Cake.Test.Case.Controller.Component */ class PaginatorTestController extends Controller { /** * components property * * @var array */ public $components = array('Paginator'); } /** * PaginatorControllerPost class * * @package Cake.Test.Case.Controller.Component */ class PaginatorControllerPost extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'posts'; /** * invalidFields property * * @var array */ public $invalidFields = array('name' => 'error_msg'); /** * lastQueries property * * @var array */ public $lastQueries = array(); /** * belongsTo property * * @var array */ public $belongsTo = array('PaginatorAuthor' => array('foreignKey' => 'author_id')); /** * beforeFind method * * @param mixed $query * @return void */ public function beforeFind($query) { array_unshift($this->lastQueries, $query); } /** * find method * * @param mixed $type * @param array $options * @return void */ public function find($conditions = null, $fields = array(), $order = null, $recursive = null) { if ($conditions === 'popular') { $conditions = array($this->name . '.' . $this->primaryKey . ' > ' => '1'); $options = Hash::merge($fields, compact('conditions')); return parent::find('all', $options); } return parent::find($conditions, $fields); } } /** * ControllerPaginateModel class * * @package Cake.Test.Case.Controller.Component */ class ControllerPaginateModel extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'comments'; /** * paginate method * * @return bool */ public function paginate($conditions, $fields, $order, $limit, $page, $recursive, $extra) { $this->extra = $extra; return true; } /** * paginateCount * * @return void */ public function paginateCount($conditions, $recursive, $extra) { $this->extraCount = $extra; } } /** * PaginatorControllerComment class * * @package Cake.Test.Case.Controller.Component */ class PaginatorControllerComment extends CakeTestModel { /** * name property * * @var string */ public $name = 'Comment'; /** * useTable property * * @var string */ public $useTable = 'comments'; /** * alias property * * @var string */ public $alias = 'PaginatorControllerComment'; } /** * PaginatorAuthor class * * @package Cake.Test.Case.Controller.Component */ class PaginatorAuthor extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'authors'; /** * alias property * * @var string */ public $virtualFields = array( 'joined_offset' => 'PaginatorAuthor.id + 1' ); } /** * PaginatorCustomPost class * * @package Cake.Test.Case.Controller.Component */ class PaginatorCustomPost extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'posts'; /** * belongsTo property * * @var string */ public $belongsTo = array('Author'); /** * findMethods property * * @var array */ public $findMethods = array( 'published' => true, 'totals' => true, 'totalsOperation' => true ); /** * _findPublished custom find * * @return array */ protected function _findPublished($state, $query, $results = array()) { if ($state === 'before') { $query['conditions']['published'] = 'Y'; return $query; } return $results; } /** * _findTotals custom find * * @return array */ protected function _findTotals($state, $query, $results = array()) { if ($state === 'before') { $query['fields'] = array('author_id'); $this->virtualFields['total_posts'] = "COUNT({$this->alias}.id)"; $query['fields'][] = 'total_posts'; $query['group'] = array('author_id'); $query['order'] = array('author_id' => 'ASC'); return $query; } $this->virtualFields = array(); return $results; } /** * _findTotalsOperation custom find * * @return array */ protected function _findTotalsOperation($state, $query, $results = array()) { if ($state === 'before') { if (!empty($query['operation']) && $query['operation'] === 'count') { unset($query['limit']); $query['recursive'] = -1; $query['fields'] = array('COUNT(DISTINCT author_id) AS count'); return $query; } $query['recursive'] = 0; $query['callbacks'] = 'before'; $query['fields'] = array('author_id', 'Author.user'); $this->virtualFields['total_posts'] = "COUNT({$this->alias}.id)"; $query['fields'][] = 'total_posts'; $query['group'] = array('author_id', 'Author.user'); $query['order'] = array('author_id' => 'ASC'); return $query; } $this->virtualFields = array(); return $results; } } class PaginatorComponentTest extends CakeTestCase { /** * fixtures property * * @var array */ public $fixtures = array('core.post', 'core.comment', 'core.author'); /** * setup * * @return void */ public function setUp() { parent::setUp(); $this->request = new CakeRequest('controller_posts/index'); $this->request->params['pass'] = $this->request->params['named'] = array(); $this->Controller = new Controller($this->request); $this->Paginator = new PaginatorComponent($this->getMock('ComponentCollection'), array()); $this->Paginator->Controller = $this->Controller; $this->Controller->Post = $this->getMock('Model'); $this->Controller->Post->alias = 'Post'; } /** * testPaginate method * * @return void */ public function testPaginate() { $Controller = new PaginatorTestController($this->request); $Controller->uses = array('PaginatorControllerPost', 'PaginatorControllerComment'); $Controller->request->params['pass'] = array('1'); $Controller->request->query = array(); $Controller->constructClasses(); $Controller->PaginatorControllerPost->order = null; $Controller->Paginator->settings = array( 'order' => array('PaginatorControllerComment.id' => 'ASC') ); $results = Hash::extract($Controller->Paginator->paginate('PaginatorControllerComment'), '{n}.PaginatorControllerComment.id'); $this->assertEquals(array(1, 2, 3, 4, 5, 6), $results); $Controller->Paginator->settings = array( 'order' => array('PaginatorControllerPost.id' => 'ASC') ); $results = Hash::extract($Controller->Paginator->paginate('PaginatorControllerPost'), '{n}.PaginatorControllerPost.id'); $this->assertEquals(array(1, 2, 3), $results); $Controller->modelClass = null; $Controller->uses[0] = 'Plugin.PaginatorControllerPost'; $results = Hash::extract($Controller->Paginator->paginate(), '{n}.PaginatorControllerPost.id'); $this->assertEquals(array(1, 2, 3), $results); $Controller->request->params['named'] = array('page' => '-1'); $results = Hash::extract($Controller->Paginator->paginate('PaginatorControllerPost'), '{n}.PaginatorControllerPost.id'); $this->assertEquals(1, $Controller->params['paging']['PaginatorControllerPost']['page']); $this->assertEquals(array(1, 2, 3), $results); $Controller->request->params['named'] = array('sort' => 'PaginatorControllerPost.id', 'direction' => 'asc'); $results = Hash::extract($Controller->Paginator->paginate('PaginatorControllerPost'), '{n}.PaginatorControllerPost.id'); $this->assertEquals(1, $Controller->params['paging']['PaginatorControllerPost']['page']); $this->assertEquals(array(1, 2, 3), $results); $Controller->request->params['named'] = array('sort' => 'PaginatorControllerPost.id', 'direction' => 'desc'); $results = Hash::extract($Controller->Paginator->paginate('PaginatorControllerPost'), '{n}.PaginatorControllerPost.id'); $this->assertEquals(1, $Controller->params['paging']['PaginatorControllerPost']['page']); $this->assertEquals(array(3, 2, 1), $results); $Controller->request->params['named'] = array('sort' => 'id', 'direction' => 'desc'); $results = Hash::extract($Controller->Paginator->paginate('PaginatorControllerPost'), '{n}.PaginatorControllerPost.id'); $this->assertEquals(1, $Controller->params['paging']['PaginatorControllerPost']['page']); $this->assertEquals(array(3, 2, 1), $results); $Controller->request->params['named'] = array('sort' => 'NotExisting.field', 'direction' => 'desc', 'limit' => 2); $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertEquals(1, $Controller->params['paging']['PaginatorControllerPost']['page']); $this->assertEquals(array(), $Controller->PaginatorControllerPost->lastQueries[1]['order'], 'no order should be set.'); $Controller->request->params['named'] = array( 'sort' => 'PaginatorControllerPost.author_id', 'direction' => 'allYourBase' ); $results = Hash::extract($Controller->Paginator->paginate('PaginatorControllerPost'), '{n}.PaginatorControllerPost.id'); $this->assertEquals(array('PaginatorControllerPost.author_id' => 'asc'), $Controller->PaginatorControllerPost->lastQueries[0]['order']); $this->assertEquals(array(1, 3, 2), $results); $Controller->request->params['named'] = array(); $Controller->Paginator->settings = array('limit' => 0, 'maxLimit' => 10, 'paramType' => 'named'); $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertSame(1, $Controller->params['paging']['PaginatorControllerPost']['page']); $this->assertSame($Controller->params['paging']['PaginatorControllerPost']['pageCount'], 3); $this->assertFalse($Controller->params['paging']['PaginatorControllerPost']['prevPage']); $this->assertTrue($Controller->params['paging']['PaginatorControllerPost']['nextPage']); $Controller->request->params['named'] = array(); $Controller->Paginator->settings = array('limit' => 'garbage!', 'maxLimit' => 10, 'paramType' => 'named'); $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertSame(1, $Controller->params['paging']['PaginatorControllerPost']['page']); $this->assertSame($Controller->params['paging']['PaginatorControllerPost']['pageCount'], 3); $this->assertFalse($Controller->params['paging']['PaginatorControllerPost']['prevPage']); $this->assertTrue($Controller->params['paging']['PaginatorControllerPost']['nextPage']); $Controller->request->params['named'] = array(); $Controller->Paginator->settings = array('limit' => '-1', 'maxLimit' => 10, 'paramType' => 'named'); $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertSame($Controller->params['paging']['PaginatorControllerPost']['limit'], 1); $this->assertSame(1, $Controller->params['paging']['PaginatorControllerPost']['page']); $this->assertSame($Controller->params['paging']['PaginatorControllerPost']['pageCount'], 3); $this->assertFalse($Controller->params['paging']['PaginatorControllerPost']['prevPage']); $this->assertTrue($Controller->params['paging']['PaginatorControllerPost']['nextPage']); $Controller->Paginator->settings = array('conditions' => array('PaginatorAuthor.user' => 'mariano')); $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertSame(2, $Controller->params['paging']['PaginatorControllerPost']['count']); } /** * Test that non-numeric values are rejected for page, and limit * * @return void */ public function testPageParamCasting() { $this->Controller->Post->expects($this->at(0)) ->method('hasMethod') ->with('paginate') ->will($this->returnValue(false)); $this->Controller->Post->expects($this->at(1)) ->method('find') ->will($this->returnValue(array('stuff'))); $this->Controller->Post->expects($this->at(2)) ->method('hasMethod') ->with('paginateCount') ->will($this->returnValue(false)); $this->Controller->Post->expects($this->at(3)) ->method('find') ->will($this->returnValue(2)); $this->request->params['named'] = array('page' => '1 " onclick="alert(\'xss\');">'); $this->Paginator->settings = array('limit' => 1, 'maxLimit' => 10, 'paramType' => 'named'); $this->Paginator->paginate('Post'); $this->assertSame(1, $this->request->params['paging']['Post']['page'], 'XSS exploit opened'); } /** * testPaginateExtraParams method * * @return void */ public function testPaginateExtraParams() { $Controller = new PaginatorTestController($this->request); $Controller->uses = array('PaginatorControllerPost', 'PaginatorControllerComment'); $Controller->request->params['pass'] = array('1'); $Controller->params['url'] = array(); $Controller->constructClasses(); $Controller->request->params['named'] = array('page' => '-1', 'contain' => array('PaginatorControllerComment')); $Controller->Paginator->settings = array( 'order' => array('PaginatorControllerPost.id' => 'ASC') ); $result = $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertEquals(1, $Controller->params['paging']['PaginatorControllerPost']['page']); $this->assertEquals(array(1, 2, 3), Hash::extract($result, '{n}.PaginatorControllerPost.id')); $this->assertTrue(!isset($Controller->PaginatorControllerPost->lastQueries[1]['contain'])); $Controller->Paginator->settings = array( 'order' => array('PaginatorControllerPost.author_id') ); $result = $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertEquals(1, $Controller->params['paging']['PaginatorControllerPost']['page']); $this->assertEquals(array(1, 3, 2), Hash::extract($result, '{n}.PaginatorControllerPost.id')); $Controller->request->params['named'] = array('page' => '-1'); $Controller->Paginator->settings = array( 'PaginatorControllerPost' => array( 'contain' => array('PaginatorControllerComment'), 'maxLimit' => 10, 'paramType' => 'named', 'order' => array('PaginatorControllerPost.id' => 'ASC') ), ); $result = $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertEquals(1, $Controller->params['paging']['PaginatorControllerPost']['page']); $this->assertEquals(array(1, 2, 3), Hash::extract($result, '{n}.PaginatorControllerPost.id')); $this->assertTrue(isset($Controller->PaginatorControllerPost->lastQueries[0]['contain'])); $Controller->Paginator->settings = array( 'PaginatorControllerPost' => array( 'popular', 'fields' => array('id', 'title'), 'maxLimit' => 10, 'paramType' => 'named' ), ); $result = $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertEquals(array(2, 3), Hash::extract($result, '{n}.PaginatorControllerPost.id')); $this->assertEquals(array('PaginatorControllerPost.id > ' => '1'), $Controller->PaginatorControllerPost->lastQueries[0]['conditions']); $Controller->request->params['named'] = array('limit' => 12); $Controller->Paginator->settings = array('limit' => 30, 'maxLimit' => 100, 'paramType' => 'named'); $Controller->Paginator->paginate('PaginatorControllerPost'); $paging = $Controller->params['paging']['PaginatorControllerPost']; $this->assertEquals(12, $Controller->PaginatorControllerPost->lastQueries[0]['limit']); $this->assertEquals(12, $paging['options']['limit']); $Controller = new PaginatorTestController($this->request); $Controller->uses = array('ControllerPaginateModel'); $Controller->request->query = array(); $Controller->constructClasses(); $Controller->Paginator->settings = array( 'ControllerPaginateModel' => array( 'contain' => array('ControllerPaginateModel'), 'group' => 'Comment.author_id', 'maxLimit' => 10, 'paramType' => 'named' ) ); $Controller->Paginator->paginate('ControllerPaginateModel'); $expected = array( 'contain' => array('ControllerPaginateModel'), 'group' => 'Comment.author_id', 'maxLimit' => 10, 'paramType' => 'named' ); $this->assertEquals($expected, $Controller->ControllerPaginateModel->extra); $this->assertEquals($expected, $Controller->ControllerPaginateModel->extraCount); $Controller->Paginator->settings = array( 'ControllerPaginateModel' => array( 'foo', 'contain' => array('ControllerPaginateModel'), 'group' => 'Comment.author_id', 'maxLimit' => 10, 'paramType' => 'named' ) ); $Controller->Paginator->paginate('ControllerPaginateModel'); $expected = array( 'contain' => array('ControllerPaginateModel'), 'group' => 'Comment.author_id', 'type' => 'foo', 'maxLimit' => 10, 'paramType' => 'named' ); $this->assertEquals($expected, $Controller->ControllerPaginateModel->extra); $this->assertEquals($expected, $Controller->ControllerPaginateModel->extraCount); } /** * Test that special paginate types are called and that the type param doesn't leak out into defaults or options. * * @return void */ public function testPaginateSpecialType() { $Controller = new PaginatorTestController($this->request); $Controller->uses = array('PaginatorControllerPost', 'PaginatorControllerComment'); $Controller->request->params['pass'][] = '1'; $Controller->params['url'] = array(); $Controller->constructClasses(); $Controller->Paginator->settings = array( 'PaginatorControllerPost' => array( 'popular', 'fields' => array('id', 'title'), 'maxLimit' => 10, 'paramType' => 'named' ) ); $result = $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertEquals(array(2, 3), Hash::extract($result, '{n}.PaginatorControllerPost.id')); $this->assertEquals( $Controller->PaginatorControllerPost->lastQueries[0]['conditions'], array('PaginatorControllerPost.id > ' => '1') ); $this->assertFalse(isset($Controller->params['paging']['PaginatorControllerPost']['options'][0])); } /** * testDefaultPaginateParams method * * @return void */ public function testDefaultPaginateParams() { $Controller = new PaginatorTestController($this->request); $Controller->modelClass = 'PaginatorControllerPost'; $Controller->params['url'] = array(); $Controller->constructClasses(); $Controller->Paginator->settings = array( 'order' => 'PaginatorControllerPost.id DESC', 'maxLimit' => 10, 'paramType' => 'named' ); $results = Hash::extract($Controller->Paginator->paginate('PaginatorControllerPost'), '{n}.PaginatorControllerPost.id'); $this->assertEquals('PaginatorControllerPost.id DESC', $Controller->params['paging']['PaginatorControllerPost']['order']); $this->assertEquals(array(3, 2, 1), $results); } /** * test paginate() and model default order * * @return void */ public function testPaginateOrderModelDefault() { $Controller = new PaginatorTestController($this->request); $Controller->uses = array('PaginatorControllerPost'); $Controller->params['url'] = array(); $Controller->constructClasses(); $Controller->PaginatorControllerPost->order = array( $Controller->PaginatorControllerPost->alias . '.created' => 'desc' ); $Controller->Paginator->settings = array( 'fields' => array('id', 'title', 'created'), 'maxLimit' => 10, 'paramType' => 'named' ); $result = $Controller->Paginator->paginate('PaginatorControllerPost'); $expected = array('2007-03-18 10:43:23', '2007-03-18 10:41:23', '2007-03-18 10:39:23'); $this->assertEquals($expected, Hash::extract($result, '{n}.PaginatorControllerPost.created')); $this->assertEquals( $Controller->PaginatorControllerPost->order, $Controller->request->paging['PaginatorControllerPost']['options']['order'] ); $Controller->PaginatorControllerPost->order = array('PaginatorControllerPost.id'); $result = $Controller->Paginator->validateSort($Controller->PaginatorControllerPost, array()); $this->assertEquals(array('PaginatorControllerPost.id' => 'asc'), $result['order']); $Controller->PaginatorControllerPost->order = 'PaginatorControllerPost.id'; $result = $Controller->Paginator->validateSort($Controller->PaginatorControllerPost, array()); $this->assertArrayNotHasKey('order', $result); $Controller->PaginatorControllerPost->order = array( 'PaginatorControllerPost.id', 'PaginatorControllerPost.created' => 'asc' ); $result = $Controller->Paginator->validateSort($Controller->PaginatorControllerPost, array()); $expected = array( 'PaginatorControllerPost.id' => 'asc', 'PaginatorControllerPost.created' => 'asc' ); $this->assertEquals($expected, $result['order']); } /** * test paginate() and virtualField interactions * * @return void */ public function testPaginateOrderVirtualField() { $Controller = new PaginatorTestController($this->request); $Controller->uses = array('PaginatorControllerPost', 'PaginatorControllerComment'); $Controller->params['url'] = array(); $Controller->constructClasses(); $Controller->PaginatorControllerPost->virtualFields = array( 'offset_test' => 'PaginatorControllerPost.id + 1' ); $Controller->Paginator->settings = array( 'fields' => array('id', 'title', 'offset_test'), 'order' => array('offset_test' => 'DESC'), 'maxLimit' => 10, 'paramType' => 'named' ); $result = $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertEquals(array(4, 3, 2), Hash::extract($result, '{n}.PaginatorControllerPost.offset_test')); $Controller->request->params['named'] = array('sort' => 'offset_test', 'direction' => 'asc'); $result = $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertEquals(array(2, 3, 4), Hash::extract($result, '{n}.PaginatorControllerPost.offset_test')); } /** * test paginate() and virtualField on joined model * * @return void */ public function testPaginateOrderVirtualFieldJoinedModel() { $Controller = new PaginatorTestController($this->request); $Controller->uses = array('PaginatorControllerPost'); $Controller->params['url'] = array(); $Controller->constructClasses(); $Controller->PaginatorControllerPost->recursive = 0; $Controller->Paginator->settings = array( 'order' => array('PaginatorAuthor.joined_offset' => 'DESC'), 'maxLimit' => 10, 'paramType' => 'named' ); $result = $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertEquals(array(4, 2, 2), Hash::extract($result, '{n}.PaginatorAuthor.joined_offset')); $Controller->request->params['named'] = array('sort' => 'PaginatorAuthor.joined_offset', 'direction' => 'asc'); $result = $Controller->Paginator->paginate('PaginatorControllerPost'); $this->assertEquals(array(2, 2, 4), Hash::extract($result, '{n}.PaginatorAuthor.joined_offset')); } /** * Tests for missing models * * @expectedException MissingModelException * @return void */ public function testPaginateMissingModel() { $Controller = new PaginatorTestController($this->request); $Controller->constructClasses(); $Controller->Paginator->paginate('MissingModel'); } /** * test that option merging prefers specific models * * @return void */ public function testMergeOptionsModelSpecific() { $this->Paginator->settings = array( 'page' => 1, 'limit' => 20, 'maxLimit' => 100, 'paramType' => 'named', 'Post' => array( 'page' => 1, 'limit' => 10, 'maxLimit' => 50, 'paramType' => 'named', ) ); $result = $this->Paginator->mergeOptions('Silly'); $this->assertEquals($this->Paginator->settings, $result); $result = $this->Paginator->mergeOptions('Post'); $expected = array('page' => 1, 'limit' => 10, 'paramType' => 'named', 'maxLimit' => 50); $this->assertEquals($expected, $result); } /** * test mergeOptions with named params. * * @return void */ public function testMergeOptionsNamedParams() { $this->request->params['named'] = array( 'page' => 10, 'limit' => 10 ); $this->Paginator->settings = array( 'page' => 1, 'limit' => 20, 'maxLimit' => 100, 'paramType' => 'named', ); $result = $this->Paginator->mergeOptions('Post'); $expected = array('page' => 10, 'limit' => 10, 'maxLimit' => 100, 'paramType' => 'named'); $this->assertEquals($expected, $result); } /** * test mergeOptions with customFind key * * @return void */ public function testMergeOptionsCustomFindKey() { $this->request->params['named'] = array( 'page' => 10, 'limit' => 10 ); $this->Paginator->settings = array( 'page' => 1, 'limit' => 20, 'maxLimit' => 100, 'paramType' => 'named', 'findType' => 'myCustomFind' ); $result = $this->Paginator->mergeOptions('Post'); $expected = array('page' => 10, 'limit' => 10, 'maxLimit' => 100, 'paramType' => 'named', 'findType' => 'myCustomFind'); $this->assertEquals($expected, $result); } /** * test merging options from the querystring. * * @return void */ public function testMergeOptionsQueryString() { $this->request->params['named'] = array( 'page' => 10, 'limit' => 10 ); $this->request->query = array( 'page' => 99, 'limit' => 75 ); $this->Paginator->settings = array( 'page' => 1, 'limit' => 20, 'maxLimit' => 100, 'paramType' => 'querystring', ); $result = $this->Paginator->mergeOptions('Post'); $expected = array('page' => 99, 'limit' => 75, 'maxLimit' => 100, 'paramType' => 'querystring'); $this->assertEquals($expected, $result); } /** * test that the default whitelist doesn't let people screw with things they should not be allowed to. * * @return void */ public function testMergeOptionsDefaultWhiteList() { $this->request->params['named'] = array( 'page' => 10, 'limit' => 10, 'fields' => array('bad.stuff'), 'recursive' => 1000, 'conditions' => array('bad.stuff'), 'contain' => array('bad') ); $this->Paginator->settings = array( 'page' => 1, 'limit' => 20, 'maxLimit' => 100, 'paramType' => 'named', ); $result = $this->Paginator->mergeOptions('Post'); $expected = array('page' => 10, 'limit' => 10, 'maxLimit' => 100, 'paramType' => 'named'); $this->assertEquals($expected, $result); } /** * test that modifying the whitelist works. * * @return void */ public function testMergeOptionsExtraWhitelist() { $this->request->params['named'] = array( 'page' => 10, 'limit' => 10, 'fields' => array('bad.stuff'), 'recursive' => 1000, 'conditions' => array('bad.stuff'), 'contain' => array('bad') ); $this->Paginator->settings = array( 'page' => 1, 'limit' => 20, 'maxLimit' => 100, 'paramType' => 'named', ); $this->Paginator->whitelist[] = 'fields'; $result = $this->Paginator->mergeOptions('Post'); $expected = array( 'page' => 10, 'limit' => 10, 'maxLimit' => 100, 'paramType' => 'named', 'fields' => array('bad.stuff') ); $this->assertEquals($expected, $result); } /** * test mergeOptions with limit > maxLimit in code. * * @return void */ public function testMergeOptionsMaxLimit() { $this->Paginator->settings = array( 'limit' => 200, 'paramType' => 'named', ); $result = $this->Paginator->mergeOptions('Post'); $expected = array('page' => 1, 'limit' => 200, 'maxLimit' => 100, 'paramType' => 'named'); $this->assertEquals($expected, $result); $this->Paginator->settings = array( 'maxLimit' => 10, 'paramType' => 'named', ); $result = $this->Paginator->mergeOptions('Post'); $expected = array('page' => 1, 'limit' => 20, 'maxLimit' => 10, 'paramType' => 'named'); $this->assertEquals($expected, $result); $this->request->params['named'] = array( 'limit' => 500 ); $this->Paginator->settings = array( 'limit' => 150, 'paramType' => 'named', ); $result = $this->Paginator->mergeOptions('Post'); $expected = array('page' => 1, 'limit' => 500, 'maxLimit' => 100, 'paramType' => 'named'); $this->assertEquals($expected, $result); } /** * test that invalid directions are ignored. * * @return void */ public function testValidateSortInvalidDirection() { $model = $this->getMock('Model'); $model->alias = 'model'; $model->expects($this->any())->method('hasField')->will($this->returnValue(true)); $options = array('sort' => 'something', 'direction' => 'boogers'); $result = $this->Paginator->validateSort($model, $options); $this->assertEquals('asc', $result['order']['model.something']); } /** * Test that a really large page number gets clamped to the max page size. * * @expectedException NotFoundException * @return void */ public function testOutOfRangePageNumberGetsClamped() { $Controller = new PaginatorTestController($this->request); $Controller->uses = array('PaginatorControllerPost'); $Controller->params['named'] = array( 'page' => 3000, ); $Controller->constructClasses(); $Controller->PaginatorControllerPost->recursive = 0; $Controller->Paginator->paginate('PaginatorControllerPost'); } /** * Test that a really REALLY large page number gets clamped to the max page size. * * @expectedException NotFoundException * @return void */ public function testOutOfVeryBigPageNumberGetsClamped() { $Controller = new PaginatorTestController($this->request); $Controller->uses = array('PaginatorControllerPost'); $Controller->params['named'] = array( 'page' => '3000000000000000000000000', ); $Controller->constructClasses(); $Controller->PaginatorControllerPost->recursive = 0; $Controller->Paginator->paginate('PaginatorControllerPost'); } /** * testOutOfRangePageNumberAndPageCountZero * * @return void */ public function testOutOfRangePageNumberAndPageCountZero() { $Controller = new PaginatorTestController($this->request); $Controller->uses = array('PaginatorControllerPost'); $Controller->params['named'] = array( 'page' => '3000', ); $Controller->constructClasses(); $Controller->PaginatorControllerPost->recursive = 0; $Controller->paginate = array( 'conditions' => array('PaginatorControllerPost.id >' => 100) ); try { $Controller->Paginator->paginate('PaginatorControllerPost'); $this->fail(); } catch (NotFoundException $e) { $this->assertEquals( 1, $Controller->request->params['paging']['PaginatorControllerPost']['page'], 'Page number should not be 0' ); } } /** * test that fields not in whitelist won't be part of order conditions. * * @return void */ public function testValidateSortWhitelistFailure() { $model = $this->getMock('Model'); $model->alias = 'model'; $model->expects($this->any())->method('hasField')->will($this->returnValue(true)); $options = array('sort' => 'body', 'direction' => 'asc'); $result = $this->Paginator->validateSort($model, $options, array('title', 'id')); $this->assertNull($result['order']); } /** * test that fields in the whitelist are not validated * * @return void */ public function testValidateSortWhitelistTrusted() { $model = $this->getMock('Model'); $model->alias = 'model'; $model->expects($this->never())->method('hasField'); $options = array('sort' => 'body', 'direction' => 'asc'); $result = $this->Paginator->validateSort($model, $options, array('body')); $expected = array('body' => 'asc'); $this->assertEquals($expected, $result['order']); } /** * test that virtual fields work. * * @return void */ public function testValidateSortVirtualField() { $model = $this->getMock('Model'); $model->alias = 'model'; $model->expects($this->at(0)) ->method('hasField') ->with('something') ->will($this->returnValue(false)); $model->expects($this->at(1)) ->method('hasField') ->with('something', true) ->will($this->returnValue(true)); $options = array('sort' => 'something', 'direction' => 'desc'); $result = $this->Paginator->validateSort($model, $options); $this->assertEquals('desc', $result['order']['something']); } /** * test that sorting fields is alias specific * * @return void */ public function testValidateSortSharedFields() { $model = $this->getMock('Model'); $model->alias = 'Parent'; $model->Child = $this->getMock('Model'); $model->Child->alias = 'Child'; $model->expects($this->never()) ->method('hasField'); $model->Child->expects($this->at(0)) ->method('hasField') ->with('something') ->will($this->returnValue(true)); $options = array('sort' => 'Child.something', 'direction' => 'desc'); $result = $this->Paginator->validateSort($model, $options); $this->assertEquals('desc', $result['order']['Child.something']); } /** * test that multiple sort works. * * @return void */ public function testValidateSortMultiple() { $model = $this->getMock('Model'); $model->alias = 'model'; $model->expects($this->any())->method('hasField')->will($this->returnValue(true)); $options = array( 'order' => array( 'author_id' => 'asc', 'title' => 'asc' ) ); $result = $this->Paginator->validateSort($model, $options); $expected = array( 'model.author_id' => 'asc', 'model.title' => 'asc' ); $this->assertEquals($expected, $result['order']); } /** * Test that no sort doesn't trigger an error. * * @return void */ public function testValidateSortNoSort() { $model = $this->getMock('Model'); $model->alias = 'model'; $model->expects($this->any())->method('hasField')->will($this->returnValue(true)); $options = array('direction' => 'asc'); $result = $this->Paginator->validateSort($model, $options, array('title', 'id')); $this->assertFalse(isset($result['order'])); $options = array('order' => 'invalid desc'); $result = $this->Paginator->validateSort($model, $options, array('title', 'id')); $this->assertEquals($options['order'], $result['order']); } /** * Test sorting with incorrect aliases on valid fields. * * @return void */ public function testValidateSortInvalidAlias() { $model = $this->getMock('Model'); $model->alias = 'Model'; $model->expects($this->any())->method('hasField')->will($this->returnValue(true)); $options = array('sort' => 'Derp.id'); $result = $this->Paginator->validateSort($model, $options); $this->assertEquals(array(), $result['order']); } /** * test that maxLimit is respected * * @return void */ public function testCheckLimit() { $result = $this->Paginator->checkLimit(array('limit' => 1000000, 'maxLimit' => 100)); $this->assertEquals(100, $result['limit']); $result = $this->Paginator->checkLimit(array('limit' => 'sheep!', 'maxLimit' => 100)); $this->assertEquals(1, $result['limit']); $result = $this->Paginator->checkLimit(array('limit' => '-1', 'maxLimit' => 100)); $this->assertEquals(1, $result['limit']); $result = $this->Paginator->checkLimit(array('limit' => null, 'maxLimit' => 100)); $this->assertEquals(1, $result['limit']); $result = $this->Paginator->checkLimit(array('limit' => 0, 'maxLimit' => 100)); $this->assertEquals(1, $result['limit']); } /** * testPaginateMaxLimit * * @return void */ public function testPaginateMaxLimit() { $Controller = new Controller($this->request); $Controller->uses = array('PaginatorControllerPost', 'ControllerComment'); $Controller->request->params['pass'][] = '1'; $Controller->constructClasses(); $Controller->request->params['named'] = array( 'contain' => array('ControllerComment'), 'limit' => '1000' ); $Controller->paginate('PaginatorControllerPost'); $this->assertEquals(100, $Controller->params['paging']['PaginatorControllerPost']['options']['limit']); $Controller->request->params['named'] = array( 'contain' => array('ControllerComment'), 'limit' => '1000', 'maxLimit' => 1000 ); $Controller->paginate('PaginatorControllerPost'); $this->assertEquals(100, $Controller->params['paging']['PaginatorControllerPost']['options']['limit']); $Controller->request->params['named'] = array('contain' => array('ControllerComment'), 'limit' => '10'); $Controller->paginate('PaginatorControllerPost'); $this->assertEquals(10, $Controller->params['paging']['PaginatorControllerPost']['options']['limit']); $Controller->request->params['named'] = array('contain' => array('ControllerComment'), 'limit' => '1000'); $Controller->paginate = array('maxLimit' => 2000, 'paramType' => 'named'); $Controller->paginate('PaginatorControllerPost'); $this->assertEquals(1000, $Controller->params['paging']['PaginatorControllerPost']['options']['limit']); $Controller->request->params['named'] = array('contain' => array('ControllerComment'), 'limit' => '5000'); $Controller->paginate('PaginatorControllerPost'); $this->assertEquals(2000, $Controller->params['paging']['PaginatorControllerPost']['options']['limit']); } /** * test paginate() and virtualField overlapping with real fields. * * @return void */ public function testPaginateOrderVirtualFieldSharedWithRealField() { $Controller = new Controller($this->request); $Controller->uses = array('PaginatorControllerPost', 'PaginatorControllerComment'); $Controller->constructClasses(); $Controller->PaginatorControllerComment->virtualFields = array( 'title' => 'PaginatorControllerComment.comment' ); $Controller->PaginatorControllerComment->bindModel(array( 'belongsTo' => array( 'PaginatorControllerPost' => array( 'className' => 'PaginatorControllerPost', 'foreignKey' => 'article_id' ) ) ), false); $Controller->paginate = array( 'fields' => array( 'PaginatorControllerComment.id', 'title', 'PaginatorControllerPost.title' ), ); $Controller->request->params['named'] = array( 'sort' => 'PaginatorControllerPost.title', 'direction' => 'desc' ); $result = Hash::extract( $Controller->paginate('PaginatorControllerComment'), '{n}.PaginatorControllerComment.id' ); $result1 = array_splice($result, 0, 2); sort($result1); $this->assertEquals(array(5, 6), $result1); sort($result); $this->assertEquals(array(1, 2, 3, 4), $result); } /** * test paginate() and custom find, to make sure the correct count is returned. * * @return void */ public function testPaginateCustomFind() { $Controller = new Controller($this->request); $Controller->uses = array('PaginatorCustomPost'); $Controller->constructClasses(); $data = array('author_id' => 3, 'title' => 'Fourth Article', 'body' => 'Article Body, unpublished', 'published' => 'N'); $Controller->PaginatorCustomPost->create($data); $result = $Controller->PaginatorCustomPost->save(); $this->assertTrue(!empty($result)); $result = $Controller->paginate(); $this->assertEquals(array(1, 2, 3, 4), Hash::extract($result, '{n}.PaginatorCustomPost.id')); $result = $Controller->params['paging']['PaginatorCustomPost']; $this->assertEquals(4, $result['current']); $this->assertEquals(4, $result['count']); $Controller->paginate = array('published'); $result = $Controller->paginate(); $this->assertEquals(array(1, 2, 3), Hash::extract($result, '{n}.PaginatorCustomPost.id')); $result = $Controller->params['paging']['PaginatorCustomPost']; $this->assertEquals(3, $result['current']); $this->assertEquals(3, $result['count']); $Controller->paginate = array('published', 'limit' => 2); $result = $Controller->paginate(); $this->assertEquals(array(1, 2), Hash::extract($result, '{n}.PaginatorCustomPost.id')); $result = $Controller->params['paging']['PaginatorCustomPost']; $this->assertEquals(2, $result['current']); $this->assertEquals(3, $result['count']); $this->assertEquals(2, $result['pageCount']); $this->assertTrue($result['nextPage']); $this->assertFalse($result['prevPage']); } /** * test paginate() and custom find with fields array, to make sure the correct count is returned. * * @return void */ public function testPaginateCustomFindFieldsArray() { $Controller = new Controller($this->request); $Controller->uses = array('PaginatorCustomPost'); $Controller->constructClasses(); $data = array('author_id' => 3, 'title' => 'Fourth Article', 'body' => 'Article Body, unpublished', 'published' => 'N'); $Controller->PaginatorCustomPost->create($data); $result = $Controller->PaginatorCustomPost->save(); $this->assertTrue(!empty($result)); $Controller->paginate = array( 'list', 'conditions' => array('PaginatorCustomPost.published' => 'Y'), 'limit' => 2 ); $result = $Controller->paginate(); $expected = array( 1 => 'First Post', 2 => 'Second Post', ); $this->assertEquals($expected, $result); $result = $Controller->params['paging']['PaginatorCustomPost']; $this->assertEquals(2, $result['current']); $this->assertEquals(3, $result['count']); $this->assertEquals(2, $result['pageCount']); $this->assertTrue($result['nextPage']); $this->assertFalse($result['prevPage']); } /** * test paginate() and custom find with customFind key, to make sure the correct count is returned. * * @return void */ public function testPaginateCustomFindWithCustomFindKey() { $Controller = new Controller($this->request); $Controller->uses = array('PaginatorCustomPost'); $Controller->constructClasses(); $data = array('author_id' => 3, 'title' => 'Fourth Article', 'body' => 'Article Body, unpublished', 'published' => 'N'); $Controller->PaginatorCustomPost->create($data); $result = $Controller->PaginatorCustomPost->save(); $this->assertTrue(!empty($result)); $Controller->paginate = array( 'conditions' => array('PaginatorCustomPost.published' => 'Y'), 'findType' => 'list', 'limit' => 2 ); $result = $Controller->paginate(); $expected = array( 1 => 'First Post', 2 => 'Second Post', ); $this->assertEquals($expected, $result); $result = $Controller->params['paging']['PaginatorCustomPost']; $this->assertEquals(2, $result['current']); $this->assertEquals(3, $result['count']); $this->assertEquals(2, $result['pageCount']); $this->assertTrue($result['nextPage']); $this->assertFalse($result['prevPage']); } /** * test paginate() and custom find with fields array, to make sure the correct count is returned. * * @return void */ public function testPaginateCustomFindGroupBy() { $Controller = new Controller($this->request); $Controller->uses = array('PaginatorCustomPost'); $Controller->constructClasses(); $data = array('author_id' => 2, 'title' => 'Fourth Article', 'body' => 'Article Body, unpublished', 'published' => 'N'); $Controller->PaginatorCustomPost->create($data); $result = $Controller->PaginatorCustomPost->save(); $this->assertTrue(!empty($result)); $Controller->paginate = array( 'totals', 'limit' => 2 ); $result = $Controller->paginate(); $expected = array( array( 'PaginatorCustomPost' => array( 'author_id' => '1', 'total_posts' => '2' ) ), array( 'PaginatorCustomPost' => array( 'author_id' => '2', 'total_posts' => '1' ) ) ); $this->assertEquals($expected, $result); $result = $Controller->params['paging']['PaginatorCustomPost']; $this->assertEquals(2, $result['current']); $this->assertEquals(3, $result['count']); $this->assertEquals(2, $result['pageCount']); $this->assertTrue($result['nextPage']); $this->assertFalse($result['prevPage']); $Controller->paginate = array( 'totals', 'limit' => 2, 'page' => 2 ); $result = $Controller->paginate(); $expected = array( array( 'PaginatorCustomPost' => array( 'author_id' => '3', 'total_posts' => '1' ) ), ); $this->assertEquals($expected, $result); $result = $Controller->params['paging']['PaginatorCustomPost']; $this->assertEquals(1, $result['current']); $this->assertEquals(3, $result['count']); $this->assertEquals(2, $result['pageCount']); $this->assertFalse($result['nextPage']); $this->assertTrue($result['prevPage']); } /** * test paginate() and custom find with returning other query on count operation, * to make sure the correct count is returned. * * @return void */ public function testPaginateCustomFindCount() { $Controller = new Controller($this->request); $Controller->uses = array('PaginatorCustomPost'); $Controller->constructClasses(); $data = array('author_id' => 2, 'title' => 'Fourth Article', 'body' => 'Article Body, unpublished', 'published' => 'N'); $Controller->PaginatorCustomPost->create($data); $result = $Controller->PaginatorCustomPost->save(); $this->assertTrue(!empty($result)); $Controller->paginate = array( 'totalsOperation', 'limit' => 2 ); $result = $Controller->paginate(); $expected = array( array( 'PaginatorCustomPost' => array( 'author_id' => '1', 'total_posts' => '2' ), 'Author' => array( 'user' => 'mariano', ) ), array( 'PaginatorCustomPost' => array( 'author_id' => '2', 'total_posts' => '1' ), 'Author' => array( 'user' => 'nate' ) ) ); $this->assertEquals($expected, $result); $result = $Controller->params['paging']['PaginatorCustomPost']; $this->assertEquals(2, $result['current']); $this->assertEquals(3, $result['count']); $this->assertEquals(2, $result['pageCount']); $this->assertTrue($result['nextPage']); $this->assertFalse($result['prevPage']); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php000066400000000000000000000765171265552240500306340ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Controller.Component * @since CakePHP(tm) v 1.2.0.5435 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Controller', 'Controller'); App::uses('RequestHandlerComponent', 'Controller/Component'); App::uses('CakeRequest', 'Network'); App::uses('CakeResponse', 'Network'); App::uses('Router', 'Routing'); App::uses('JsonView', 'View'); /** * RequestHandlerTestController class * * @package Cake.Test.Case.Controller.Component */ class RequestHandlerTestController extends Controller { /** * uses property * * @var mixed */ public $uses = null; /** * test method for ajax redirection * * @return void */ public function destination() { $this->viewPath = 'Posts'; $this->render('index'); } /** * test method for ajax redirection + parameter parsing * * @return void */ public function param_method($one = null, $two = null) { echo "one: $one two: $two"; $this->autoRender = false; } /** * test method for testing layout rendering when isAjax() * * @return void */ public function ajax2_layout() { if ($this->autoLayout) { $this->layout = 'ajax2'; } $this->destination(); } } /** * CustomJsonView class * * @package Cake.Test.Case.Controller.Component */ class CustomJsonView extends JsonView { } /** * RequestHandlerComponentTest class * * @package Cake.Test.Case.Controller.Component */ class RequestHandlerComponentTest extends CakeTestCase { /** * Controller property * * @var RequestHandlerTestController */ public $Controller; /** * RequestHandler property * * @var RequestHandlerComponent */ public $RequestHandler; /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->_init(); } /** * init method * * @return void */ protected function _init() { $request = new CakeRequest('controller_posts/index'); $response = new CakeResponse(); $this->Controller = new RequestHandlerTestController($request, $response); $this->Controller->constructClasses(); $this->RequestHandler = new RequestHandlerComponent($this->Controller->Components); $this->_extensions = Router::extensions(); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->RequestHandler, $this->Controller); if (!headers_sent()) { header('Content-type: text/html'); //reset content type. } call_user_func_array('Router::parseExtensions', $this->_extensions); } /** * Test that the constructor sets the settings. * * @return void */ public function testConstructorSettings() { $settings = array( 'ajaxLayout' => 'test_ajax', 'viewClassMap' => array('json' => 'MyPlugin.MyJson') ); $Collection = new ComponentCollection(); $Collection->init($this->Controller); $RequestHandler = new RequestHandlerComponent($Collection, $settings); $this->assertEquals('test_ajax', $RequestHandler->ajaxLayout); $this->assertEquals(array('json' => 'MyPlugin.MyJson'), $RequestHandler->settings['viewClassMap']); } /** * testInitializeCallback method * * @return void */ public function testInitializeCallback() { $this->assertNull($this->RequestHandler->ext); $this->Controller->request->params['ext'] = 'rss'; $this->RequestHandler->initialize($this->Controller); $this->assertEquals('rss', $this->RequestHandler->ext); } /** * test that a mapped Accept-type header will set $this->ext correctly. * * @return void */ public function testInitializeContentTypeSettingExt() { $this->assertNull($this->RequestHandler->ext); $_SERVER['HTTP_ACCEPT'] = 'application/json'; Router::parseExtensions('json'); $this->RequestHandler->initialize($this->Controller); $this->assertEquals('json', $this->RequestHandler->ext); } /** * Test that RequestHandler sets $this->ext when jQuery sends its wonky-ish headers. * * @return void */ public function testInitializeContentTypeWithjQueryAccept() { $_SERVER['HTTP_ACCEPT'] = 'application/json, application/javascript, */*; q=0.01'; $this->assertNull($this->RequestHandler->ext); Router::parseExtensions('json'); $this->RequestHandler->initialize($this->Controller); $this->assertEquals('json', $this->RequestHandler->ext); } /** * Test that RequestHandler does not set extension to csv for text/plain mimetype * * @return void */ public function testInitializeContentTypeWithjQueryTextPlainAccept() { $_SERVER['HTTP_ACCEPT'] = 'text/plain, */*; q=0.01'; $this->assertNull($this->RequestHandler->ext); Router::parseExtensions('csv'); $this->RequestHandler->initialize($this->Controller); $this->assertNull($this->RequestHandler->ext); } /** * Test that RequestHandler sets $this->ext when jQuery sends its wonky-ish headers * and the application is configured to handle multiple extensions * * @return void */ public function testInitializeContentTypeWithjQueryAcceptAndMultiplesExtensions() { $_SERVER['HTTP_ACCEPT'] = 'application/json, application/javascript, */*; q=0.01'; $this->assertNull($this->RequestHandler->ext); Router::parseExtensions('rss', 'json'); $this->RequestHandler->initialize($this->Controller); $this->assertEquals('json', $this->RequestHandler->ext); } /** * Test that RequestHandler does not set $this->ext when multiple accepts are sent. * * @return void */ public function testInitializeNoContentTypeWithSingleAccept() { $_SERVER['HTTP_ACCEPT'] = 'application/json, text/html, */*; q=0.01'; $this->assertNull($this->RequestHandler->ext); Router::parseExtensions('json'); $this->RequestHandler->initialize($this->Controller); $this->assertNull($this->RequestHandler->ext); } /** * Test that ext is set to the first listed extension with multiple accepted * content types. * Having multiple types accepted with same weight, means the client lets the * server choose the returned content type. * * @return void */ public function testInitializeNoContentTypeWithMultipleAcceptedTypes() { $_SERVER['HTTP_ACCEPT'] = 'application/json, application/javascript, application/xml, */*; q=0.01'; $this->assertNull($this->RequestHandler->ext); Router::parseExtensions('xml', 'json'); $this->RequestHandler->initialize($this->Controller); $this->assertEquals('xml', $this->RequestHandler->ext); $this->RequestHandler->ext = null; Router::setExtensions(array('json', 'xml'), false); $this->RequestHandler->initialize($this->Controller); $this->assertEquals('json', $this->RequestHandler->ext); } /** * Test that ext is set to type with highest weight * * @return void */ public function testInitializeContentTypeWithMultipleAcceptedTypes() { $_SERVER['HTTP_ACCEPT'] = 'text/csv;q=1.0, application/json;q=0.8, application/xml;q=0.7'; $this->assertNull($this->RequestHandler->ext); Router::parseExtensions('xml', 'json'); $this->RequestHandler->initialize($this->Controller); $this->assertEquals('json', $this->RequestHandler->ext); } /** * Test that ext is not set with confusing android accepts headers. * * @return void */ public function testInitializeAmbiguousAndroidAccepts() { $_SERVER['HTTP_ACCEPT'] = 'application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5'; $this->assertNull($this->RequestHandler->ext); Router::parseExtensions('html', 'xml'); $this->RequestHandler->initialize($this->Controller); $this->assertNull($this->RequestHandler->ext); } /** * Test that the headers sent by firefox are not treated as XML requests. * * @return void */ public function testInititalizeFirefoxHeaderNotXml() { $_SERVER['HTTP_ACCEPT'] = 'text/html,application/xhtml+xml,application/xml;image/png,image/jpeg,image/*;q=0.9,*/*;q=0.8'; Router::parseExtensions('xml', 'json'); $this->RequestHandler->initialize($this->Controller); $this->assertNull($this->RequestHandler->ext); } /** * Test that a type mismatch doesn't incorrectly set the ext * * @return void */ public function testInitializeContentTypeAndExtensionMismatch() { $this->assertNull($this->RequestHandler->ext); $extensions = Router::extensions(); Router::parseExtensions('xml'); $this->Controller->request = $this->getMock('CakeRequest'); $this->Controller->request->expects($this->any()) ->method('accepts') ->will($this->returnValue(array('application/json'))); $this->RequestHandler->initialize($this->Controller); $this->assertNull($this->RequestHandler->ext); call_user_func_array(array('Router', 'parseExtensions'), $extensions); } /** * testViewClassMap method * * @return void */ public function testViewClassMap() { $this->RequestHandler->settings = array('viewClassMap' => array('json' => 'CustomJson')); $this->RequestHandler->initialize($this->Controller); $result = $this->RequestHandler->viewClassMap(); $expected = array( 'json' => 'CustomJson', 'xml' => 'Xml' ); $this->assertEquals($expected, $result); $result = $this->RequestHandler->viewClassMap('xls', 'Excel.Excel'); $expected = array( 'json' => 'CustomJson', 'xml' => 'Xml', 'xls' => 'Excel.Excel' ); $this->assertEquals($expected, $result); $this->RequestHandler->renderAs($this->Controller, 'json'); $this->assertEquals('CustomJson', $this->Controller->viewClass); } /** * testDisabling method * * @return void */ public function testDisabling() { $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; $this->_init(); $this->RequestHandler->initialize($this->Controller); $this->Controller->beforeFilter(); $this->RequestHandler->startup($this->Controller); $this->assertEquals(true, $this->Controller->params['isAjax']); } /** * testAutoAjaxLayout method * * @return void */ public function testAutoAjaxLayout() { $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; $this->RequestHandler->startup($this->Controller); $this->assertEquals($this->Controller->layout, $this->RequestHandler->ajaxLayout); $this->_init(); $this->Controller->request->params['ext'] = 'js'; $this->RequestHandler->initialize($this->Controller); $this->RequestHandler->startup($this->Controller); $this->assertNotEquals('ajax', $this->Controller->layout); unset($_SERVER['HTTP_X_REQUESTED_WITH']); } /** * testStartupCallback method * * @return void */ public function testStartupCallback() { $_SERVER['REQUEST_METHOD'] = 'PUT'; $_SERVER['CONTENT_TYPE'] = 'application/xml'; $this->Controller->request = $this->getMock('CakeRequest', array('_readInput')); $this->RequestHandler->startup($this->Controller); $this->assertTrue(is_array($this->Controller->data)); $this->assertFalse(is_object($this->Controller->data)); } /** * testStartupCallback with charset. * * @return void */ public function testStartupCallbackCharset() { $_SERVER['REQUEST_METHOD'] = 'PUT'; $_SERVER['CONTENT_TYPE'] = 'application/xml; charset=UTF-8'; $this->Controller->request = $this->getMock('CakeRequest', array('_readInput')); $this->RequestHandler->startup($this->Controller); $this->assertTrue(is_array($this->Controller->data)); $this->assertFalse(is_object($this->Controller->data)); } /** * Test mapping a new type and having startup process it. * * @return void */ public function testStartupCustomTypeProcess() { if (!function_exists('str_getcsv')) { $this->markTestSkipped('Need "str_getcsv" for this test.'); } $_SERVER['REQUEST_METHOD'] = 'POST'; $_SERVER['CONTENT_TYPE'] = 'text/csv'; $this->Controller->request = $this->getMock('CakeRequest', array('_readInput')); $this->Controller->request->expects($this->once()) ->method('_readInput') ->will($this->returnValue('"A","csv","string"')); $this->RequestHandler->addInputType('csv', array('str_getcsv')); $this->RequestHandler->startup($this->Controller); $expected = array( 'A', 'csv', 'string' ); $this->assertEquals($expected, $this->Controller->request->data); } /** * testNonAjaxRedirect method * * @return void */ public function testNonAjaxRedirect() { $this->RequestHandler->initialize($this->Controller); $this->RequestHandler->startup($this->Controller); $this->assertNull($this->RequestHandler->beforeRedirect($this->Controller, '/')); } /** * test that redirects with ajax and no URL don't do anything. * * @return void */ public function testAjaxRedirectWithNoUrl() { $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; $this->Controller->response = $this->getMock('CakeResponse'); $this->Controller->response->expects($this->never()) ->method('body'); $this->RequestHandler->initialize($this->Controller); $this->RequestHandler->startup($this->Controller); $this->assertNull($this->RequestHandler->beforeRedirect($this->Controller, null)); } /** * testRenderAs method * * @return void */ public function testRenderAs() { $this->assertFalse(in_array('Rss', $this->Controller->helpers)); $this->RequestHandler->renderAs($this->Controller, 'rss'); $this->assertTrue(in_array('Rss', $this->Controller->helpers)); $this->Controller->viewPath = 'request_handler_test\\rss'; $this->RequestHandler->renderAs($this->Controller, 'js'); $this->assertEquals('request_handler_test' . DS . 'js', $this->Controller->viewPath); } /** * test that attachment headers work with renderAs * * @return void */ public function testRenderAsWithAttachment() { $this->RequestHandler->request = $this->getMock('CakeRequest'); $this->RequestHandler->request->expects($this->any()) ->method('parseAccept') ->will($this->returnValue(array('1.0' => array('application/xml')))); $this->RequestHandler->response = $this->getMock('CakeResponse', array('type', 'download', 'charset')); $this->RequestHandler->response->expects($this->at(0)) ->method('type') ->with('application/xml'); $this->RequestHandler->response->expects($this->at(1)) ->method('charset') ->with('UTF-8'); $this->RequestHandler->response->expects($this->at(2)) ->method('download') ->with('myfile.xml'); $this->RequestHandler->renderAs($this->Controller, 'xml', array('attachment' => 'myfile.xml')); $this->assertEquals('Xml', $this->Controller->viewClass); } /** * test that respondAs works as expected. * * @return void */ public function testRespondAs() { $this->RequestHandler->response = $this->getMock('CakeResponse', array('type')); $this->RequestHandler->response->expects($this->at(0))->method('type') ->with('application/json'); $this->RequestHandler->response->expects($this->at(1))->method('type') ->with('text/xml'); $result = $this->RequestHandler->respondAs('json'); $this->assertTrue($result); $result = $this->RequestHandler->respondAs('text/xml'); $this->assertTrue($result); } /** * test that attachment headers work with respondAs * * @return void */ public function testRespondAsWithAttachment() { $this->RequestHandler = $this->getMock( 'RequestHandlerComponent', array('_header'), array(&$this->Controller->Components) ); $this->RequestHandler->response = $this->getMock('CakeResponse', array('type', 'download')); $this->RequestHandler->request = $this->getMock('CakeRequest'); $this->RequestHandler->request->expects($this->once()) ->method('parseAccept') ->will($this->returnValue(array('1.0' => array('application/xml')))); $this->RequestHandler->response->expects($this->once())->method('download') ->with('myfile.xml'); $this->RequestHandler->response->expects($this->once())->method('type') ->with('application/xml'); $result = $this->RequestHandler->respondAs('xml', array('attachment' => 'myfile.xml')); $this->assertTrue($result); } /** * test that calling renderAs() more than once continues to work. * * @link #6466 * @return void */ public function testRenderAsCalledTwice() { $this->RequestHandler->renderAs($this->Controller, 'print'); $this->assertEquals('RequestHandlerTest' . DS . 'print', $this->Controller->viewPath); $this->assertEquals('print', $this->Controller->layoutPath); $this->RequestHandler->renderAs($this->Controller, 'js'); $this->assertEquals('RequestHandlerTest' . DS . 'js', $this->Controller->viewPath); $this->assertEquals('js', $this->Controller->layoutPath); $this->assertTrue(in_array('Js', $this->Controller->helpers)); } /** * testRequestClientTypes method * * @return void */ public function testRequestClientTypes() { $_SERVER['HTTP_X_PROTOTYPE_VERSION'] = '1.5'; $this->assertEquals('1.5', $this->RequestHandler->getAjaxVersion()); unset($_SERVER['HTTP_X_REQUESTED_WITH'], $_SERVER['HTTP_X_PROTOTYPE_VERSION']); $this->assertFalse($this->RequestHandler->getAjaxVersion()); } /** * Tests the detection of various Flash versions * * @return void */ public function testFlashDetection() { $request = $this->getMock('CakeRequest'); $request->expects($this->once())->method('is') ->with('flash') ->will($this->returnValue(true)); $this->RequestHandler->request = $request; $this->assertTrue($this->RequestHandler->isFlash()); } /** * testRequestContentTypes method * * @return void */ public function testRequestContentTypes() { $_SERVER['REQUEST_METHOD'] = 'GET'; $this->assertNull($this->RequestHandler->requestedWith()); $_SERVER['REQUEST_METHOD'] = 'POST'; $_SERVER['CONTENT_TYPE'] = 'application/json'; $this->assertEquals('json', $this->RequestHandler->requestedWith()); $result = $this->RequestHandler->requestedWith(array('json', 'xml')); $this->assertEquals('json', $result); $result = $this->RequestHandler->requestedWith(array('rss', 'atom')); $this->assertFalse($result); $_SERVER['REQUEST_METHOD'] = 'DELETE'; $this->assertEquals('json', $this->RequestHandler->requestedWith()); $_SERVER['REQUEST_METHOD'] = 'POST'; unset($_SERVER['CONTENT_TYPE']); $_SERVER['HTTP_CONTENT_TYPE'] = 'application/json'; $result = $this->RequestHandler->requestedWith(array('json', 'xml')); $this->assertEquals('json', $result); $result = $this->RequestHandler->requestedWith(array('rss', 'atom')); $this->assertFalse($result); $_SERVER['HTTP_ACCEPT'] = 'text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,*/*'; $this->assertTrue($this->RequestHandler->isXml()); $this->assertFalse($this->RequestHandler->isAtom()); $this->assertFalse($this->RequestHandler->isRSS()); $_SERVER['HTTP_ACCEPT'] = 'application/atom+xml,text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,*/*'; $this->assertTrue($this->RequestHandler->isAtom()); $this->assertFalse($this->RequestHandler->isRSS()); $_SERVER['HTTP_ACCEPT'] = 'application/rss+xml,text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,*/*'; $this->assertFalse($this->RequestHandler->isAtom()); $this->assertTrue($this->RequestHandler->isRSS()); $this->assertFalse($this->RequestHandler->isWap()); $_SERVER['HTTP_ACCEPT'] = 'text/vnd.wap.wml,text/html,text/plain,image/png,*/*'; $this->assertTrue($this->RequestHandler->isWap()); $_SERVER['HTTP_ACCEPT'] = 'application/rss+xml,text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,*/*'; } /** * testResponseContentType method * * @return void */ public function testResponseContentType() { $this->assertEquals('html', $this->RequestHandler->responseType()); $this->assertTrue($this->RequestHandler->respondAs('atom')); $this->assertEquals('atom', $this->RequestHandler->responseType()); } /** * testMobileDeviceDetection method * * @return void */ public function testMobileDeviceDetection() { $request = $this->getMock('CakeRequest'); $request->expects($this->once())->method('is') ->with('mobile') ->will($this->returnValue(true)); $this->RequestHandler->request = $request; $this->assertTrue($this->RequestHandler->isMobile()); } /** * testRequestProperties method * * @return void */ public function testRequestProperties() { $request = $this->getMock('CakeRequest'); $request->expects($this->once())->method('is') ->with('ssl') ->will($this->returnValue(true)); $this->RequestHandler->request = $request; $this->assertTrue($this->RequestHandler->isSsl()); } /** * testRequestMethod method * * @return void */ public function testRequestMethod() { $request = $this->getMock('CakeRequest'); $request->expects($this->at(0))->method('is') ->with('get') ->will($this->returnValue(true)); $request->expects($this->at(1))->method('is') ->with('post') ->will($this->returnValue(false)); $request->expects($this->at(2))->method('is') ->with('delete') ->will($this->returnValue(true)); $request->expects($this->at(3))->method('is') ->with('put') ->will($this->returnValue(false)); $this->RequestHandler->request = $request; $this->assertTrue($this->RequestHandler->isGet()); $this->assertFalse($this->RequestHandler->isPost()); $this->assertTrue($this->RequestHandler->isDelete()); $this->assertFalse($this->RequestHandler->isPut()); } /** * test that map alias converts aliases to content types. * * @return void */ public function testMapAlias() { $result = $this->RequestHandler->mapAlias('xml'); $this->assertEquals('application/xml', $result); $result = $this->RequestHandler->mapAlias('text/html'); $this->assertNull($result); $result = $this->RequestHandler->mapAlias('wap'); $this->assertEquals('text/vnd.wap.wml', $result); $result = $this->RequestHandler->mapAlias(array('xml', 'js', 'json')); $expected = array('application/xml', 'application/javascript', 'application/json'); $this->assertEquals($expected, $result); } /** * test accepts() on the component * * @return void */ public function testAccepts() { $_SERVER['HTTP_ACCEPT'] = 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5'; $this->assertTrue($this->RequestHandler->accepts(array('js', 'xml', 'html'))); $this->assertFalse($this->RequestHandler->accepts(array('gif', 'jpeg', 'foo'))); $_SERVER['HTTP_ACCEPT'] = '*/*;q=0.5'; $this->assertFalse($this->RequestHandler->accepts('rss')); } /** * test accepts and prefers methods. * * @return void */ public function testPrefers() { $_SERVER['HTTP_ACCEPT'] = 'text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,*/*'; $this->assertNotEquals('rss', $this->RequestHandler->prefers()); $this->RequestHandler->ext = 'rss'; $this->assertEquals('rss', $this->RequestHandler->prefers()); $this->assertFalse($this->RequestHandler->prefers('xml')); $this->assertEquals('xml', $this->RequestHandler->prefers(array('js', 'xml', 'xhtml'))); $this->assertFalse($this->RequestHandler->prefers(array('red', 'blue'))); $this->assertEquals('xhtml', $this->RequestHandler->prefers(array('js', 'json', 'xhtml'))); $this->assertTrue($this->RequestHandler->prefers(array('rss')), 'Should return true if input matches ext.'); $this->assertFalse($this->RequestHandler->prefers(array('html')), 'No match with ext, return false.'); $_SERVER['HTTP_ACCEPT'] = 'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5'; $this->_init(); $this->assertEquals('xml', $this->RequestHandler->prefers()); $_SERVER['HTTP_ACCEPT'] = '*/*;q=0.5'; $this->assertEquals('html', $this->RequestHandler->prefers()); $this->assertFalse($this->RequestHandler->prefers('rss')); } /** * testCustomContent method * * @return void */ public function testCustomContent() { $_SERVER['HTTP_ACCEPT'] = 'text/x-mobile,text/html;q=0.9,text/plain;q=0.8,*/*;q=0.5'; $this->RequestHandler->setContent('mobile', 'text/x-mobile'); $this->RequestHandler->startup($this->Controller); $this->assertEquals('mobile', $this->RequestHandler->prefers()); } /** * testClientProperties method * * @return void */ public function testClientProperties() { $request = $this->getMock('CakeRequest'); $request->expects($this->once())->method('referer'); $request->expects($this->once())->method('clientIp')->will($this->returnValue(false)); $this->RequestHandler->request = $request; $this->RequestHandler->getReferer(); $this->RequestHandler->getClientIP(false); } /** * test that ajax requests involving redirects trigger requestAction instead. * * @return void */ public function testAjaxRedirectAsRequestAction() { App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) ), App::RESET); $this->Controller->RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components)); $this->Controller->request = $this->getMock('CakeRequest'); $this->Controller->response = $this->getMock('CakeResponse', array('_sendHeader')); $this->Controller->RequestHandler->request = $this->Controller->request; $this->Controller->RequestHandler->response = $this->Controller->response; $this->Controller->request->expects($this->any())->method('is')->will($this->returnValue(true)); $this->Controller->RequestHandler->expects($this->once())->method('_stop'); ob_start(); $this->Controller->RequestHandler->beforeRedirect( $this->Controller, array('controller' => 'request_handler_test', 'action' => 'destination') ); $result = ob_get_clean(); $this->assertRegExp('/posts index/', $result, 'RequestAction redirect failed.'); App::build(); } /** * test that ajax requests involving redirects don't force no layout * this would cause the ajax layout to not be rendered. * * @return void */ public function testAjaxRedirectAsRequestActionStillRenderingLayout() { App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) ), App::RESET); $this->Controller->RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components)); $this->Controller->request = $this->getMock('CakeRequest'); $this->Controller->response = $this->getMock('CakeResponse', array('_sendHeader')); $this->Controller->RequestHandler->request = $this->Controller->request; $this->Controller->RequestHandler->response = $this->Controller->response; $this->Controller->request->expects($this->any())->method('is')->will($this->returnValue(true)); $this->Controller->RequestHandler->expects($this->once())->method('_stop'); ob_start(); $this->Controller->RequestHandler->beforeRedirect( $this->Controller, array('controller' => 'request_handler_test', 'action' => 'ajax2_layout') ); $result = ob_get_clean(); $this->assertRegExp('/posts index/', $result, 'RequestAction redirect failed.'); $this->assertRegExp('/Ajax!/', $result, 'Layout was not rendered.'); App::build(); } /** * test that the beforeRedirect callback properly converts * array URLs into their correct string ones, and adds base => false so * the correct URLs are generated. * * @link https://cakephp.lighthouseapp.com/projects/42648-cakephp-1x/tickets/276 * @return void */ public function testBeforeRedirectCallbackWithArrayUrl() { $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; Router::setRequestInfo(array( array('plugin' => null, 'controller' => 'accounts', 'action' => 'index', 'pass' => array(), 'named' => array(), 'form' => array(), 'url' => array('url' => 'accounts/')), array('base' => '/officespace', 'here' => '/officespace/accounts/', 'webroot' => '/officespace/') )); $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components)); $RequestHandler->response = $this->getMock('CakeResponse', array('_sendHeader')); $RequestHandler->request = new CakeRequest('posts/index'); $RequestHandler->response = $this->getMock('CakeResponse', array('_sendHeader')); ob_start(); $RequestHandler->beforeRedirect( $this->Controller, array('controller' => 'request_handler_test', 'action' => 'param_method', 'first', 'second') ); $result = ob_get_clean(); $this->assertEquals('one: first two: second', $result); } /** * assure that beforeRedirect with a status code will correctly set the status header * * @return void */ public function testBeforeRedirectCallingHeader() { $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; $controller = $this->getMock('Controller', array('header')); $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components)); $RequestHandler->response = $this->getMock('CakeResponse', array('_sendHeader', 'statusCode')); $RequestHandler->request = $this->getMock('CakeRequest'); $RequestHandler->request->expects($this->once())->method('is') ->with('ajax') ->will($this->returnValue(true)); $RequestHandler->response->expects($this->once())->method('statusCode')->with(403); ob_start(); $RequestHandler->beforeRedirect($controller, 'request_handler_test/param_method/first/second', 403); ob_get_clean(); } /** * @expectedException CakeException * @return void */ public function testAddInputTypeException() { $this->RequestHandler->addInputType('csv', array('I am not callable')); } /** * Test checkNotModified method * * @return void */ public function testCheckNotModifiedByEtagStar() { $_SERVER['HTTP_IF_NONE_MATCH'] = '*'; $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components)); $RequestHandler->response = $this->getMock('CakeResponse', array('notModified')); $RequestHandler->response->etag('something'); $RequestHandler->response->expects($this->once())->method('notModified'); $this->assertFalse($RequestHandler->beforeRender($this->Controller)); } /** * Test checkNotModified method * * @return void */ public function testCheckNotModifiedByEtagExact() { $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"'; $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components)); $RequestHandler->response = $this->getMock('CakeResponse', array('notModified')); $RequestHandler->response->etag('something', true); $RequestHandler->response->expects($this->once())->method('notModified'); $this->assertFalse($RequestHandler->beforeRender($this->Controller)); } /** * Test checkNotModified method * * @return void */ public function testCheckNotModifiedByEtagAndTime() { $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"'; $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00'; $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components)); $RequestHandler->response = $this->getMock('CakeResponse', array('notModified')); $RequestHandler->response->etag('something', true); $RequestHandler->response->modified('2012-01-01 00:00:00'); $RequestHandler->response->expects($this->once())->method('notModified'); $this->assertFalse($RequestHandler->beforeRender($this->Controller)); } /** * Test checkNotModified method * * @return void */ public function testCheckNotModifiedNoInfo() { $RequestHandler = $this->getMock('RequestHandlerComponent', array('_stop'), array(&$this->Controller->Components)); $RequestHandler->response = $this->getMock('CakeResponse', array('notModified')); $RequestHandler->response->expects($this->never())->method('notModified'); $this->assertNull($RequestHandler->beforeRender($this->Controller)); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php000066400000000000000000001257311265552240500275060ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Controller.Component * @since CakePHP(tm) v 1.2.0.5435 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('SecurityComponent', 'Controller/Component'); App::uses('Controller', 'Controller'); /** * TestSecurityComponent * * @package Cake.Test.Case.Controller.Component */ class TestSecurityComponent extends SecurityComponent { /** * validatePost method * * @param Controller $controller * @return bool */ public function validatePost(Controller $controller) { return $this->_validatePost($controller); } } /** * SecurityTestController * * @package Cake.Test.Case.Controller.Component */ class SecurityTestController extends Controller { /** * components property * * @var array */ public $components = array('Session', 'TestSecurity'); /** * failed property * * @var bool */ public $failed = false; /** * Used for keeping track of headers in test * * @var array */ public $testHeaders = array(); /** * fail method * * @return void */ public function fail() { $this->failed = true; } /** * redirect method * * @param string|array $url * @param mixed $code * @param mixed $exit * @return void */ public function redirect($url, $status = null, $exit = true) { return $status; } /** * Convenience method for header() * * @param string $status * @return void */ public function header($status) { $this->testHeaders[] = $status; } } class BrokenCallbackController extends Controller { public $name = 'UncallableCallback'; public $components = array('Session', 'TestSecurity'); public function index() { } protected function _fail() { } } /** * SecurityComponentTest class * * @package Cake.Test.Case.Controller.Component */ class SecurityComponentTest extends CakeTestCase { /** * Controller property * * @var SecurityTestController */ public $Controller; /** * oldSalt property * * @var string */ public $oldSalt; /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $request = $this->getMock('CakeRequest', array('here'), array('posts/index', false)); $request->addParams(array('controller' => 'posts', 'action' => 'index')); $request->expects($this->any()) ->method('here') ->will($this->returnValue('/posts/index')); $this->Controller = new SecurityTestController($request); $this->Controller->Components->init($this->Controller); $this->Controller->Security = $this->Controller->TestSecurity; $this->Controller->Security->blackHoleCallback = 'fail'; $this->Security = $this->Controller->Security; $this->Security->csrfCheck = false; Configure::write('Security.salt', 'foo!'); } /** * Tear-down method. Resets environment state. * * @return void */ public function tearDown() { parent::tearDown(); $this->Controller->Session->delete('_Token'); unset($this->Controller->Security); unset($this->Controller->Component); unset($this->Controller); } /** * Test that requests are still blackholed when controller has incorrect * visibility keyword in the blackhole callback * * @expectedException BadRequestException * @return void */ public function testBlackholeWithBrokenCallback() { $request = new CakeRequest('posts/index', false); $request->addParams(array( 'controller' => 'posts', 'action' => 'index') ); $this->Controller = new BrokenCallbackController($request); $this->Controller->Components->init($this->Controller); $this->Controller->Security = $this->Controller->TestSecurity; $this->Controller->Security->blackHoleCallback = '_fail'; $this->Controller->Security->startup($this->Controller); $this->Controller->Security->blackHole($this->Controller, 'csrf'); } /** * Ensure that directly requesting the blackholeCallback as the controller * action results in an exception. * * @return void */ public function testExceptionWhenActionIsBlackholeCallback() { $this->Controller->request->addParams(array( 'controller' => 'posts', 'action' => 'fail' )); $this->assertFalse($this->Controller->failed); $this->Controller->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed, 'Request was blackholed.'); } /** * test that initialize can set properties. * * @return void */ public function testConstructorSettingProperties() { $settings = array( 'requirePost' => array('edit', 'update'), 'requireSecure' => array('update_account'), 'requireGet' => array('index'), 'validatePost' => false, ); $Security = new SecurityComponent($this->Controller->Components, $settings); $this->Controller->Security->initialize($this->Controller, $settings); $this->assertEquals($Security->requirePost, $settings['requirePost']); $this->assertEquals($Security->requireSecure, $settings['requireSecure']); $this->assertEquals($Security->requireGet, $settings['requireGet']); $this->assertEquals($Security->validatePost, $settings['validatePost']); } /** * testStartup method * * @return void */ public function testStartup() { $this->Controller->Security->startup($this->Controller); $result = $this->Controller->params['_Token']['key']; $this->assertNotNull($result); $this->assertTrue($this->Controller->Session->check('_Token')); } /** * testRequirePostFail method * * @return void */ public function testRequirePostFail() { $_SERVER['REQUEST_METHOD'] = 'GET'; $this->Controller->request['action'] = 'posted'; $this->Controller->Security->requirePost(array('posted')); $this->Controller->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed); } /** * testRequirePostSucceed method * * @return void */ public function testRequirePostSucceed() { $_SERVER['REQUEST_METHOD'] = 'POST'; $this->Controller->request['action'] = 'posted'; $this->Controller->Security->requirePost('posted'); $this->Security->startup($this->Controller); $this->assertFalse($this->Controller->failed); } /** * testRequireSecureFail method * * @return void */ public function testRequireSecureFail() { $_SERVER['HTTPS'] = 'off'; $_SERVER['REQUEST_METHOD'] = 'POST'; $this->Controller->request['action'] = 'posted'; $this->Controller->Security->requireSecure(array('posted')); $this->Controller->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed); } /** * testRequireSecureSucceed method * * @return void */ public function testRequireSecureSucceed() { $_SERVER['REQUEST_METHOD'] = 'Secure'; $this->Controller->request['action'] = 'posted'; $_SERVER['HTTPS'] = 'on'; $this->Controller->Security->requireSecure('posted'); $this->Controller->Security->startup($this->Controller); $this->assertFalse($this->Controller->failed); } /** * testRequireAuthFail method * * @return void */ public function testRequireAuthFail() { $_SERVER['REQUEST_METHOD'] = 'AUTH'; $this->Controller->request['action'] = 'posted'; $this->Controller->request->data = array('username' => 'willy', 'password' => 'somePass'); $this->Controller->Security->requireAuth(array('posted')); $this->Controller->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed); $this->Controller->Session->write('_Token', array('allowedControllers' => array())); $this->Controller->request->data = array('username' => 'willy', 'password' => 'somePass'); $this->Controller->request['action'] = 'posted'; $this->Controller->Security->requireAuth('posted'); $this->Controller->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed); $this->Controller->Session->write('_Token', array( 'allowedControllers' => array('SecurityTest'), 'allowedActions' => array('posted2') )); $this->Controller->request->data = array('username' => 'willy', 'password' => 'somePass'); $this->Controller->request['action'] = 'posted'; $this->Controller->Security->requireAuth('posted'); $this->Controller->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed); } /** * testRequireAuthSucceed method * * @return void */ public function testRequireAuthSucceed() { $_SERVER['REQUEST_METHOD'] = 'AUTH'; $this->Controller->Security->unlockedActions = array('posted'); $this->Controller->request['action'] = 'posted'; $this->Controller->Security->requireAuth('posted'); $this->Controller->Security->startup($this->Controller); $this->assertFalse($this->Controller->failed); $this->Controller->Security->Session->write('_Token', array( 'allowedControllers' => array('SecurityTest'), 'allowedActions' => array('posted') )); $this->Controller->request['controller'] = 'SecurityTest'; $this->Controller->request['action'] = 'posted'; $this->Controller->request->data = array( 'username' => 'willy', 'password' => 'somePass', '_Token' => '' ); $this->Controller->action = 'posted'; $this->Controller->Security->requireAuth('posted'); $this->Controller->Security->startup($this->Controller); $this->assertFalse($this->Controller->failed); } /** * testRequirePostSucceedWrongMethod method * * @return void */ public function testRequirePostSucceedWrongMethod() { $_SERVER['REQUEST_METHOD'] = 'GET'; $this->Controller->request['action'] = 'getted'; $this->Controller->Security->requirePost('posted'); $this->Controller->Security->startup($this->Controller); $this->assertFalse($this->Controller->failed); } /** * testRequireGetFail method * * @return void */ public function testRequireGetFail() { $_SERVER['REQUEST_METHOD'] = 'POST'; $this->Controller->request['action'] = 'getted'; $this->Controller->Security->requireGet(array('getted')); $this->Controller->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed); } /** * testRequireGetSucceed method * * @return void */ public function testRequireGetSucceed() { $_SERVER['REQUEST_METHOD'] = 'GET'; $this->Controller->request['action'] = 'getted'; $this->Controller->Security->requireGet('getted'); $this->Controller->Security->startup($this->Controller); $this->assertFalse($this->Controller->failed); } /** * testRequireGetSucceedWrongMethod method * * @return void */ public function testRequireGetSucceedWrongMethod() { $_SERVER['REQUEST_METHOD'] = 'POST'; $this->Controller->request['action'] = 'posted'; $this->Security->requireGet('getted'); $this->Security->startup($this->Controller); $this->assertFalse($this->Controller->failed); } /** * testRequirePutFail method * * @return void */ public function testRequirePutFail() { $_SERVER['REQUEST_METHOD'] = 'POST'; $this->Controller->request['action'] = 'putted'; $this->Controller->Security->requirePut(array('putted')); $this->Controller->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed); } /** * testRequirePutSucceed method * * @return void */ public function testRequirePutSucceed() { $_SERVER['REQUEST_METHOD'] = 'PUT'; $this->Controller->request['action'] = 'putted'; $this->Controller->Security->requirePut('putted'); $this->Controller->Security->startup($this->Controller); $this->assertFalse($this->Controller->failed); } /** * testRequirePutSucceedWrongMethod method * * @return void */ public function testRequirePutSucceedWrongMethod() { $_SERVER['REQUEST_METHOD'] = 'POST'; $this->Controller->request['action'] = 'posted'; $this->Controller->Security->requirePut('putted'); $this->Controller->Security->startup($this->Controller); $this->assertFalse($this->Controller->failed); } /** * testRequireDeleteFail method * * @return void */ public function testRequireDeleteFail() { $_SERVER['REQUEST_METHOD'] = 'POST'; $this->Controller->request['action'] = 'deleted'; $this->Controller->Security->requireDelete(array('deleted', 'other_method')); $this->Controller->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed); } /** * testRequireDeleteSucceed method * * @return void */ public function testRequireDeleteSucceed() { $_SERVER['REQUEST_METHOD'] = 'DELETE'; $this->Controller->request['action'] = 'deleted'; $this->Controller->Security->requireDelete('deleted'); $this->Controller->Security->startup($this->Controller); $this->assertFalse($this->Controller->failed); } /** * testRequireDeleteSucceedWrongMethod method * * @return void */ public function testRequireDeleteSucceedWrongMethod() { $_SERVER['REQUEST_METHOD'] = 'POST'; $this->Controller->request['action'] = 'posted'; $this->Controller->Security->requireDelete('deleted'); $this->Controller->Security->startup($this->Controller); $this->assertFalse($this->Controller->failed); } /** * Test that validatePost fires on GET with request data. * This could happen when method overriding is used. * * @return void * @triggers Controller.startup $this->Controller */ public function testValidatePostOnGetWithData() { $_SERVER['REQUEST_METHOD'] = 'GET'; $this->Controller->Security->startup($this->Controller); $fields = 'an-invalid-token'; $unlocked = ''; $this->Controller->request->data = array( 'Model' => array('username' => 'nate', 'password' => 'foo', 'valid' => '0'), '_Token' => compact('fields', 'unlocked') ); $this->assertFalse($this->Controller->failed, 'Should not be failed yet'); $this->Controller->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed, 'Should fail because of validatePost.'); } /** * Simple hash validation test * * @return void */ public function testValidatePost() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = '01c1f6dbba02ac6f21b229eab1cc666839b14303%3AModel.valid'; $unlocked = ''; $this->Controller->request->data = array( 'Model' => array('username' => 'nate', 'password' => 'foo', 'valid' => '0'), '_Token' => compact('key', 'fields', 'unlocked') ); $this->assertTrue($this->Controller->Security->validatePost($this->Controller)); } /** * Test that validatePost fails if you are missing the session information. * * @return void */ public function testValidatePostNoSession() { $this->Controller->Security->startup($this->Controller); $this->Controller->Session->delete('_Token'); $key = $this->Controller->params['_Token']['key']; $fields = 'a5475372b40f6e3ccbf9f8af191f20e1642fd877%3AModel.valid'; $this->Controller->data = array( 'Model' => array('username' => 'nate', 'password' => 'foo', 'valid' => '0'), '_Token' => compact('key', 'fields') ); $this->assertFalse($this->Controller->Security->validatePost($this->Controller)); } /** * test that validatePost fails if any of its required fields are missing. * * @return void */ public function testValidatePostFormHacking() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->params['_Token']['key']; $unlocked = ''; $this->Controller->request->data = array( 'Model' => array('username' => 'nate', 'password' => 'foo', 'valid' => '0'), '_Token' => compact('key', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertFalse($result, 'validatePost passed when fields were missing. %s'); } /** * Test that objects can't be passed into the serialized string. This was a vector for RFI and LFI * attacks. Thanks to Felix Wilhelm * * @return void */ public function testValidatePostObjectDeserialize() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = 'a5475372b40f6e3ccbf9f8af191f20e1642fd877'; $unlocked = ''; // a corrupted serialized object, so we can see if it ever gets to deserialize $attack = 'O:3:"App":1:{s:5:"__map";a:1:{s:3:"foo";s:7:"Hacked!";s:1:"fail"}}'; $fields .= urlencode(':' . str_rot13($attack)); $this->Controller->request->data = array( 'Model' => array('username' => 'mark', 'password' => 'foo', 'valid' => '0'), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertFalse($result, 'validatePost passed when key was missing. %s'); } /** * Tests validation of checkbox arrays * * @return void */ public function testValidatePostArray() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = '38504e4a341d4e6eadb437217efd91270e558d55%3A'; $unlocked = ''; $this->Controller->request->data = array( 'Model' => array('multi_field' => array('1', '3')), '_Token' => compact('key', 'fields', 'unlocked') ); $this->assertTrue($this->Controller->Security->validatePost($this->Controller)); } /** * testValidatePostNoModel method * * @return void */ public function testValidatePostNoModel() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = 'c5bc49a6c938c820e7e538df3d8ab7bffbc97ef9%3A'; $unlocked = ''; $this->Controller->request->data = array( 'anything' => 'some_data', '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * testValidatePostSimple method * * @return void */ public function testValidatePostSimple() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = '5415d31b4483c1e09ddb58d2a91ba9650b12aa83%3A'; $unlocked = ''; $this->Controller->request->data = array( 'Model' => array('username' => '', 'password' => ''), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * Tests hash validation for multiple records, including locked fields * * @return void */ public function testValidatePostComplex() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = 'b72a99e923687687bb5e64025d3cc65e1cecced4%3AAddresses.0.id%7CAddresses.1.id'; $unlocked = ''; $this->Controller->request->data = array( 'Addresses' => array( '0' => array( 'id' => '123456', 'title' => '', 'first_name' => '', 'last_name' => '', 'address' => '', 'city' => '', 'phone' => '', 'primary' => '' ), '1' => array( 'id' => '654321', 'title' => '', 'first_name' => '', 'last_name' => '', 'address' => '', 'city' => '', 'phone' => '', 'primary' => '' ) ), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * test ValidatePost with multiple select elements. * * @return void */ public function testValidatePostMultipleSelect() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = '8a764bdb989132c1d46f9a45f64ce2da5f9eebb9%3A'; $unlocked = ''; $this->Controller->request->data = array( 'Tag' => array('Tag' => array(1, 2)), '_Token' => compact('key', 'fields', 'unlocked'), ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); $this->Controller->request->data = array( 'Tag' => array('Tag' => array(1, 2, 3)), '_Token' => compact('key', 'fields', 'unlocked'), ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); $this->Controller->request->data = array( 'Tag' => array('Tag' => array(1, 2, 3, 4)), '_Token' => compact('key', 'fields', 'unlocked'), ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); $fields = '722de3615e63fdff899e86e85e6498b11c50bb66%3A'; $this->Controller->request->data = array( 'User.password' => 'bar', 'User.name' => 'foo', 'User.is_valid' => '1', 'Tag' => array('Tag' => array(1)), '_Token' => compact('key', 'fields', 'unlocked'), ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * testValidatePostCheckbox method * * First block tests un-checked checkbox * Second block tests checked checkbox * * @return void */ public function testValidatePostCheckbox() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = '01c1f6dbba02ac6f21b229eab1cc666839b14303%3AModel.valid'; $unlocked = ''; $this->Controller->request->data = array( 'Model' => array('username' => '', 'password' => '', 'valid' => '0'), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); $fields = 'efbcf463a2c31e97c85d95eedc41dff9e9c6a026%3A'; $this->Controller->request->data = array( 'Model' => array('username' => '', 'password' => '', 'valid' => '0'), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); $this->Controller->request->data = array(); $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $this->Controller->request->data = array( 'Model' => array('username' => '', 'password' => '', 'valid' => '0'), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * testValidatePostHidden method * * @return void */ public function testValidatePostHidden() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = 'baaf832a714b39a0618238ac89c7065fc8ec853e%3AModel.hidden%7CModel.other_hidden'; $unlocked = ''; $this->Controller->request->data = array( 'Model' => array( 'username' => '', 'password' => '', 'hidden' => '0', 'other_hidden' => 'some hidden value' ), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * testValidatePostWithDisabledFields method * * @return void */ public function testValidatePostWithDisabledFields() { $this->Controller->Security->disabledFields = array('Model.username', 'Model.password'); $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = 'aa7f254ebd8bf2ef118bc5ca1e191d1ae96857f5%3AModel.hidden'; $unlocked = ''; $this->Controller->request->data = array( 'Model' => array( 'username' => '', 'password' => '', 'hidden' => '0' ), '_Token' => compact('fields', 'key', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * test validating post data with posted unlocked fields. * * @return void */ public function testValidatePostDisabledFieldsInData() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $unlocked = 'Model.username'; $fields = array('Model.hidden', 'Model.password'); $fields = urlencode(Security::hash( '/posts/index' . serialize($fields) . $unlocked . Configure::read('Security.salt')) ); $this->Controller->request->data = array( 'Model' => array( 'username' => 'mark', 'password' => 'sekret', 'hidden' => '0' ), '_Token' => compact('fields', 'key', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * test that missing 'unlocked' input causes failure * * @return void */ public function testValidatePostFailNoDisabled() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = array('Model.hidden', 'Model.password', 'Model.username'); $fields = urlencode(Security::hash(serialize($fields) . Configure::read('Security.salt'))); $this->Controller->request->data = array( 'Model' => array( 'username' => 'mark', 'password' => 'sekret', 'hidden' => '0' ), '_Token' => compact('fields', 'key') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertFalse($result); } /** * Test that validatePost fails when unlocked fields are changed. * * @return void */ public function testValidatePostFailDisabledFieldTampering() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $unlocked = 'Model.username'; $fields = array('Model.hidden', 'Model.password'); $fields = urlencode(Security::hash(serialize($fields) . $unlocked . Configure::read('Security.salt'))); // Tamper the values. $unlocked = 'Model.username|Model.password'; $this->Controller->request->data = array( 'Model' => array( 'username' => 'mark', 'password' => 'sekret', 'hidden' => '0' ), '_Token' => compact('fields', 'key', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertFalse($result); } /** * testValidateHiddenMultipleModel method * * @return void */ public function testValidateHiddenMultipleModel() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = '38dd8a37bbb52e67ee4eb812bf1725a6a18b989b%3AModel.valid%7CModel2.valid%7CModel3.valid'; $unlocked = ''; $this->Controller->request->data = array( 'Model' => array('username' => '', 'password' => '', 'valid' => '0'), 'Model2' => array('valid' => '0'), 'Model3' => array('valid' => '0'), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * testValidateHasManyModel method * * @return void */ public function testValidateHasManyModel() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = 'dcef68de6634c60d2e60484ad0e2faec003456e6%3AModel.0.hidden%7CModel.0.valid'; $fields .= '%7CModel.1.hidden%7CModel.1.valid'; $unlocked = ''; $this->Controller->request->data = array( 'Model' => array( array( 'username' => 'username', 'password' => 'password', 'hidden' => 'value', 'valid' => '0' ), array( 'username' => 'username', 'password' => 'password', 'hidden' => 'value', 'valid' => '0' ) ), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * testValidateHasManyRecordsPass method * * @return void */ public function testValidateHasManyRecordsPass() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = '8b6880fbbd4b69279155f899652ecffdd9b4c5a1%3AAddress.0.id%7CAddress.0.primary%7C'; $fields .= 'Address.1.id%7CAddress.1.primary'; $unlocked = ''; $this->Controller->request->data = array( 'Address' => array( 0 => array( 'id' => '123', 'title' => 'home', 'first_name' => 'Bilbo', 'last_name' => 'Baggins', 'address' => '23 Bag end way', 'city' => 'the shire', 'phone' => 'N/A', 'primary' => '1', ), 1 => array( 'id' => '124', 'title' => 'home', 'first_name' => 'Frodo', 'last_name' => 'Baggins', 'address' => '50 Bag end way', 'city' => 'the shire', 'phone' => 'N/A', 'primary' => '1' ) ), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * Test that values like Foo.0.1 * * @return void */ public function testValidateNestedNumericSets() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $unlocked = ''; $hashFields = array('TaxonomyData'); $fields = urlencode( Security::hash( '/posts/index' . serialize($hashFields) . $unlocked . Configure::read('Security.salt'), 'sha1') ); $this->Controller->request->data = array( 'TaxonomyData' => array( 1 => array(array(2)), 2 => array(array(3)) ), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * testValidateHasManyRecords method * * validatePost should fail, hidden fields have been changed. * * @return void */ public function testValidateHasManyRecordsFail() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = '7a203edb3d345bbf38fe0dccae960da8842e11d7%3AAddress.0.id%7CAddress.0.primary%7C'; $fields .= 'Address.1.id%7CAddress.1.primary'; $unlocked = ''; $this->Controller->request->data = array( 'Address' => array( 0 => array( 'id' => '123', 'title' => 'home', 'first_name' => 'Bilbo', 'last_name' => 'Baggins', 'address' => '23 Bag end way', 'city' => 'the shire', 'phone' => 'N/A', 'primary' => '5', ), 1 => array( 'id' => '124', 'title' => 'home', 'first_name' => 'Frodo', 'last_name' => 'Baggins', 'address' => '50 Bag end way', 'city' => 'the shire', 'phone' => 'N/A', 'primary' => '1' ) ), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertFalse($result); } /** * testFormDisabledFields method * * @return void */ public function testFormDisabledFields() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = '216ee717efd1a251a6d6e9efbb96005a9d09f1eb%3An%3A0%3A%7B%7D'; $unlocked = ''; $this->Controller->request->data = array( 'MyModel' => array('name' => 'some data'), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertFalse($result); $this->Controller->Security->startup($this->Controller); $this->Controller->Security->disabledFields = array('MyModel.name'); $key = $this->Controller->request->params['_Token']['key']; $this->Controller->request->data = array( 'MyModel' => array('name' => 'some data'), '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * testRadio method * * @return void */ public function testValidatePostRadio() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = '3be63770e7953c6d2119f5377a9303372040f66f%3An%3A0%3A%7B%7D'; $unlocked = ''; $this->Controller->request->data = array( '_Token' => compact('key', 'fields', 'unlocked') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertFalse($result); $this->Controller->request->data = array( '_Token' => compact('key', 'fields', 'unlocked'), 'Test' => array('test' => '') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); $this->Controller->request->data = array( '_Token' => compact('key', 'fields', 'unlocked'), 'Test' => array('test' => '1') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); $this->Controller->request->data = array( '_Token' => compact('key', 'fields', 'unlocked'), 'Test' => array('test' => '2') ); $result = $this->Controller->Security->validatePost($this->Controller); $this->assertTrue($result); } /** * test validatePost uses here() as a hash input. * * @return void */ public function testValidatePostUrlAsHashInput() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $fields = '5415d31b4483c1e09ddb58d2a91ba9650b12aa83%3A'; $unlocked = ''; $this->Controller->request->data = array( 'Model' => array('username' => '', 'password' => ''), '_Token' => compact('key', 'fields', 'unlocked') ); $this->assertTrue($this->Controller->Security->validatePost($this->Controller)); $request = $this->getMock('CakeRequest', array('here'), array('articles/edit/1', false)); $request->expects($this->at(0)) ->method('here') ->will($this->returnValue('/posts/index?page=1')); $request->expects($this->at(1)) ->method('here') ->will($this->returnValue('/posts/edit/1')); $this->Controller->Security->request = $request; $this->assertFalse($this->Controller->Security->validatePost($this->Controller)); $this->assertFalse($this->Controller->Security->validatePost($this->Controller)); } /** * test that a requestAction's controller will have the _Token appended to * the params. * * @return void * @see https://cakephp.lighthouseapp.com/projects/42648/tickets/68 */ public function testSettingTokenForRequestAction() { $this->Controller->Security->startup($this->Controller); $key = $this->Controller->request->params['_Token']['key']; $this->Controller->params['requested'] = 1; unset($this->Controller->request->params['_Token']); $this->Controller->Security->startup($this->Controller); $this->assertEquals($this->Controller->request->params['_Token']['key'], $key); } /** * test that blackhole doesn't delete the _Token session key so repeat data submissions * stay blackholed. * * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/214 * @return void */ public function testBlackHoleNotDeletingSessionInformation() { $this->Controller->Security->startup($this->Controller); $this->Controller->Security->blackHole($this->Controller, 'auth'); $this->assertTrue($this->Controller->Security->Session->check('_Token'), '_Token was deleted by blackHole %s'); } /** * test that csrf checks are skipped for request action. * * @return void */ public function testCsrfSkipRequestAction() { $_SERVER['REQUEST_METHOD'] = 'POST'; $this->Security->validatePost = false; $this->Security->csrfCheck = true; $this->Security->csrfExpires = '+10 minutes'; $this->Controller->request->params['requested'] = 1; $this->Security->startup($this->Controller); $this->assertFalse($this->Controller->failed, 'fail() was called.'); } /** * test setting * * @return void */ public function testCsrfSettings() { $this->Security->validatePost = false; $this->Security->csrfCheck = true; $this->Security->csrfExpires = '+10 minutes'; $this->Security->startup($this->Controller); $token = $this->Security->Session->read('_Token'); $this->assertEquals(1, count($token['csrfTokens']), 'Missing the csrf token.'); $this->assertEquals(strtotime('+10 minutes'), current($token['csrfTokens']), 'Token expiry does not match'); $this->assertEquals(array('key', 'unlockedFields'), array_keys($this->Controller->request->params['_Token']), 'Keys don not match'); } /** * Test setting multiple nonces, when startup() is called more than once, (ie more than one request.) * * @return void */ public function testCsrfSettingMultipleNonces() { $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(2, count($token['csrfTokens']), 'Missing the csrf token.'); foreach ($token['csrfTokens'] as $expires) { $this->assertWithinMargin($expires, $csrfExpires, 2, 'Token expiry does not match'); } } /** * test that nonces are consumed by form submits. * * @return void */ public function testCsrfNonceConsumption() { $this->Security->validatePost = false; $this->Security->csrfCheck = true; $this->Security->csrfExpires = '+10 minutes'; $this->Security->Session->write('_Token.csrfTokens', array('nonce1' => strtotime('+10 minutes'))); $this->Controller->request->params['action'] = 'index'; $this->Controller->request->data = array( '_Token' => array( 'key' => 'nonce1' ), 'Post' => array( 'title' => 'Woot' ) ); $this->Security->startup($this->Controller); $token = $this->Security->Session->read('_Token'); $this->assertFalse(isset($token['csrfTokens']['nonce1']), 'Token was not consumed'); } /** * tests that reusable CSRF-token expiry is renewed */ public function testCsrfReusableTokenRenewal() { $this->Security->validatePost = false; $this->Security->csrfCheck = true; $this->Security->csrfUseOnce = false; $csrfExpires = '+10 minutes'; $this->Security->csrfExpires = $csrfExpires; $this->Security->Session->write('_Token.csrfTokens', array('token' => strtotime('+1 minutes'))); $this->Security->startup($this->Controller); $tokens = $this->Security->Session->read('_Token.csrfTokens'); $this->assertWithinMargin($tokens['token'], strtotime($csrfExpires), 2, 'Token expiry was not renewed'); } /** * test that expired values in the csrfTokens are cleaned up. * * @return void */ public function testCsrfNonceVacuum() { $this->Security->validatePost = false; $this->Security->csrfCheck = true; $this->Security->csrfExpires = '+10 minutes'; $this->Security->Session->write('_Token.csrfTokens', array( 'valid' => strtotime('+30 minutes'), 'poof' => strtotime('-11 minutes'), 'dust' => strtotime('-20 minutes') )); $this->Security->startup($this->Controller); $tokens = $this->Security->Session->read('_Token.csrfTokens'); $this->assertEquals(2, count($tokens), 'Too many tokens left behind'); $this->assertNotEmpty('valid', $tokens, 'Valid token was removed.'); } /** * test that when the key is missing the request is blackHoled * * @return void */ public function testCsrfBlackHoleOnKeyMismatch() { $this->Security->validatePost = false; $this->Security->csrfCheck = true; $this->Security->csrfExpires = '+10 minutes'; $this->Security->Session->write('_Token.csrfTokens', array('nonce1' => strtotime('+10 minutes'))); $this->Controller->request->params['action'] = 'index'; $this->Controller->request->data = array( '_Token' => array( 'key' => 'not the right value' ), 'Post' => array( 'title' => 'Woot' ) ); $this->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed, 'fail() was not called.'); } /** * test that when the key is missing the request is blackHoled * * @return void */ public function testCsrfBlackHoleOnExpiredKey() { $this->Security->validatePost = false; $this->Security->csrfCheck = true; $this->Security->csrfExpires = '+10 minutes'; $this->Security->Session->write('_Token.csrfTokens', array('nonce1' => strtotime('-5 minutes'))); $this->Controller->request->params['action'] = 'index'; $this->Controller->request->data = array( '_Token' => array( 'key' => 'nonce1' ), 'Post' => array( 'title' => 'Woot' ) ); $this->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed, 'fail() was not called.'); } /** * test that csrfUseOnce = false works. * * @return void */ public function testCsrfNotUseOnce() { $this->Security->validatePost = false; $this->Security->csrfCheck = true; $this->Security->csrfUseOnce = false; $this->Security->csrfExpires = '+10 minutes'; // Generate one token $this->Security->startup($this->Controller); $token = $this->Security->Session->read('_Token.csrfTokens'); $this->assertEquals(1, count($token), 'Should only be one token.'); $this->Security->startup($this->Controller); $tokenTwo = $this->Security->Session->read('_Token.csrfTokens'); $this->assertEquals(1, count($tokenTwo), 'Should only be one token.'); $this->assertEquals($token, $tokenTwo, 'Tokens should not be different.'); $key = $this->Controller->request->params['_Token']['key']; $this->assertEquals(array($key), array_keys($token), '_Token.key and csrfToken do not match request will blackhole.'); } /** * ensure that longer session tokens are not consumed * * @return void */ public function testCsrfNotUseOnceValidationLeavingToken() { $this->Security->validatePost = false; $this->Security->csrfCheck = true; $this->Security->csrfUseOnce = false; $this->Security->csrfExpires = '+10 minutes'; $this->Security->Session->write('_Token.csrfTokens', array('nonce1' => strtotime('+10 minutes'))); $this->Controller->request = $this->getMock('CakeRequest', array('is')); $this->Controller->request->params['action'] = 'index'; $this->Controller->request->data = array( '_Token' => array( 'key' => 'nonce1' ), 'Post' => array( 'title' => 'Woot' ) ); $this->Security->startup($this->Controller); $token = $this->Security->Session->read('_Token'); $this->assertTrue(isset($token['csrfTokens']['nonce1']), 'Token was consumed'); } /** * Test generateToken() * * @return void */ public function testGenerateToken() { $request = $this->Controller->request; $this->Security->generateToken($request); $this->assertNotEmpty($request->params['_Token']); $this->assertTrue(isset($request->params['_Token']['unlockedFields'])); $this->assertTrue(isset($request->params['_Token']['key'])); } /** * Test the limiting of CSRF tokens. * * @return void */ public function testCsrfLimit() { $this->Security->csrfLimit = 3; $time = strtotime('+10 minutes'); $tokens = array( '1' => $time, '2' => $time, '3' => $time, '4' => $time, '5' => $time, ); $this->Security->Session->write('_Token', array('csrfTokens' => $tokens)); $this->Security->generateToken($this->Controller->request); $result = $this->Security->Session->read('_Token.csrfTokens'); $this->assertFalse(isset($result['1'])); $this->assertFalse(isset($result['2'])); $this->assertFalse(isset($result['3'])); $this->assertTrue(isset($result['4'])); $this->assertTrue(isset($result['5'])); } /** * Test unlocked actions * * @return void */ public function testUnlockedActions() { $_SERVER['REQUEST_METHOD'] = 'POST'; $this->Controller->request->data = array('data'); $this->Controller->Security->unlockedActions = 'index'; $this->Controller->Security->blackHoleCallback = null; $result = $this->Controller->Security->startup($this->Controller); $this->assertNull($result); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/Component/SessionComponentTest.php000066400000000000000000000161201265552240500273110ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Controller.Component * @since CakePHP(tm) v 1.2.0.5436 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Controller', 'Controller'); App::uses('SessionComponent', 'Controller/Component'); /** * SessionTestController class * * @package Cake.Test.Case.Controller.Component */ class SessionTestController extends Controller { /** * uses property * * @var array */ public $uses = array(); /** * sessionId method * * @return string */ public function sessionId() { return $this->Session->id(); } } /** * OrangeSessionTestController class * * @package Cake.Test.Case.Controller.Component */ class OrangeSessionTestController extends Controller { /** * uses property * * @var array */ public $uses = array(); /** * sessionId method * * @return string */ public function sessionId() { return $this->Session->id(); } } /** * SessionComponentTest class * * @package Cake.Test.Case.Controller.Component */ class SessionComponentTest extends CakeTestCase { protected static $_sessionBackup; /** * fixtures * * @var string */ public $fixtures = array('core.session'); /** * test case startup * * @return void */ public static function setupBeforeClass() { static::$_sessionBackup = Configure::read('Session'); Configure::write('Session', array( 'defaults' => 'php', 'timeout' => 100, 'cookie' => 'test' )); } /** * cleanup after test case. * * @return void */ public static function teardownAfterClass() { Configure::write('Session', static::$_sessionBackup); } /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $_SESSION = null; $this->ComponentCollection = new ComponentCollection(); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); CakeSession::destroy(); } /** * ensure that session ids don't change when request action is called. * * @return void */ public function testSessionIdConsistentAcrossRequestAction() { $Object = new Object(); $Session = new SessionComponent($this->ComponentCollection); $expected = $Session->id(); $result = $Object->requestAction('/session_test/sessionId'); $this->assertEquals($expected, $result); $result = $Object->requestAction('/orange_session_test/sessionId'); $this->assertEquals($expected, $result); } /** * testSessionValid method * * @return void */ public function testSessionValid() { $Session = new SessionComponent($this->ComponentCollection); $this->assertTrue($Session->valid()); Configure::write('Session.checkAgent', true); $Session->userAgent('rweerw'); $this->assertFalse($Session->valid()); $Session = new SessionComponent($this->ComponentCollection); $Session->time = $Session->read('Config.time') + 1; $this->assertFalse($Session->valid()); } /** * testSessionError method * * @return void */ public function testSessionError() { CakeSession::$lastError = null; $Session = new SessionComponent($this->ComponentCollection); $this->assertFalse($Session->error()); } /** * testSessionReadWrite method * * @return void */ public function testSessionReadWrite() { $Session = new SessionComponent($this->ComponentCollection); $this->assertNull($Session->read('Test')); $this->assertTrue($Session->write('Test', 'some value')); $this->assertEquals('some value', $Session->read('Test')); $Session->delete('Test'); $this->assertTrue($Session->write('Test.key.path', 'some value')); $this->assertEquals('some value', $Session->read('Test.key.path')); $this->assertEquals(array('path' => 'some value'), $Session->read('Test.key')); $this->assertTrue($Session->write('Test.key.path2', 'another value')); $this->assertEquals(array('path' => 'some value', 'path2' => 'another value'), $Session->read('Test.key')); $Session->delete('Test'); $array = array('key1' => 'val1', 'key2' => 'val2', 'key3' => 'val3'); $this->assertTrue($Session->write('Test', $array)); $this->assertEquals($Session->read('Test'), $array); $Session->delete('Test'); $this->assertTrue($Session->write(array('Test' => 'some value'))); $this->assertEquals('some value', $Session->read('Test')); $Session->delete('Test'); } /** * testSessionDelete method * * @return void */ public function testSessionDelete() { $Session = new SessionComponent($this->ComponentCollection); $this->assertFalse($Session->delete('Test')); $Session->write('Test', 'some value'); $this->assertTrue($Session->delete('Test')); } /** * testSessionCheck method * * @return void */ public function testSessionCheck() { $Session = new SessionComponent($this->ComponentCollection); $this->assertFalse($Session->check('Test')); $Session->write('Test', 'some value'); $this->assertTrue($Session->check('Test')); $Session->delete('Test'); } /** * testSessionFlash method * * @return void */ public function testSessionFlash() { $Session = new SessionComponent($this->ComponentCollection); $this->assertNull($Session->read('Message.flash')); $Session->setFlash('This is a test message'); $this->assertEquals(array('message' => 'This is a test message', 'element' => 'default', 'params' => array()), $Session->read('Message.flash')); $Session->setFlash('This is a test message', 'test', array('name' => 'Joel Moss')); $this->assertEquals(array('message' => 'This is a test message', 'element' => 'test', 'params' => array('name' => 'Joel Moss')), $Session->read('Message.flash')); $Session->setFlash('This is a test message', 'default', array(), 'myFlash'); $this->assertEquals(array('message' => 'This is a test message', 'element' => 'default', 'params' => array()), $Session->read('Message.myFlash')); $Session->setFlash('This is a test message', 'non_existing_layout'); $this->assertEquals(array('message' => 'This is a test message', 'element' => 'default', 'params' => array()), $Session->read('Message.myFlash')); $Session->delete('Message'); } /** * testSessionId method * * @return void */ public function testSessionId() { unset($_SESSION); $Session = new SessionComponent($this->ComponentCollection); CakeSession::start(); $this->assertEquals(session_id(), $Session->id()); } /** * testSessionDestroy method * * @return void */ public function testSessionDestroy() { $Session = new SessionComponent($this->ComponentCollection); $Session->write('Test', 'some value'); $this->assertEquals('some value', $Session->read('Test')); $Session->destroy('Test'); $this->assertNull($Session->read('Test')); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/ComponentCollectionTest.php000066400000000000000000000122661265552240500260260ustar00rootroot00000000000000Components = new ComponentCollection(); } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Components); } /** * test triggering callbacks on loaded helpers * * @return void */ public function testLoad() { $result = $this->Components->load('Cookie'); $this->assertInstanceOf('CookieComponent', $result); $this->assertInstanceOf('CookieComponent', $this->Components->Cookie); $result = $this->Components->loaded(); $this->assertEquals(array('Cookie'), $result, 'loaded() results are wrong.'); $this->assertTrue($this->Components->enabled('Cookie')); $result = $this->Components->load('Cookie'); $this->assertSame($result, $this->Components->Cookie); } /** * Tests loading as an alias * * @return void */ public function testLoadWithAlias() { $result = $this->Components->load('Cookie', array('className' => 'CookieAlias', 'somesetting' => true)); $this->assertInstanceOf('CookieAliasComponent', $result); $this->assertInstanceOf('CookieAliasComponent', $this->Components->Cookie); $this->assertTrue($this->Components->Cookie->settings['somesetting']); $result = $this->Components->loaded(); $this->assertEquals(array('Cookie'), $result, 'loaded() results are wrong.'); $this->assertTrue($this->Components->enabled('Cookie')); $result = $this->Components->load('Cookie'); $this->assertInstanceOf('CookieAliasComponent', $result); App::build(array('Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS))); CakePlugin::load('TestPlugin'); $result = $this->Components->load('SomeOther', array('className' => 'TestPlugin.Other')); $this->assertInstanceOf('OtherComponent', $result); $this->assertInstanceOf('OtherComponent', $this->Components->SomeOther); $result = $this->Components->loaded(); $this->assertEquals(array('Cookie', 'SomeOther'), $result, 'loaded() results are wrong.'); App::build(); CakePlugin::unload(); } /** * test load and enable = false * * @return void */ public function testLoadWithEnableFalse() { $result = $this->Components->load('Cookie', array('enabled' => false)); $this->assertInstanceOf('CookieComponent', $result); $this->assertInstanceOf('CookieComponent', $this->Components->Cookie); $this->assertFalse($this->Components->enabled('Cookie'), 'Cookie should be disabled'); } /** * test missingcomponent exception * * @expectedException MissingComponentException * @return void */ public function testLoadMissingComponent() { $this->Components->load('ThisComponentShouldAlwaysBeMissing'); } /** * test loading a plugin component. * * @return void */ public function testLoadPluginComponent() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), )); CakePlugin::load('TestPlugin'); $result = $this->Components->load('TestPlugin.Other'); $this->assertInstanceOf('OtherComponent', $result, 'Component class is wrong.'); $this->assertInstanceOf('OtherComponent', $this->Components->Other, 'Class is wrong'); App::build(); CakePlugin::unload(); } /** * test unload() * * @return void */ public function testUnload() { $this->Components->load('Cookie'); $this->Components->load('Security'); $result = $this->Components->loaded(); $this->assertEquals(array('Cookie', 'Security'), $result, 'loaded components is wrong'); $this->Components->unload('Cookie'); $this->assertFalse(isset($this->Components->Cookie)); $this->assertTrue(isset($this->Components->Security)); $result = $this->Components->loaded(); $this->assertEquals(array('Security'), $result, 'loaded components is wrong'); $result = $this->Components->enabled(); $this->assertEquals(array('Security'), $result, 'enabled components is wrong'); } /** * test getting the controller out of the collection * * @return void */ public function testGetController() { $controller = $this->getMock('Controller'); $controller->components = array('Security'); $this->Components->init($controller); $result = $this->Components->getController(); $this->assertSame($controller, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/ComponentTest.php000066400000000000000000000137301265552240500240070ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Controller * @since CakePHP(tm) v 1.2.0.5436 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Controller', 'Controller'); App::uses('Component', 'Controller'); /** * ParamTestComponent * * @package Cake.Test.Case.Controller */ class ParamTestComponent extends Component { /** * components property * * @var array */ public $components = array('Banana' => array('config' => 'value')); } /** * ComponentTestController class * * @package Cake.Test.Case.Controller */ class ComponentTestController extends Controller { /** * uses property * * @var array */ public $uses = array(); } /** * AppleComponent class * * @package Cake.Test.Case.Controller */ class AppleComponent extends Component { /** * components property * * @var array */ public $components = array('Orange'); /** * testName property * * @var mixed */ public $testName = null; /** * startup method * * @param Controller $controller * @return void */ public function startup(Controller $controller) { $this->testName = $controller->name; } } /** * OrangeComponent class * * @package Cake.Test.Case.Controller */ class OrangeComponent extends Component { /** * components property * * @var array */ public $components = array('Banana'); /** * initialize method * * @param Controller $controller * @return void */ public function initialize(Controller $controller) { $this->Controller = $controller; $this->Banana->testField = 'OrangeField'; } /** * startup method * * @param Controller $controller * @return string */ public function startup(Controller $controller) { $controller->foo = 'pass'; } } /** * BananaComponent class * * @package Cake.Test.Case.Controller */ class BananaComponent extends Component { /** * testField property * * @var string */ public $testField = 'BananaField'; /** * startup method * * @param Controller $controller * @return string */ public function startup(Controller $controller) { $controller->bar = 'fail'; } } /** * MutuallyReferencingOneComponent class * * @package Cake.Test.Case.Controller */ class MutuallyReferencingOneComponent extends Component { /** * components property * * @var array */ public $components = array('MutuallyReferencingTwo'); } /** * MutuallyReferencingTwoComponent class * * @package Cake.Test.Case.Controller */ class MutuallyReferencingTwoComponent extends Component { /** * components property * * @var array */ public $components = array('MutuallyReferencingOne'); } /** * SomethingWithEmailComponent class * * @package Cake.Test.Case.Controller */ class SomethingWithEmailComponent extends Component { /** * components property * * @var array */ public $components = array('Email'); } /** * ComponentTest class * * @package Cake.Test.Case.Controller */ class ComponentTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->_pluginPaths = App::path('plugins'); App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); } /** * test accessing inner components. * * @return void */ public function testInnerComponentConstruction() { $Collection = new ComponentCollection(); $Component = new AppleComponent($Collection); $this->assertInstanceOf('OrangeComponent', $Component->Orange, 'class is wrong'); } /** * test component loading * * @return void */ public function testNestedComponentLoading() { $Collection = new ComponentCollection(); $Apple = new AppleComponent($Collection); $this->assertInstanceOf('OrangeComponent', $Apple->Orange, 'class is wrong'); $this->assertInstanceOf('BananaComponent', $Apple->Orange->Banana, 'class is wrong'); $this->assertTrue(empty($Apple->Session)); $this->assertTrue(empty($Apple->Orange->Session)); } /** * test that component components are not enabled in the collection. * * @return void */ public function testInnerComponentsAreNotEnabled() { $Collection = new ComponentCollection(); $Apple = $Collection->load('Apple'); $this->assertInstanceOf('OrangeComponent', $Apple->Orange, 'class is wrong'); $result = $Collection->enabled(); $this->assertEquals(array('Apple'), $result, 'Too many components enabled.'); } /** * test a component being used more than once. * * @return void */ public function testMultipleComponentInitialize() { $Collection = new ComponentCollection(); $Banana = $Collection->load('Banana'); $Orange = $Collection->load('Orange'); $this->assertSame($Banana, $Orange->Banana, 'Should be references'); $Banana->testField = 'OrangeField'; $this->assertSame($Banana->testField, $Orange->Banana->testField, 'References are broken'); } /** * Test mutually referencing components. * * @return void */ public function testSomethingReferencingEmailComponent() { $Controller = new ComponentTestController(); $Controller->components = array('SomethingWithEmail'); $Controller->uses = false; $Controller->constructClasses(); $Controller->Components->trigger('initialize', array(&$Controller)); $Controller->beforeFilter(); $Controller->Components->trigger('startup', array(&$Controller)); $this->assertInstanceOf('SomethingWithEmailComponent', $Controller->SomethingWithEmail); $this->assertInstanceOf('EmailComponent', $Controller->SomethingWithEmail->Email); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/ControllerMergeVarsTest.php000066400000000000000000000142731265552240500260070ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Controller * @since CakePHP(tm) v 1.2.3 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Controller', 'Controller'); /** * Test case AppController * * @package Cake.Test.Case.Controller */ class MergeVarsAppController extends Controller { /** * components * * @var array */ public $components = array('MergeVar' => array('flag', 'otherFlag', 'redirect' => false)); /** * helpers * * @var array */ public $helpers = array('MergeVar' => array('format' => 'html', 'terse')); } /** * MergeVar Component * * @package Cake.Test.Case.Controller */ class MergeVarComponent extends Object { } /** * Additional controller for testing * * @package Cake.Test.Case.Controller */ class MergeVariablesController extends MergeVarsAppController { /** * uses * * @var arrays */ public $uses = array(); /** * parent for mergeVars * * @var string */ protected $_mergeParent = 'MergeVarsAppController'; } /** * MergeVarPlugin App Controller * * @package Cake.Test.Case.Controller */ class MergeVarPluginAppController extends MergeVarsAppController { /** * components * * @var array */ public $components = array('Auth' => array('setting' => 'val', 'otherVal')); /** * helpers * * @var array */ public $helpers = array('Js'); /** * parent for mergeVars * * @var string */ protected $_mergeParent = 'MergeVarsAppController'; } /** * MergePostsController * * @package Cake.Test.Case.Controller */ class MergePostsController extends MergeVarPluginAppController { /** * uses * * @var array */ public $uses = array(); } /** * Test Case for Controller Merging of Vars. * * @package Cake.Test.Case.Controller */ class ControllerMergeVarsTest extends CakeTestCase { /** * test that component settings are not duplicated when merging component settings * * @return void */ public function testComponentParamMergingNoDuplication() { $Controller = new MergeVariablesController(); $Controller->constructClasses(); $expected = array('MergeVar' => array('flag', 'otherFlag', 'redirect' => false)); $this->assertEquals($expected, $Controller->components, 'Duplication of settings occurred. %s'); } /** * test component merges with redeclared components * * @return void */ public function testComponentMergingWithRedeclarations() { $Controller = new MergeVariablesController(); $Controller->components['MergeVar'] = array('remote', 'redirect' => true); $Controller->constructClasses(); $expected = array('MergeVar' => array('flag', 'otherFlag', 'redirect' => true, 'remote')); $this->assertEquals($expected, $Controller->components, 'Merging of settings is wrong. %s'); } /** * test merging of helpers array, ensure no duplication occurs * * @return void */ public function testHelperSettingMergingNoDuplication() { $Controller = new MergeVariablesController(); $Controller->constructClasses(); $expected = array('MergeVar' => array('format' => 'html', 'terse')); $this->assertEquals($expected, $Controller->helpers, 'Duplication of settings occurred. %s'); } /** * Test that helpers declared in appcontroller come before those in the subclass * orderwise * * @return void */ public function testHelperOrderPrecedence() { $Controller = new MergeVariablesController(); $Controller->helpers = array('Custom', 'Foo' => array('something')); $Controller->constructClasses(); $expected = array( 'MergeVar' => array('format' => 'html', 'terse'), 'Custom' => null, 'Foo' => array('something') ); $this->assertSame($expected, $Controller->helpers, 'Order is incorrect.'); } /** * test merging of vars with plugin * * @return void */ public function testMergeVarsWithPlugin() { $Controller = new MergePostsController(); $Controller->components = array('Email' => array('ports' => 'open')); $Controller->plugin = 'MergeVarPlugin'; $Controller->constructClasses(); $expected = array( 'MergeVar' => array('flag', 'otherFlag', 'redirect' => false), 'Auth' => array('setting' => 'val', 'otherVal'), 'Email' => array('ports' => 'open') ); $this->assertEquals($expected, $Controller->components, 'Components are unexpected.'); $expected = array( 'MergeVar' => array('format' => 'html', 'terse'), 'Js' => null ); $this->assertEquals($expected, $Controller->helpers, 'Helpers are unexpected.'); $Controller = new MergePostsController(); $Controller->components = array(); $Controller->plugin = 'MergeVarPlugin'; $Controller->constructClasses(); $expected = array( 'MergeVar' => array('flag', 'otherFlag', 'redirect' => false), 'Auth' => array('setting' => 'val', 'otherVal'), ); $this->assertEquals($expected, $Controller->components, 'Components are unexpected.'); } /** * Ensure that _mergeControllerVars is not being greedy and merging with * AppController when you make an instance of Controller * * @return void */ public function testMergeVarsNotGreedy() { $Controller = new Controller(); $Controller->components = array(); $Controller->uses = array(); $Controller->constructClasses(); $this->assertFalse(isset($Controller->Session)); } /** * Ensure that $modelClass is correct even when Controller::$uses * has been iterated, eg: by a Component, or event handlers. * * @return void */ public function testMergeVarsModelClass() { $Controller = new MergeVariablescontroller(); $Controller->uses = array('Test', 'TestAlias'); $Controller->constructClasses(); $this->assertEquals($Controller->uses[0], $Controller->modelClass); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/ControllerTest.php000066400000000000000000001210161265552240500241650ustar00rootroot00000000000000 'error_msg'); /** * lastQuery property * * @var mixed */ public $lastQuery = null; /** * beforeFind method * * @param mixed $query * @return void */ public function beforeFind($query) { $this->lastQuery = $query; } /** * find method * * @param string $type * @param array $options * @return void */ public function find($type = 'first', $options = array()) { if ($type === 'popular') { $conditions = array($this->name . '.' . $this->primaryKey . ' > ' => '1'); $options = Hash::merge($options, compact('conditions')); return parent::find('all', $options); } return parent::find($type, $options); } } /** * ControllerPostsController class * * @package Cake.Test.Case.Controller */ class ControllerCommentsController extends ControllerTestAppController { protected $_mergeParent = 'ControllerTestAppController'; } /** * ControllerComment class * * @package Cake.Test.Case.Controller */ class ControllerComment extends CakeTestModel { /** * name property * * @var string */ public $name = 'Comment'; /** * useTable property * * @var string */ public $useTable = 'comments'; /** * data property * * @var array */ public $data = array('name' => 'Some Name'); /** * alias property * * @var string */ public $alias = 'ControllerComment'; } /** * ControllerAlias class * * @package Cake.Test.Case.Controller */ class ControllerAlias extends CakeTestModel { /** * alias property * * @var string */ public $alias = 'ControllerSomeAlias'; /** * useTable property * * @var string */ public $useTable = 'posts'; } /** * NameTest class * * @package Cake.Test.Case.Controller */ class NameTest extends CakeTestModel { /** * name property * @var string */ public $name = 'Name'; /** * useTable property * @var string */ public $useTable = 'comments'; /** * alias property * * @var string */ public $alias = 'Name'; } /** * TestController class * * @package Cake.Test.Case.Controller */ class TestController extends ControllerTestAppController { /** * helpers property * * @var array */ public $helpers = array('Session'); /** * components property * * @var array */ public $components = array('Security'); /** * uses property * * @var array */ public $uses = array('ControllerComment', 'ControllerAlias'); protected $_mergeParent = 'ControllerTestAppController'; /** * index method * * @param mixed $testId * @param mixed $test2Id * @return void */ public function index($testId, $testTwoId) { $this->data = array( 'testId' => $testId, 'test2Id' => $testTwoId ); } /** * view method * * @param mixed $testId * @param mixed $test2Id * @return void */ public function view($testId, $testTwoId) { $this->data = array( 'testId' => $testId, 'test2Id' => $testTwoId ); } public function returner() { return 'I am from the controller.'; } //@codingStandardsIgnoreStart protected function protected_m() { } private function private_m() { } public function _hidden() { } //@codingStandardsIgnoreEnd public function admin_add() { } } /** * TestComponent class * * @package Cake.Test.Case.Controller */ class TestComponent extends Object { /** * beforeRedirect method * * @return void */ public function beforeRedirect() { } /** * initialize method * * @return void */ public function initialize(Controller $controller) { } /** * startup method * * @return void */ public function startup(Controller $controller) { } /** * shutdown method * * @return void */ public function shutdown(Controller $controller) { } /** * beforeRender callback * * @return void */ public function beforeRender(Controller $controller) { if ($this->viewclass) { $controller->viewClass = $this->viewclass; } } } class Test2Component extends TestComponent { public $model; public function __construct(ComponentCollection $collection, $settings) { $this->controller = $collection->getController(); $this->model = $this->controller->modelClass; } public function beforeRender(Controller $controller) { return false; } } /** * AnotherTestController class * * @package Cake.Test.Case.Controller */ class AnotherTestController extends ControllerTestAppController { /** * uses property * * @var array */ public $uses = false; /** * merge parent * * @var string */ protected $_mergeParent = 'ControllerTestAppController'; } /** * ControllerTest class * * @package Cake.Test.Case.Controller */ class ControllerTest extends CakeTestCase { /** * fixtures property * * @var array */ public $fixtures = array( 'core.post', 'core.comment' ); /** * reset environment. * * @return void */ public function setUp() { parent::setUp(); App::objects('plugin', null, false); App::build(); Router::reload(); } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); CakePlugin::unload(); } /** * testLoadModel method * * @return void */ public function testLoadModel() { $request = new CakeRequest('controller_posts/index'); $response = $this->getMock('CakeResponse'); $Controller = new Controller($request, $response); $this->assertFalse(isset($Controller->ControllerPost)); $result = $Controller->loadModel('ControllerPost'); $this->assertTrue($result); $this->assertInstanceOf('ControllerPost', $Controller->ControllerPost); $this->assertContains('ControllerPost', $Controller->uses); } /** * Test loadModel() when uses = true. * * @return void */ public function testLoadModelUsesTrue() { $request = new CakeRequest('controller_posts/index'); $response = $this->getMock('CakeResponse'); $Controller = new Controller($request, $response); $Controller->uses = true; $Controller->loadModel('ControllerPost'); $this->assertInstanceOf('ControllerPost', $Controller->ControllerPost); $this->assertContains('ControllerPost', $Controller->uses); } /** * testLoadModel method from a plugin controller * * @return void */ public function testLoadModelInPlugins() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'Controller' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Controller' . DS), 'Model' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS) )); CakePlugin::load('TestPlugin'); App::uses('TestPluginAppController', 'TestPlugin.Controller'); App::uses('TestPluginController', 'TestPlugin.Controller'); $Controller = new TestPluginController(); $Controller->plugin = 'TestPlugin'; $Controller->uses = false; $this->assertFalse(isset($Controller->Comment)); $result = $Controller->loadModel('Comment'); $this->assertTrue($result); $this->assertInstanceOf('Comment', $Controller->Comment); $this->assertTrue(in_array('Comment', $Controller->uses)); ClassRegistry::flush(); unset($Controller); } /** * testConstructClasses method * * @return void */ public function testConstructClasses() { $request = new CakeRequest('controller_posts/index'); $Controller = new Controller($request); $Controller->uses = array('ControllerPost', 'ControllerComment'); $Controller->constructClasses(); $this->assertInstanceOf('ControllerPost', $Controller->ControllerPost); $this->assertInstanceOf('ControllerComment', $Controller->ControllerComment); $this->assertEquals('Comment', $Controller->ControllerComment->name); unset($Controller); App::build(array('Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS))); CakePlugin::load('TestPlugin'); $Controller = new Controller($request); $Controller->uses = array('TestPlugin.TestPluginPost'); $Controller->constructClasses(); $this->assertTrue(isset($Controller->TestPluginPost)); $this->assertInstanceOf('TestPluginPost', $Controller->TestPluginPost); } /** * testConstructClassesWithComponents method * * @return void */ public function testConstructClassesWithComponents() { $Controller = new TestPluginController(new CakeRequest(), new CakeResponse()); $Controller->uses = array('NameTest'); $Controller->components[] = 'Test2'; $Controller->constructClasses(); $this->assertEquals('NameTest', $Controller->Test2->model); $this->assertEquals('Name', $Controller->NameTest->name); $this->assertEquals('Name', $Controller->NameTest->alias); } /** * testAliasName method * * @return void */ public function testAliasName() { $request = new CakeRequest('controller_posts/index'); $Controller = new Controller($request); $Controller->uses = array('NameTest'); $Controller->constructClasses(); $this->assertEquals('Name', $Controller->NameTest->name); $this->assertEquals('Name', $Controller->NameTest->alias); unset($Controller); } /** * testFlash method * * @return void */ public function testFlash() { $request = new CakeRequest('controller_posts/index'); $request->webroot = '/'; $request->base = '/'; $Controller = new Controller($request, $this->getMock('CakeResponse', array('_sendHeader'))); $Controller->flash('this should work', '/flash'); $result = $Controller->response->body(); $expected = ' this should work

this should work

'; $result = str_replace(array("\t", "\r\n", "\n"), "", $result); $expected = str_replace(array("\t", "\r\n", "\n"), "", $expected); $this->assertEquals($expected, $result); App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); $Controller = new Controller($request); $Controller->response = $this->getMock('CakeResponse', array('_sendHeader')); $Controller->flash('this should work', '/flash', 1, 'ajax2'); $result = $Controller->response->body(); $this->assertRegExp('/Ajax!/', $result); App::build(); } /** * testControllerSet method * * @return void */ public function testControllerSet() { $request = new CakeRequest('controller_posts/index'); $Controller = new Controller($request); $Controller->set('variable_with_underscores', null); $this->assertTrue(array_key_exists('variable_with_underscores', $Controller->viewVars)); $Controller->viewVars = array(); $viewVars = array('ModelName' => array('id' => 1, 'name' => 'value')); $Controller->set($viewVars); $this->assertTrue(array_key_exists('ModelName', $Controller->viewVars)); $Controller->viewVars = array(); $Controller->set('variable_with_underscores', 'value'); $this->assertTrue(array_key_exists('variable_with_underscores', $Controller->viewVars)); $Controller->viewVars = array(); $viewVars = array('ModelName' => 'name'); $Controller->set($viewVars); $this->assertTrue(array_key_exists('ModelName', $Controller->viewVars)); $Controller->set('title', 'someTitle'); $this->assertSame($Controller->viewVars['title'], 'someTitle'); $Controller->viewVars = array(); $expected = array('ModelName' => 'name', 'ModelName2' => 'name2'); $Controller->set(array('ModelName', 'ModelName2'), array('name', 'name2')); $this->assertSame($expected, $Controller->viewVars); $Controller->viewVars = array(); $Controller->set(array(3 => 'three', 4 => 'four')); $Controller->set(array(1 => 'one', 2 => 'two')); $expected = array(3 => 'three', 4 => 'four', 1 => 'one', 2 => 'two'); $this->assertEquals($expected, $Controller->viewVars); } /** * testRender method * * @return void */ public function testRender() { App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) ), App::RESET); ClassRegistry::flush(); $request = new CakeRequest('controller_posts/index'); $request->params['action'] = 'index'; $Controller = new Controller($request, new CakeResponse()); $Controller->viewPath = 'Posts'; $result = $Controller->render('index'); $this->assertRegExp('/posts index/', (string)$result); $Controller->view = 'index'; $result = $Controller->render(); $this->assertRegExp('/posts index/', (string)$result); $result = $Controller->render('/Elements/test_element'); $this->assertRegExp('/this is the test element/', (string)$result); $Controller->view = null; $Controller = new TestController($request, new CakeResponse()); $Controller->uses = array('ControllerAlias', 'TestPlugin.ControllerComment', 'ControllerPost'); $Controller->helpers = array('Html'); $Controller->constructClasses(); $Controller->ControllerComment->validationErrors = array('title' => 'tooShort'); $expected = $Controller->ControllerComment->validationErrors; $Controller->viewPath = 'Posts'; $Controller->render('index'); $View = $Controller->View; $this->assertTrue(isset($View->validationErrors['ControllerComment'])); $this->assertEquals($expected, $View->validationErrors['ControllerComment']); $expectedModels = array( 'ControllerAlias' => array('plugin' => null, 'className' => 'ControllerAlias'), 'ControllerComment' => array('plugin' => 'TestPlugin', 'className' => 'ControllerComment'), 'ControllerPost' => array('plugin' => null, 'className' => 'ControllerPost') ); $this->assertEquals($expectedModels, $Controller->request->params['models']); ClassRegistry::flush(); App::build(); } /** * test that a component beforeRender can change the controller view class. * * @return void */ public function testComponentBeforeRenderChangingViewClass() { App::build(array( 'View' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS ) ), true); $Controller = new Controller($this->getMock('CakeRequest'), new CakeResponse()); $Controller->uses = array(); $Controller->components = array('Test'); $Controller->constructClasses(); $Controller->Test->viewclass = 'Theme'; $Controller->viewPath = 'Posts'; $Controller->theme = 'TestTheme'; $result = $Controller->render('index'); $this->assertRegExp('/default test_theme layout/', (string)$result); App::build(); } /** * test that a component beforeRender can change the controller view class. * * @return void */ public function testComponentCancelRender() { $Controller = new Controller($this->getMock('CakeRequest'), new CakeResponse()); $Controller->uses = array(); $Controller->components = array('Test2'); $Controller->constructClasses(); $result = $Controller->render('index'); $this->assertInstanceOf('CakeResponse', $result); } /** * testToBeInheritedGuardmethods method * * @return void */ public function testToBeInheritedGuardmethods() { $request = new CakeRequest('controller_posts/index'); $Controller = new Controller($request, $this->getMock('CakeResponse')); $this->assertTrue($Controller->beforeScaffold('')); $this->assertTrue($Controller->afterScaffoldSave('')); $this->assertTrue($Controller->afterScaffoldSaveError('')); $this->assertFalse($Controller->scaffoldError('')); } /** * Generates status codes for redirect test. * * @return void */ public static function statusCodeProvider() { return array( array(300, "Multiple Choices"), array(301, "Moved Permanently"), array(302, "Found"), array(303, "See Other"), array(304, "Not Modified"), array(305, "Use Proxy"), array(307, "Temporary Redirect"), array(403, "Forbidden"), ); } /** * testRedirect method * * @dataProvider statusCodeProvider * @return void */ public function testRedirectByCode($code, $msg) { $Controller = new Controller(null); $Controller->response = $this->getMock('CakeResponse', array('header', 'statusCode')); $Controller->Components = $this->getMock('ComponentCollection', array('trigger')); $Controller->response->expects($this->once())->method('statusCode') ->with($code); $Controller->response->expects($this->once())->method('header') ->with('Location', 'http://cakephp.org'); $Controller->redirect('http://cakephp.org', (int)$code, false); $this->assertFalse($Controller->autoRender); } /** * test redirecting by message * * @dataProvider statusCodeProvider * @return void */ public function testRedirectByMessage($code, $msg) { $Controller = new Controller(null); $Controller->response = $this->getMock('CakeResponse', array('header', 'statusCode')); $Controller->Components = $this->getMock('ComponentCollection', array('trigger')); $Controller->response->expects($this->once())->method('statusCode') ->with($code); $Controller->response->expects($this->once())->method('header') ->with('Location', 'http://cakephp.org'); $Controller->redirect('http://cakephp.org', $msg, false); $this->assertFalse($Controller->autoRender); } /** * test that redirect triggers methods on the components. * * @return void */ public function testRedirectTriggeringComponentsReturnNull() { $Controller = new Controller(null); $Controller->response = $this->getMock('CakeResponse', array('header', 'statusCode')); $Controller->Components = $this->getMock('ComponentCollection', array('trigger')); $Controller->Components->expects($this->once())->method('trigger') ->will($this->returnValue(null)); $Controller->response->expects($this->once())->method('statusCode') ->with(301); $Controller->response->expects($this->once())->method('header') ->with('Location', 'http://cakephp.org'); $Controller->redirect('http://cakephp.org', 301, false); } /** * test that beforeRedirect callback returning null doesn't affect things. * * @return void */ public function testRedirectBeforeRedirectModifyingParams() { $Controller = new Controller(null); $Controller->response = $this->getMock('CakeResponse', array('header', 'statusCode')); $Controller->Components = $this->getMock('ComponentCollection', array('trigger')); $Controller->Components->expects($this->once())->method('trigger') ->will($this->returnValue(array('http://book.cakephp.org'))); $Controller->response->expects($this->once())->method('statusCode') ->with(301); $Controller->response->expects($this->once())->method('header') ->with('Location', 'http://book.cakephp.org'); $Controller->redirect('http://cakephp.org', 301, false); } /** * test that beforeRedirect callback returning null doesn't affect things. * * @return void */ public function testRedirectBeforeRedirectModifyingParamsArrayReturn() { $Controller = $this->getMock('Controller', array('header', '_stop')); $Controller->response = $this->getMock('CakeResponse'); $Controller->Components = $this->getMock('ComponentCollection', array('trigger')); $return = array( array( 'url' => 'http://example.com/test/1', 'exit' => false, 'status' => 302 ), array( 'url' => 'http://example.com/test/2', ), ); $Controller->Components->expects($this->once())->method('trigger') ->will($this->returnValue($return)); $Controller->response->expects($this->once())->method('header') ->with('Location', 'http://example.com/test/2'); $Controller->response->expects($this->at(1))->method('statusCode') ->with(302); $Controller->expects($this->never())->method('_stop'); $Controller->redirect('http://cakephp.org', 301); } /** * test that beforeRedirect callback returning false in controller * * @return void */ public function testRedirectBeforeRedirectInController() { $Controller = $this->getMock('Controller', array('_stop', 'beforeRedirect')); $Controller->response = $this->getMock('CakeResponse', array('header')); $Controller->Components = $this->getMock('ComponentCollection', array('trigger')); $Controller->expects($this->once())->method('beforeRedirect') ->with('http://cakephp.org') ->will($this->returnValue(false)); $Controller->response->expects($this->never())->method('header'); $Controller->expects($this->never())->method('_stop'); $Controller->redirect('http://cakephp.org'); } /** * Test that beforeRedirect works with returning an array from the controller method. * * @return void */ public function testRedirectBeforeRedirectInControllerWithArray() { $Controller = $this->getMock('Controller', array('_stop', 'beforeRedirect')); $Controller->response = $this->getMock('CakeResponse', array('header')); $Controller->Components = $this->getMock('ComponentCollection', array('trigger')); $Controller->expects($this->once()) ->method('beforeRedirect') ->with('http://cakephp.org', null, true) ->will($this->returnValue(array( 'url' => 'http://example.org', 'status' => 302, 'exit' => true ))); $Controller->response->expects($this->at(0)) ->method('header') ->with('Location', 'http://example.org'); $Controller->expects($this->once())->method('_stop'); $Controller->redirect('http://cakephp.org'); } /** * testMergeVars method * * @return void */ public function testMergeVars() { $request = new CakeRequest('controller_posts/index'); $TestController = new TestController($request); $TestController->constructClasses(); $testVars = get_class_vars('TestController'); $appVars = get_class_vars('ControllerTestAppController'); $components = is_array($appVars['components']) ? array_merge($appVars['components'], $testVars['components']) : $testVars['components']; if (!in_array('Session', $components)) { $components[] = 'Session'; } $helpers = is_array($appVars['helpers']) ? array_merge($appVars['helpers'], $testVars['helpers']) : $testVars['helpers']; $uses = is_array($appVars['uses']) ? array_merge($appVars['uses'], $testVars['uses']) : $testVars['uses']; $this->assertEquals(0, count(array_diff_key($TestController->helpers, array_flip($helpers)))); $this->assertEquals(0, count(array_diff($TestController->uses, $uses))); $this->assertEquals(count(array_diff_assoc(Hash::normalize($TestController->components), Hash::normalize($components))), 0); $expected = array('ControllerComment', 'ControllerAlias', 'ControllerPost'); $this->assertEquals($expected, $TestController->uses, '$uses was merged incorrectly, ControllerTestAppController models should be last.'); $TestController = new AnotherTestController($request); $TestController->constructClasses(); $appVars = get_class_vars('ControllerTestAppController'); $testVars = get_class_vars('AnotherTestController'); $this->assertTrue(in_array('ControllerPost', $appVars['uses'])); $this->assertFalse($testVars['uses']); $this->assertFalse(property_exists($TestController, 'ControllerPost')); $TestController = new ControllerCommentsController($request); $TestController->constructClasses(); $appVars = get_class_vars('ControllerTestAppController'); $testVars = get_class_vars('ControllerCommentsController'); $this->assertTrue(in_array('ControllerPost', $appVars['uses'])); $this->assertEquals(array('ControllerPost'), $testVars['uses']); $this->assertTrue(isset($TestController->ControllerPost)); $this->assertTrue(isset($TestController->ControllerComment)); } /** * test that options from child classes replace those in the parent classes. * * @return void */ public function testChildComponentOptionsSupercedeParents() { $request = new CakeRequest('controller_posts/index'); $TestController = new TestController($request); $expected = array('foo'); $TestController->components = array('Cookie' => $expected); $TestController->constructClasses(); $this->assertEquals($expected, $TestController->components['Cookie']); } /** * Ensure that _mergeControllerVars is not being greedy and merging with * ControllerTestAppController when you make an instance of Controller * * @return void */ public function testMergeVarsNotGreedy() { $request = new CakeRequest('controller_posts/index'); $Controller = new Controller($request); $Controller->components = array(); $Controller->uses = array(); $Controller->constructClasses(); $this->assertFalse(isset($Controller->Session)); $this->assertFalse(isset($Controller->Flash)); } /** * testReferer method * * @return void */ public function testReferer() { $request = $this->getMock('CakeRequest'); $request->expects($this->any())->method('referer') ->with(true) ->will($this->returnValue('/posts/index')); $Controller = new Controller($request); $result = $Controller->referer(null, true); $this->assertEquals('/posts/index', $result); $Controller = new Controller($request); $request->setReturnValue('referer', '/', array(true)); $result = $Controller->referer(array('controller' => 'posts', 'action' => 'index'), true); $this->assertEquals('/posts/index', $result); $request = $this->getMock('CakeRequest'); $request->expects($this->any())->method('referer') ->with(false) ->will($this->returnValue('http://localhost/posts/index')); $Controller = new Controller($request); $result = $Controller->referer(); $this->assertEquals('http://localhost/posts/index', $result); $Controller = new Controller(null); $result = $Controller->referer(); $this->assertEquals('/', $result); } /** * Test that the referer is not absolute if it is '/'. * * This avoids the base path being applied twice on string urls. * * @return void */ public function testRefererSlash() { $request = $this->getMock('CakeRequest', array('referer')); $request->base = '/base'; $request->expects($this->any()) ->method('referer') ->will($this->returnValue('/')); Router::setRequestInfo($request); $controller = new Controller($request); $result = $controller->referer('/', true); $this->assertEquals('/', $result); $controller = new Controller($request); $result = $controller->referer('/some/path', true); $this->assertEquals('/base/some/path', $result); } /** * testSetAction method * * @return void */ public function testSetAction() { $request = new CakeRequest('controller_posts/index'); $TestController = new TestController($request); $TestController->setAction('view', 1, 2); $expected = array('testId' => 1, 'test2Id' => 2); $this->assertSame($expected, $TestController->request->data); $this->assertSame('view', $TestController->request->params['action']); $this->assertSame('view', $TestController->view); } /** * testValidateErrors method * * @return void */ public function testValidateErrors() { ClassRegistry::flush(); $request = new CakeRequest('controller_posts/index'); $TestController = new TestController($request); $TestController->constructClasses(); $this->assertFalse($TestController->validateErrors()); $this->assertEquals(0, $TestController->validate()); $TestController->ControllerComment->invalidate('some_field', 'error_message'); $TestController->ControllerComment->invalidate('some_field2', 'error_message2'); $comment = new ControllerComment($request); $comment->set('someVar', 'data'); $result = $TestController->validateErrors($comment); $expected = array('some_field' => array('error_message'), 'some_field2' => array('error_message2')); $this->assertSame($expected, $result); $this->assertEquals(2, $TestController->validate($comment)); } /** * test that validateErrors works with any old model. * * @return void */ public function testValidateErrorsOnArbitraryModels() { Configure::write('Config.language', 'eng'); $TestController = new TestController(); $Post = new ControllerPost(); $Post->validate = array('title' => 'notBlank'); $Post->set('title', ''); $result = $TestController->validateErrors($Post); $expected = array('title' => array('This field cannot be left blank')); $this->assertEquals($expected, $result); } /** * testPostConditions method * * @return void */ public function testPostConditions() { $request = new CakeRequest('controller_posts/index'); $Controller = new Controller($request); $data = array( 'Model1' => array('field1' => '23'), 'Model2' => array('field2' => 'string'), 'Model3' => array('field3' => '23'), ); $expected = array( 'Model1.field1' => '23', 'Model2.field2' => 'string', 'Model3.field3' => '23', ); $result = $Controller->postConditions($data); $this->assertSame($expected, $result); $data = array(); $Controller->data = array( 'Model1' => array('field1' => '23'), 'Model2' => array('field2' => 'string'), 'Model3' => array('field3' => '23'), ); $expected = array( 'Model1.field1' => '23', 'Model2.field2' => 'string', 'Model3.field3' => '23', ); $result = $Controller->postConditions($data); $this->assertSame($expected, $result); $data = array(); $Controller->data = array(); $result = $Controller->postConditions($data); $this->assertNull($result); $data = array(); $Controller->data = array( 'Model1' => array('field1' => '23'), 'Model2' => array('field2' => 'string'), 'Model3' => array('field3' => '23'), ); $ops = array( 'Model1.field1' => '>', 'Model2.field2' => 'LIKE', 'Model3.field3' => '<=', ); $expected = array( 'Model1.field1 >' => '23', 'Model2.field2 LIKE' => "%string%", 'Model3.field3 <=' => '23', ); $result = $Controller->postConditions($data, $ops); $this->assertSame($expected, $result); } /** * testControllerHttpCodes method * * @return void */ public function testControllerHttpCodes() { $response = $this->getMock('CakeResponse', array('httpCodes')); $Controller = new Controller(null, $response); $Controller->response->expects($this->at(0))->method('httpCodes')->with(null); $Controller->response->expects($this->at(1))->method('httpCodes')->with(100); $Controller->httpCodes(); $Controller->httpCodes(100); } /** * Tests that the startup process calls the correct functions * * @return void */ public function testStartupProcess() { $Controller = $this->getMock('Controller', array('getEventManager')); $eventManager = $this->getMock('CakeEventManager'); $eventManager->expects($this->at(0))->method('dispatch') ->with( $this->logicalAnd( $this->isInstanceOf('CakeEvent'), $this->attributeEqualTo('_name', 'Controller.initialize'), $this->attributeEqualTo('_subject', $Controller) ) ); $eventManager->expects($this->at(1))->method('dispatch') ->with( $this->logicalAnd( $this->isInstanceOf('CakeEvent'), $this->attributeEqualTo('_name', 'Controller.startup'), $this->attributeEqualTo('_subject', $Controller) ) ); $Controller->expects($this->exactly(2))->method('getEventManager') ->will($this->returnValue($eventManager)); $Controller->startupProcess(); } /** * Tests that the shutdown process calls the correct functions * * @return void */ public function testStartupProcessIndirect() { $Controller = $this->getMock('Controller', array('beforeFilter')); $Controller->components = array('MockShutdown'); $Controller->Components = $this->getMock('ComponentCollection', array('trigger')); $Controller->expects($this->once())->method('beforeFilter'); $Controller->Components->expects($this->exactly(2))->method('trigger')->with($this->isInstanceOf('CakeEvent')); $Controller->startupProcess(); } /** * Tests that the shutdown process calls the correct functions * * @return void */ public function testShutdownProcess() { $Controller = $this->getMock('Controller', array('getEventManager')); $eventManager = $this->getMock('CakeEventManager'); $eventManager->expects($this->once())->method('dispatch') ->with( $this->logicalAnd( $this->isInstanceOf('CakeEvent'), $this->attributeEqualTo('_name', 'Controller.shutdown'), $this->attributeEqualTo('_subject', $Controller) ) ); $Controller->expects($this->once())->method('getEventManager') ->will($this->returnValue($eventManager)); $Controller->shutdownProcess(); } /** * Tests that the shutdown process calls the correct functions * * @return void */ public function testShutdownProcessIndirect() { $Controller = $this->getMock('Controller', array('afterFilter')); $Controller->components = array('MockShutdown'); $Controller->Components = $this->getMock('ComponentCollection', array('trigger')); $Controller->expects($this->once())->method('afterFilter'); $Controller->Components->expects($this->exactly(1))->method('trigger')->with($this->isInstanceOf('CakeEvent')); $Controller->shutdownProcess(); } /** * test that BC works for attributes on the request object. * * @return void */ public function testPropertyBackwardsCompatibility() { $request = new CakeRequest('posts/index', false); $request->addParams(array('controller' => 'posts', 'action' => 'index')); $request->data = array('Post' => array('id' => 1)); $request->here = '/posts/index'; $request->webroot = '/'; $Controller = new TestController($request); $this->assertEquals($request->data, $Controller->data); $this->assertEquals($request->webroot, $Controller->webroot); $this->assertEquals($request->here, $Controller->here); $this->assertEquals($request->action, $Controller->action); $this->assertFalse(empty($Controller->data)); $this->assertTrue(isset($Controller->data)); $this->assertTrue(empty($Controller->something)); $this->assertFalse(isset($Controller->something)); $this->assertEquals($request, $Controller->params); $this->assertEquals($request->params['controller'], $Controller->params['controller']); } /** * test that the BC wrapper doesn't interfere with models and components. * * @return void */ public function testPropertyCompatibilityAndModelsComponents() { $request = new CakeRequest('controller_posts/index'); $Controller = new TestController($request); $Controller->constructClasses(); $this->assertInstanceOf('SecurityComponent', $Controller->Security); $this->assertInstanceOf('ControllerComment', $Controller->ControllerComment); } /** * test that using Controller::paginate() falls back to PaginatorComponent * * @return void */ public function testPaginateBackwardsCompatibility() { $request = new CakeRequest('controller_posts/index'); $request->params['pass'] = $request->params['named'] = array(); $response = $this->getMock('CakeResponse', array('httpCodes')); $Controller = new Controller($request, $response); $Controller->uses = array('ControllerPost', 'ControllerComment'); $Controller->passedArgs[] = '1'; $Controller->params['url'] = array(); $Controller->constructClasses(); $expected = array('page' => 1, 'limit' => 20, 'maxLimit' => 100, 'paramType' => 'named'); $this->assertEquals($expected, $Controller->paginate); $results = Hash::extract($Controller->paginate('ControllerPost'), '{n}.ControllerPost.id'); $this->assertEquals(array(1, 2, 3), $results); $Controller->passedArgs = array(); $Controller->paginate = array('limit' => '1'); $this->assertEquals(array('limit' => '1'), $Controller->paginate); $Controller->paginate('ControllerPost'); $this->assertSame($Controller->params['paging']['ControllerPost']['page'], 1); $this->assertSame($Controller->params['paging']['ControllerPost']['pageCount'], 3); $this->assertFalse($Controller->params['paging']['ControllerPost']['prevPage']); $this->assertTrue($Controller->params['paging']['ControllerPost']['nextPage']); } /** * testMissingAction method * * @expectedException MissingActionException * @expectedExceptionMessage Action TestController::missing() could not be found. * @return void */ public function testInvokeActionMissingAction() { $url = new CakeRequest('test/missing'); $url->addParams(array('controller' => 'test_controller', 'action' => 'missing')); $response = $this->getMock('CakeResponse'); $Controller = new TestController($url, $response); $Controller->invokeAction($url); } /** * test invoking private methods. * * @expectedException PrivateActionException * @expectedExceptionMessage Private Action TestController::private_m() is not directly accessible. * @return void */ public function testInvokeActionPrivate() { $url = new CakeRequest('test/private_m/'); $url->addParams(array('controller' => 'test_controller', 'action' => 'private_m')); $response = $this->getMock('CakeResponse'); $Controller = new TestController($url, $response); $Controller->invokeAction($url); } /** * test invoking protected methods. * * @expectedException PrivateActionException * @expectedExceptionMessage Private Action TestController::protected_m() is not directly accessible. * @return void */ public function testInvokeActionProtected() { $url = new CakeRequest('test/protected_m/'); $url->addParams(array('controller' => 'test_controller', 'action' => 'protected_m')); $response = $this->getMock('CakeResponse'); $Controller = new TestController($url, $response); $Controller->invokeAction($url); } /** * test invoking hidden methods. * * @expectedException PrivateActionException * @expectedExceptionMessage Private Action TestController::_hidden() is not directly accessible. * @return void */ public function testInvokeActionHidden() { $url = new CakeRequest('test/_hidden/'); $url->addParams(array('controller' => 'test_controller', 'action' => '_hidden')); $response = $this->getMock('CakeResponse'); $Controller = new TestController($url, $response); $Controller->invokeAction($url); } /** * test invoking controller methods. * * @expectedException PrivateActionException * @expectedExceptionMessage Private Action TestController::redirect() is not directly accessible. * @return void */ public function testInvokeActionBaseMethods() { $url = new CakeRequest('test/redirect/'); $url->addParams(array('controller' => 'test_controller', 'action' => 'redirect')); $response = $this->getMock('CakeResponse'); $Controller = new TestController($url, $response); $Controller->invokeAction($url); } /** * test invoking controller methods. * * @expectedException PrivateActionException * @expectedExceptionMessage Private Action TestController::admin_add() is not directly accessible. * @return void */ public function testInvokeActionPrefixProtection() { Router::reload(); Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin')); $url = new CakeRequest('test/admin_add/'); $url->addParams(array('controller' => 'test_controller', 'action' => 'admin_add')); $response = $this->getMock('CakeResponse'); $Controller = new TestController($url, $response); $Controller->invokeAction($url); } /** * test invoking controller methods. * * @expectedException PrivateActionException * @expectedExceptionMessage Private Action TestController::Admin_add() is not directly accessible. * @return void */ public function testInvokeActionPrefixProtectionCasing() { Router::reload(); Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin')); $url = new CakeRequest('test/Admin_add/'); $url->addParams(array('controller' => 'test_controller', 'action' => 'Admin_add')); $response = $this->getMock('CakeResponse'); $Controller = new TestController($url, $response); $Controller->invokeAction($url); } /** * test invoking controller methods. * * @return void */ public function testInvokeActionReturnValue() { $url = new CakeRequest('test/returner/'); $url->addParams(array( 'controller' => 'test_controller', 'action' => 'returner', 'pass' => array() )); $response = $this->getMock('CakeResponse'); $Controller = new TestController($url, $response); $result = $Controller->invokeAction($url); $this->assertEquals('I am from the controller.', $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/PagesControllerTest.php000066400000000000000000000045101265552240500251440ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Controller * @since CakePHP(tm) v 1.2.0.5436 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('PagesController', 'Controller'); /** * PagesControllerTest class * * @package Cake.Test.Case.Controller */ class PagesControllerTest extends CakeTestCase { /** * testDisplay method * * @return void */ public function testDisplay() { App::build(array( 'View' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS ) )); $Pages = new PagesController(new CakeRequest(null, false), new CakeResponse()); $Pages->viewPath = 'Posts'; $Pages->display('index'); $this->assertRegExp('/posts index/', $Pages->response->body()); $this->assertEquals('index', $Pages->viewVars['page']); $Pages->viewPath = 'Themed'; $Pages->display('TestTheme', 'Posts', 'index'); $this->assertRegExp('/posts index themed view/', $Pages->response->body()); $this->assertEquals('TestTheme', $Pages->viewVars['page']); $this->assertEquals('Posts', $Pages->viewVars['subpage']); } /** * Test that missing view renders 404 page in production * * @expectedException NotFoundException * @expectedExceptionCode 404 * @return void */ public function testMissingView() { Configure::write('debug', 0); $Pages = new PagesController(new CakeRequest(null, false), new CakeResponse()); $Pages->display('non_existing_page'); } /** * Test that missing view in debug mode renders missing_view error page * * @expectedException MissingViewException * @expectedExceptionCode 500 * @return void */ public function testMissingViewInDebug() { Configure::write('debug', 1); $Pages = new PagesController(new CakeRequest(null, false), new CakeResponse()); $Pages->display('non_existing_page'); } } cakephp-2.8.0/lib/Cake/Test/Case/Controller/ScaffoldTest.php000066400000000000000000000251731265552240500235720ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Controller * @since CakePHP(tm) v 1.2.0.5436 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Router', 'Routing'); App::uses('Controller', 'Controller'); App::uses('Scaffold', 'Controller'); App::uses('ScaffoldView', 'View'); App::uses('AppModel', 'Model'); require_once dirname(dirname(__FILE__)) . DS . 'Model' . DS . 'models.php'; /** * ScaffoldMockController class * * @package Cake.Test.Case.Controller */ class ScaffoldMockController extends Controller { /** * scaffold property * * @var mixed */ public $scaffold; } /** * ScaffoldMockControllerWithFields class * * @package Cake.Test.Case.Controller */ class ScaffoldMockControllerWithFields extends Controller { /** * name property * * @var string */ public $name = 'ScaffoldMock'; /** * scaffold property * * @var mixed */ public $scaffold; /** * function beforeScaffold * * @param string $method Method name. * @return bool true */ public function beforeScaffold($method) { $this->set('scaffoldFields', array('title')); return true; } } /** * ScaffoldMockControllerWithError class * * @package Cake.Test.Case.Controller */ class ScaffoldMockControllerWithError extends Controller { /** * name property * * @var string */ public $name = 'ScaffoldMock'; /** * scaffold property * * @var mixed */ public $scaffold; /** * function beforeScaffold * * @param string $method Method name. * @return bool false */ public function beforeScaffold($method) { return false; } } /** * TestScaffoldMock class * * @package Cake.Test.Case.Controller */ class TestScaffoldMock extends Scaffold { /** * Overload _scaffold * * @param CakeRequest $request Request object for scaffolding * @return void */ protected function _scaffold(CakeRequest $request) { $this->_params = $request; } /** * Get Params from the Controller. * * @return unknown */ public function getParams() { return $this->_params; } } /** * Scaffold Test class * * @package Cake.Test.Case.Controller */ class ScaffoldTest extends CakeTestCase { /** * Controller property * * @var SecurityTestController */ public $Controller; /** * fixtures property * * @var array */ public $fixtures = array('core.article', 'core.user', 'core.comment', 'core.join_thing', 'core.tag'); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); Configure::write('Config.language', 'eng'); $request = new CakeRequest(null, false); $this->Controller = new ScaffoldMockController($request); $this->Controller->response = $this->getMock('CakeResponse', array('_sendHeader')); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Controller); } /** * Test the correct Generation of Scaffold Params. * This ensures that the correct action and view will be generated * * @return void */ public function testScaffoldParams() { $params = array( 'plugin' => null, 'pass' => array(), 'form' => array(), 'named' => array(), 'url' => array('url' => 'admin/scaffold_mock/edit'), 'controller' => 'scaffold_mock', 'action' => 'admin_edit', 'admin' => true, ); $this->Controller->request->base = ''; $this->Controller->request->webroot = '/'; $this->Controller->request->here = '/admin/scaffold_mock/edit'; $this->Controller->request->addParams($params); //set router. Router::setRequestInfo($this->Controller->request); $this->Controller->constructClasses(); $Scaffold = new TestScaffoldMock($this->Controller, $this->Controller->request); $result = $Scaffold->getParams(); $this->assertEquals('admin_edit', $result['action']); } /** * test that the proper names and variable values are set by Scaffold * * @return void */ public function testScaffoldVariableSetting() { $params = array( 'plugin' => null, 'pass' => array(), 'form' => array(), 'named' => array(), 'url' => array('url' => 'admin/scaffold_mock/edit'), 'controller' => 'scaffold_mock', 'action' => 'admin_edit', 'admin' => true, ); $this->Controller->request->base = ''; $this->Controller->request->webroot = '/'; $this->Controller->request->here = '/admin/scaffold_mock/edit'; $this->Controller->request->addParams($params); //set router. Router::setRequestInfo($this->Controller->request); $this->Controller->constructClasses(); $Scaffold = new TestScaffoldMock($this->Controller, $this->Controller->request); $result = $Scaffold->controller->viewVars; $this->assertEquals('Scaffold :: Admin Edit :: Scaffold Mock', $result['title_for_layout']); $this->assertEquals('Scaffold Mock', $result['singularHumanName']); $this->assertEquals('Scaffold Mock', $result['pluralHumanName']); $this->assertEquals('ScaffoldMock', $result['modelClass']); $this->assertEquals('id', $result['primaryKey']); $this->assertEquals('title', $result['displayField']); $this->assertEquals('scaffoldMock', $result['singularVar']); $this->assertEquals('scaffoldMock', $result['pluralVar']); $this->assertEquals(array('id', 'user_id', 'title', 'body', 'published', 'created', 'updated'), $result['scaffoldFields']); $this->assertArrayHasKey('plugin', $result['associations']['belongsTo']['User']); } /** * test that Scaffold overrides the view property even if its set to 'Theme' * * @return void */ public function testScaffoldChangingViewProperty() { $this->Controller->action = 'edit'; $this->Controller->theme = 'TestTheme'; $this->Controller->viewClass = 'Theme'; $this->Controller->constructClasses(); new TestScaffoldMock($this->Controller, $this->Controller->request); $this->assertEquals('Scaffold', $this->Controller->viewClass); } /** * test that scaffold outputs flash messages when sessions are unset. * * @return void */ public function testScaffoldFlashMessages() { $params = array( 'plugin' => null, 'pass' => array(1), 'form' => array(), 'named' => array(), 'url' => array('url' => 'scaffold_mock'), 'controller' => 'scaffold_mock', 'action' => 'edit', ); $this->Controller->request->base = ''; $this->Controller->request->webroot = '/'; $this->Controller->request->here = '/scaffold_mock/edit'; $this->Controller->request->addParams($params); //set router. Router::reload(); Router::setRequestInfo($this->Controller->request); $this->Controller->request->data = array( 'ScaffoldMock' => array( 'id' => 1, 'title' => 'New title', 'body' => 'new body' ) ); $this->Controller->constructClasses(); unset($this->Controller->Session); ob_start(); new Scaffold($this->Controller, $this->Controller->request); $this->Controller->response->send(); $result = ob_get_clean(); $this->assertRegExp('/Scaffold Mock has been updated/', $result); } /** * test that habtm relationship keys get added to scaffoldFields. * * @return void */ public function testHabtmFieldAdditionWithScaffoldForm() { CakePlugin::unload(); $params = array( 'plugin' => null, 'pass' => array(1), 'form' => array(), 'named' => array(), 'url' => array('url' => 'scaffold_mock'), 'controller' => 'scaffold_mock', 'action' => 'edit', ); $this->Controller->request->base = ''; $this->Controller->request->webroot = '/'; $this->Controller->request->here = '/scaffold_mock/edit'; $this->Controller->request->addParams($params); //set router. Router::reload(); Router::setRequestInfo($this->Controller->request); $this->Controller->constructClasses(); ob_start(); $Scaffold = new Scaffold($this->Controller, $this->Controller->request); $this->Controller->response->send(); $result = ob_get_clean(); $this->assertRegExp('/name="data\[ScaffoldTag\]\[ScaffoldTag\]"/', $result); $result = $Scaffold->controller->viewVars; $this->assertEquals(array('id', 'user_id', 'title', 'body', 'published', 'created', 'updated', 'ScaffoldTag'), $result['scaffoldFields']); } /** * test that the proper names and variable values are set by Scaffold * * @return void */ public function testEditScaffoldWithScaffoldFields() { $request = new CakeRequest(null, false); $this->Controller = new ScaffoldMockControllerWithFields($request); $this->Controller->response = $this->getMock('CakeResponse', array('_sendHeader')); $params = array( 'plugin' => null, 'pass' => array(1), 'form' => array(), 'named' => array(), 'url' => array('url' => 'scaffold_mock/edit'), 'controller' => 'scaffold_mock', 'action' => 'edit', ); $this->Controller->request->base = ''; $this->Controller->request->webroot = '/'; $this->Controller->request->here = '/scaffold_mock/edit'; $this->Controller->request->addParams($params); //set router. Router::reload(); Router::setRequestInfo($this->Controller->request); $this->Controller->constructClasses(); ob_start(); new Scaffold($this->Controller, $this->Controller->request); $this->Controller->response->send(); $result = ob_get_clean(); $this->assertNotRegExp('/textarea name="data\[ScaffoldMock\]\[body\]" cols="30" rows="6" id="ScaffoldMockBody"/', $result); } /** * test in case of scaffold error * * @return void */ public function testScaffoldError() { $request = new CakeRequest(null, false); $this->Controller = new ScaffoldMockControllerWithError($request); $this->Controller->response = $this->getMock('CakeResponse', array('_sendHeader')); $params = array( 'plugin' => null, 'pass' => array(1), 'form' => array(), 'named' => array(), 'url' => array('url' => 'scaffold_mock/edit'), 'controller' => 'scaffold_mock', 'action' => 'edit', ); $this->Controller->request->base = ''; $this->Controller->request->webroot = '/'; $this->Controller->request->here = '/scaffold_mock/edit'; $this->Controller->request->addParams($params); //set router. Router::reload(); Router::setRequestInfo($this->Controller->request); $this->Controller->constructClasses(); ob_start(); new Scaffold($this->Controller, $this->Controller->request); $this->Controller->response->send(); $result = ob_get_clean(); $this->assertRegExp('/Scaffold Error/', $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Core/000077500000000000000000000000001265552240500172355ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Core/AppTest.php000066400000000000000000000611501265552240500213310ustar00rootroot00000000000000assertEquals($expected, $old); App::build(array('Model' => array('/path/to/models/'))); $new = App::path('Model'); $expected = array( '/path/to/models/', APP . 'Model' . DS ); $this->assertEquals($expected, $new); App::build(); App::build(array('Model' => array('/path/to/models/')), App::PREPEND); $new = App::path('Model'); $expected = array( '/path/to/models/', APP . 'Model' . DS ); $this->assertEquals($expected, $new); App::build(); App::build(array('Model' => array('/path/to/models/')), App::APPEND); $new = App::path('Model'); $expected = array( APP . 'Model' . DS, '/path/to/models/' ); $this->assertEquals($expected, $new); App::build(); App::build(array( 'Model' => array('/path/to/models/'), 'Controller' => array('/path/to/controllers/'), ), App::APPEND); $new = App::path('Model'); $expected = array( APP . 'Model' . DS, '/path/to/models/' ); $this->assertEquals($expected, $new); $new = App::path('Controller'); $expected = array( APP . 'Controller' . DS, '/path/to/controllers/' ); $this->assertEquals($expected, $new); App::build(); //reset defaults $defaults = App::path('Model'); $this->assertEquals($old, $defaults); } /** * tests that it is possible to set up paths using the CakePHP 1.3 notation for them (models, behaviors, controllers...) * * @return void */ public function testCompatibleBuild() { $old = App::path('models'); $expected = array( APP . 'Model' . DS ); $this->assertEquals($expected, $old); App::build(array('models' => array('/path/to/models/'))); $new = App::path('models'); $expected = array( '/path/to/models/', APP . 'Model' . DS ); $this->assertEquals($expected, $new); $this->assertEquals($expected, App::path('Model')); App::build(array('datasources' => array('/path/to/datasources/'))); $expected = array( '/path/to/datasources/', APP . 'Model' . DS . 'Datasource' . DS ); $result = App::path('datasources'); $this->assertEquals($expected, $result); $this->assertEquals($expected, App::path('Model/Datasource')); App::build(array('behaviors' => array('/path/to/behaviors/'))); $expected = array( '/path/to/behaviors/', APP . 'Model' . DS . 'Behavior' . DS ); $result = App::path('behaviors'); $this->assertEquals($expected, $result); $this->assertEquals($expected, App::path('Model/Behavior')); App::build(array('controllers' => array('/path/to/controllers/'))); $expected = array( '/path/to/controllers/', APP . 'Controller' . DS ); $result = App::path('controllers'); $this->assertEquals($expected, $result); $this->assertEquals($expected, App::path('Controller')); App::build(array('components' => array('/path/to/components/'))); $expected = array( '/path/to/components/', APP . 'Controller' . DS . 'Component' . DS ); $result = App::path('components'); $this->assertEquals($expected, $result); $this->assertEquals($expected, App::path('Controller/Component')); App::build(array('views' => array('/path/to/views/'))); $expected = array( '/path/to/views/', APP . 'View' . DS ); $result = App::path('views'); $this->assertEquals($expected, $result); $this->assertEquals($expected, App::path('View')); App::build(array('helpers' => array('/path/to/helpers/'))); $expected = array( '/path/to/helpers/', APP . 'View' . DS . 'Helper' . DS ); $result = App::path('helpers'); $this->assertEquals($expected, $result); $this->assertEquals($expected, App::path('View/Helper')); App::build(array('shells' => array('/path/to/shells/'))); $expected = array( '/path/to/shells/', APP . 'Console' . DS . 'Command' . DS ); $result = App::path('shells'); $this->assertEquals($expected, $result); $this->assertEquals($expected, App::path('Console/Command')); App::build(); //reset defaults $defaults = App::path('Model'); $this->assertEquals($old, $defaults); } /** * test package build() with App::REGISTER. * * @return void */ public function testBuildPackage() { $pluginPaths = array( '/foo/bar', APP . 'Plugin' . DS, dirname(dirname(CAKE)) . DS . 'plugins' . DS ); App::build(array( 'Plugin' => array( '/foo/bar' ) )); $result = App::path('Plugin'); $this->assertEquals($pluginPaths, $result); $paths = App::path('Service'); $this->assertEquals(array(), $paths); App::build(array( 'Service' => array( '%s' . 'Service' . DS, ), ), App::REGISTER); $expected = array( APP . 'Service' . DS, ); $result = App::path('Service'); $this->assertEquals($expected, $result); //Ensure new paths registered for other packages are not affected $result = App::path('Plugin'); $this->assertEquals($pluginPaths, $result); App::build(); $paths = App::path('Service'); $this->assertEquals(array(), $paths); } /** * test path() with a plugin. * * @return void */ public function testPathWithPlugins() { $basepath = CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS; App::build(array( 'Plugin' => array($basepath), )); CakePlugin::load('TestPlugin'); $result = App::path('Vendor', 'TestPlugin'); $this->assertEquals($basepath . 'TestPlugin' . DS . 'Vendor' . DS, $result[0]); } /** * testBuildWithReset method * * @return void */ public function testBuildWithReset() { $old = App::path('Model'); $expected = array( APP . 'Model' . DS ); $this->assertEquals($expected, $old); App::build(array('Model' => array('/path/to/models/')), App::RESET); $new = App::path('Model'); $expected = array( '/path/to/models/' ); $this->assertEquals($expected, $new); App::build(); //reset defaults $defaults = App::path('Model'); $this->assertEquals($old, $defaults); } /** * testCore method * * @return void */ public function testCore() { $model = App::core('Model'); $this->assertEquals(array(CAKE . 'Model' . DS), $model); $view = App::core('View'); $this->assertEquals(array(CAKE . 'View' . DS), $view); $controller = App::core('Controller'); $this->assertEquals(array(CAKE . 'Controller' . DS), $controller); $component = App::core('Controller/Component'); $this->assertEquals(array(CAKE . 'Controller' . DS . 'Component' . DS), str_replace('/', DS, $component)); $auth = App::core('Controller/Component/Auth'); $this->assertEquals(array(CAKE . 'Controller' . DS . 'Component' . DS . 'Auth' . DS), str_replace('/', DS, $auth)); $datasource = App::core('Model/Datasource'); $this->assertEquals(array(CAKE . 'Model' . DS . 'Datasource' . DS), str_replace('/', DS, $datasource)); } /** * testListObjects method * * @return void */ public function testListObjects() { $result = App::objects('class', CAKE . 'Routing', false); $this->assertTrue(in_array('Dispatcher', $result)); $this->assertTrue(in_array('Router', $result)); App::build(array( 'Model/Behavior' => App::core('Model/Behavior'), 'Controller' => App::core('Controller'), 'Controller/Component' => App::core('Controller/Component'), 'View' => App::core('View'), 'Model' => App::core('Model'), 'View/Helper' => App::core('View/Helper'), ), App::RESET); $result = App::objects('behavior', null, false); $this->assertTrue(in_array('TreeBehavior', $result)); $result = App::objects('Model/Behavior', null, false); $this->assertTrue(in_array('TreeBehavior', $result)); $result = App::objects('component', null, false); $this->assertTrue(in_array('AuthComponent', $result)); $result = App::objects('Controller/Component', null, false); $this->assertTrue(in_array('AuthComponent', $result)); $result = App::objects('view', null, false); $this->assertTrue(in_array('MediaView', $result)); $result = App::objects('View', null, false); $this->assertTrue(in_array('MediaView', $result)); $result = App::objects('helper', null, false); $this->assertTrue(in_array('HtmlHelper', $result)); $result = App::objects('View/Helper', null, false); $this->assertTrue(in_array('HtmlHelper', $result)); $result = App::objects('model', null, false); $this->assertTrue(in_array('AcoAction', $result)); $result = App::objects('Model', null, false); $this->assertTrue(in_array('AcoAction', $result)); $result = App::objects('file'); $this->assertFalse($result); $result = App::objects('file', 'non_existing_configure'); $expected = array(); $this->assertEquals($expected, $result); $result = App::objects('NonExistingType'); $this->assertSame(array(), $result); App::build(array( 'plugins' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Lib' . DS ) )); $result = App::objects('plugin', null, false); $this->assertTrue(in_array('Cache', $result)); $this->assertTrue(in_array('Log', $result)); App::build(); } /** * Make sure that .svn and friends are excluded from App::objects('plugin') * * @return void */ public function testListObjectsIgnoreDotDirectories() { $path = CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS; $this->skipIf(!is_writable($path), $path . ' is not writable.'); App::build(array( 'plugins' => array($path) ), App::RESET); mkdir($path . '.svn'); $result = App::objects('plugin', null, false); rmdir($path . '.svn'); $this->assertNotContains('.svn', $result); } /** * Tests listing objects within a plugin * * @return void */ public function testListObjectsInPlugin() { App::build(array( 'Model' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS), 'plugins' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); $result = App::objects('TestPlugin.model'); $this->assertTrue(in_array('TestPluginPost', $result)); $result = App::objects('TestPlugin.Model'); $this->assertTrue(in_array('TestPluginPost', $result)); $result = App::objects('TestPlugin.behavior'); $this->assertTrue(in_array('TestPluginPersisterOneBehavior', $result)); $result = App::objects('TestPlugin.Model/Behavior'); $this->assertTrue(in_array('TestPluginPersisterOneBehavior', $result)); $result = App::objects('TestPlugin.helper'); $expected = array('OtherHelperHelper', 'PluggedHelperHelper', 'TestPluginAppHelper'); $this->assertEquals($expected, $result); $result = App::objects('TestPlugin.View/Helper'); $expected = array('OtherHelperHelper', 'PluggedHelperHelper', 'TestPluginAppHelper'); $this->assertEquals($expected, $result); $result = App::objects('TestPlugin.component'); $this->assertTrue(in_array('OtherComponent', $result)); $result = App::objects('TestPlugin.Controller/Component'); $this->assertTrue(in_array('OtherComponent', $result)); $result = App::objects('TestPluginTwo.behavior'); $this->assertSame(array(), $result); $result = App::objects('TestPluginTwo.Model/Behavior'); $this->assertSame(array(), $result); $result = App::objects('model', null, false); $this->assertTrue(in_array('Comment', $result)); $this->assertTrue(in_array('Post', $result)); $result = App::objects('Model', null, false); $this->assertTrue(in_array('Comment', $result)); $this->assertTrue(in_array('Post', $result)); App::build(); } /** * test that themePath can find paths for themes. * * @return void */ public function testThemePath() { App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); $path = App::themePath('test_theme'); $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS . 'Themed' . DS . 'TestTheme' . DS; $this->assertEquals($expected, $path); $path = App::themePath('TestTheme'); $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS . 'Themed' . DS . 'TestTheme' . DS; $this->assertEquals($expected, $path); App::build(); } /** * testClassLoading method * * @return void */ public function testClassLoading() { $file = App::import('Model', 'Model', false); $this->assertTrue($file); $this->assertTrue(class_exists('Model')); $file = App::import('Controller', 'Controller', false); $this->assertTrue($file); $this->assertTrue(class_exists('Controller')); $file = App::import('Component', 'Auth', false); $this->assertTrue($file); $this->assertTrue(class_exists('AuthComponent')); $file = App::import('Shell', 'Shell', false); $this->assertTrue($file); $this->assertTrue(class_exists('Shell')); $file = App::import('Configure', 'PhpReader'); $this->assertTrue($file); $this->assertTrue(class_exists('PhpReader')); $file = App::import('Model', 'SomeRandomModelThatDoesNotExist', false); $this->assertFalse($file); $file = App::import('Model', 'AppModel', false); $this->assertTrue($file); $this->assertTrue(class_exists('AppModel')); $file = App::import('WrongType', null, true, array(), ''); $this->assertFalse($file); $file = App::import('Model', 'NonExistingPlugin.NonExistingModel', false); $this->assertFalse($file); $file = App::import('Model', array('NonExistingPlugin.NonExistingModel'), false); $this->assertFalse($file); if (!class_exists('AppController', false)) { $classes = array_flip(get_declared_classes()); $this->assertFalse(isset($classes['PagesController'])); $this->assertFalse(isset($classes['AppController'])); $file = App::import('Controller', 'Pages'); $this->assertTrue($file); $this->assertTrue(class_exists('PagesController')); $classes = array_flip(get_declared_classes()); $this->assertTrue(isset($classes['PagesController'])); $this->assertTrue(isset($classes['AppController'])); $file = App::import('Behavior', 'Containable'); $this->assertTrue($file); $this->assertTrue(class_exists('ContainableBehavior')); $file = App::import('Component', 'RequestHandler'); $this->assertTrue($file); $this->assertTrue(class_exists('RequestHandlerComponent')); $file = App::import('Helper', 'Form'); $this->assertTrue($file); $this->assertTrue(class_exists('FormHelper')); $file = App::import('Model', 'NonExistingModel'); $this->assertFalse($file); $file = App::import('Datasource', 'DboSource'); $this->assertTrue($file); $this->assertTrue(class_exists('DboSource')); } App::build(); } /** * test import() with plugins * * @return void */ public function testPluginImporting() { App::build(array( 'Lib' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Lib' . DS), 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); $result = App::import('Controller', 'TestPlugin.Tests'); $this->assertTrue($result); $this->assertTrue(class_exists('TestPluginAppController')); $this->assertTrue(class_exists('TestsController')); $result = App::import('Lib', 'TestPlugin.TestPluginLibrary'); $this->assertTrue($result); $this->assertTrue(class_exists('TestPluginLibrary')); $result = App::import('Lib', 'Library'); $this->assertTrue($result); $this->assertTrue(class_exists('Library')); $result = App::import('Helper', 'TestPlugin.OtherHelper'); $this->assertTrue($result); $this->assertTrue(class_exists('OtherHelperHelper')); $result = App::import('Helper', 'TestPlugin.TestPluginApp'); $this->assertTrue($result); $this->assertTrue(class_exists('TestPluginAppHelper')); $result = App::import('Datasource', 'TestPlugin.TestSource'); $this->assertTrue($result); $this->assertTrue(class_exists('TestSource')); App::uses('ExampleExample', 'TestPlugin.Vendor/Example'); $this->assertTrue(class_exists('ExampleExample')); App::build(); } /** * test that building helper paths actually works. * * @return void * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/410 */ public function testImportingHelpersFromAlternatePaths() { $this->assertFalse(class_exists('BananaHelper', false), 'BananaHelper exists, cannot test importing it.'); App::build(array( 'View/Helper' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS . 'Helper' . DS ) )); $this->assertFalse(class_exists('BananaHelper', false), 'BananaHelper exists, cannot test importing it.'); App::import('Helper', 'Banana'); $this->assertTrue(class_exists('BananaHelper', false), 'BananaHelper was not loaded.'); App::build(); } /** * testFileLoading method * * @return void */ public function testFileLoading() { $file = App::import('File', 'RealFile', false, array(), CAKE . 'Config' . DS . 'config.php'); $this->assertTrue($file); $file = App::import('File', 'NoFile', false, array(), CAKE . 'Config' . DS . 'cake' . DS . 'config.php'); $this->assertFalse($file); } /** * testFileLoadingWithArray method * * @return void */ public function testFileLoadingWithArray() { $type = array( 'type' => 'File', 'name' => 'SomeName', 'parent' => false, 'file' => CAKE . DS . 'Config' . DS . 'config.php' ); $file = App::import($type); $this->assertTrue($file); $type = array( 'type' => 'File', 'name' => 'NoFile', 'parent' => false, 'file' => CAKE . 'Config' . DS . 'cake' . DS . 'config.php' ); $file = App::import($type); $this->assertFalse($file); } /** * testFileLoadingReturnValue method * * @return void */ public function testFileLoadingReturnValue() { $file = App::import('File', 'Name', false, array(), CAKE . 'Config' . DS . 'config.php', true); $this->assertTrue(!empty($file)); $this->assertTrue(isset($file['Cake.version'])); $type = array( 'type' => 'File', 'name' => 'OtherName', 'parent' => false, 'file' => CAKE . 'Config' . DS . 'config.php', 'return' => true ); $file = App::import($type); $this->assertTrue(!empty($file)); $this->assertTrue(isset($file['Cake.version'])); } /** * testLoadingWithSearch method * * @return void */ public function testLoadingWithSearch() { $file = App::import('File', 'NewName', false, array(CAKE . 'Config' . DS), 'config.php'); $this->assertTrue($file); $file = App::import('File', 'AnotherNewName', false, array(CAKE), 'config.php'); $this->assertFalse($file); } /** * testLoadingWithSearchArray method * * @return void */ public function testLoadingWithSearchArray() { $type = array( 'type' => 'File', 'name' => 'RandomName', 'parent' => false, 'file' => 'config.php', 'search' => array(CAKE . 'Config' . DS) ); $file = App::import($type); $this->assertTrue($file); $type = array( 'type' => 'File', 'name' => 'AnotherRandomName', 'parent' => false, 'file' => 'config.php', 'search' => array(CAKE) ); $file = App::import($type); $this->assertFalse($file); } /** * testMultipleLoading method * * @return void */ public function testMultipleLoading() { if (class_exists('PersisterOne', false) || class_exists('PersisterTwo', false)) { $this->markTestSkipped('Cannot test loading of classes that exist.'); } App::build(array( 'Model' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS) )); $toLoad = array('PersisterOne', 'PersisterTwo'); $load = App::import('Model', $toLoad); $this->assertTrue($load); $classes = array_flip(get_declared_classes()); $this->assertTrue(isset($classes['PersisterOne'])); $this->assertTrue(isset($classes['PersisterTwo'])); $load = App::import('Model', array('PersisterOne', 'SomeNotFoundClass', 'PersisterTwo')); $this->assertFalse($load); } public function testLoadingVendor() { App::build(array( 'plugins' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'vendors' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS), ), App::RESET); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); ob_start(); $result = App::import('Vendor', 'css/TestAsset', array('ext' => 'css')); $text = ob_get_clean(); $this->assertTrue($result); $this->assertEquals('/* this is the test asset css file */', trim($text)); $result = App::import('Vendor', 'TestPlugin.sample/SamplePlugin'); $this->assertTrue($result); $this->assertTrue(class_exists('SamplePluginClassTestName')); $result = App::import('Vendor', 'sample/ConfigureTestVendorSample'); $this->assertTrue($result); $this->assertTrue(class_exists('ConfigureTestVendorSample')); ob_start(); $result = App::import('Vendor', 'SomeNameInSubfolder', array('file' => 'somename/some.name.php')); $text = ob_get_clean(); $this->assertTrue($result); $this->assertEquals('This is a file with dot in file name', $text); ob_start(); $result = App::import('Vendor', 'TestHello', array('file' => 'Test' . DS . 'hello.php')); $text = ob_get_clean(); $this->assertTrue($result); $this->assertEquals('This is the hello.php file in Test directory', $text); ob_start(); $result = App::import('Vendor', 'MyTest', array('file' => 'Test' . DS . 'MyTest.php')); $text = ob_get_clean(); $this->assertTrue($result); $this->assertEquals('This is the MyTest.php file', $text); ob_start(); $result = App::import('Vendor', 'Welcome'); $text = ob_get_clean(); $this->assertTrue($result); $this->assertEquals('This is the welcome.php file in vendors directory', $text); ob_start(); $result = App::import('Vendor', 'TestPlugin.Welcome'); $text = ob_get_clean(); $this->assertTrue($result); $this->assertEquals('This is the welcome.php file in test_plugin/vendors directory', $text); } /** * Tests that the automatic class loader will also find in "libs" folder for both * app and plugins if it does not find the class in other configured paths * * @return void */ public function testLoadClassInLibs() { App::build(array( 'libs' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Lib' . DS), 'plugins' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); $this->assertFalse(class_exists('CustomLibClass', false)); App::uses('CustomLibClass', 'TestPlugin.Custom/Package'); $this->assertTrue(class_exists('CustomLibClass')); $this->assertFalse(class_exists('TestUtilityClass', false)); App::uses('TestUtilityClass', 'Utility'); $this->assertTrue(class_exists('TestUtilityClass')); } /** * Tests that App::location() returns the defined path for a class * * @return void */ public function testClassLocation() { App::uses('MyCustomClass', 'MyPackage/Name'); $this->assertEquals('MyPackage/Name', App::location('MyCustomClass')); } /** * Test that paths() works. * * @return void */ public function testPaths() { $result = App::paths(); $this->assertArrayHasKey('Plugin', $result); $this->assertArrayHasKey('Controller', $result); $this->assertArrayHasKey('Controller/Component', $result); } /** * Proves that it is possible to load plugin libraries in top * level Lib dir for plugins * * @return void */ public function testPluginLibClasses() { App::build(array( 'plugins' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); $this->assertFalse(class_exists('TestPluginOtherLibrary', false)); App::uses('TestPluginOtherLibrary', 'TestPlugin.Lib'); $this->assertTrue(class_exists('TestPluginOtherLibrary')); } /** * Test that increaseMemoryLimit increases the maximum amount of memory actually * * @dataProvider memoryVariationProvider * @return void */ public function testIncreaseMemoryLimit($memoryLimit, $additionalKb, $expected) { $this->skipIf(!function_exists('ini_set')); $originalMemoryLimit = ini_get('memory_limit'); ini_set('memory_limit', $memoryLimit); App::increaseMemoryLimit($additionalKb); $this->assertEquals($expected, ini_get('memory_limit')); ini_set('memory_limit', $originalMemoryLimit); } /** * Data provider function for testIncreaseMemoryLimit * * @return void */ public function memoryVariationProvider() { return array( array('131072K', 100000, '231072K'), array('256M', 1, '262145K'), array('1G', 1, '1048577K'), array('-1', 100000, '-1') ); } } cakephp-2.8.0/lib/Cake/Test/Case/Core/CakePluginTest.php000066400000000000000000000230071265552240500226320ustar00rootroot00000000000000 array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); App::objects('plugins', null, false); } /** * Reverts the changes done to the environment while testing * * @return void */ public function tearDown() { parent::tearDown(); CakePlugin::unload(); } /** * Tests loading a single plugin * * @return void */ public function testLoadSingle() { CakePlugin::unload(); CakePlugin::load('TestPlugin'); $expected = array('TestPlugin'); $this->assertEquals($expected, CakePlugin::loaded()); } /** * Tests unloading plugins * * @return void */ public function testUnload() { CakePlugin::load('TestPlugin'); $expected = array('TestPlugin'); $this->assertEquals($expected, CakePlugin::loaded()); CakePlugin::unload('TestPlugin'); $this->assertEquals(array(), CakePlugin::loaded()); CakePlugin::load('TestPlugin'); $expected = array('TestPlugin'); $this->assertEquals($expected, CakePlugin::loaded()); CakePlugin::unload('TestFakePlugin'); $this->assertEquals($expected, CakePlugin::loaded()); } /** * Tests loading a plugin and its bootstrap file * * @return void */ public function testLoadSingleWithBootstrap() { CakePlugin::load('TestPlugin', array('bootstrap' => true)); $this->assertTrue(CakePlugin::loaded('TestPlugin')); $this->assertEquals('loaded plugin bootstrap', Configure::read('CakePluginTest.test_plugin.bootstrap')); } /** * Tests loading a plugin with bootstrap file and routes file * * @return void */ public function testLoadSingleWithBootstrapAndRoutes() { CakePlugin::load('TestPlugin', array('bootstrap' => true, 'routes' => true)); $this->assertTrue(CakePlugin::loaded('TestPlugin')); $this->assertEquals('loaded plugin bootstrap', Configure::read('CakePluginTest.test_plugin.bootstrap')); CakePlugin::routes(); $this->assertEquals('loaded plugin routes', Configure::read('CakePluginTest.test_plugin.routes')); } /** * Tests loading multiple plugins at once * * @return void */ public function testLoadMultiple() { CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); $expected = array('TestPlugin', 'TestPluginTwo'); $this->assertEquals($expected, CakePlugin::loaded()); } /** * Tests loading multiple plugins and their bootstrap files * * @return void */ public function testLoadMultipleWithDefaults() { CakePlugin::load(array('TestPlugin', 'TestPluginTwo'), array('bootstrap' => true, 'routes' => false)); $expected = array('TestPlugin', 'TestPluginTwo'); $this->assertEquals($expected, CakePlugin::loaded()); $this->assertEquals('loaded plugin bootstrap', Configure::read('CakePluginTest.test_plugin.bootstrap')); $this->assertEquals('loaded plugin two bootstrap', Configure::read('CakePluginTest.test_plugin_two.bootstrap')); } /** * Tests loading multiple plugins with default loading params and some overrides * * @return void */ public function testLoadMultipleWithDefaultsAndOverride() { CakePlugin::load( array('TestPlugin', 'TestPluginTwo' => array('routes' => false)), array('bootstrap' => true, 'routes' => true) ); $expected = array('TestPlugin', 'TestPluginTwo'); $this->assertEquals($expected, CakePlugin::loaded()); $this->assertEquals('loaded plugin bootstrap', Configure::read('CakePluginTest.test_plugin.bootstrap')); $this->assertEquals(null, Configure::read('CakePluginTest.test_plugin_two.bootstrap')); } /** * Tests that it is possible to load multiple bootstrap files at once * * @return void */ public function testMultipleBootstrapFiles() { CakePlugin::load('TestPlugin', array('bootstrap' => array('bootstrap', 'custom_config'))); $this->assertTrue(CakePlugin::loaded('TestPlugin')); $this->assertEquals('loaded plugin bootstrap', Configure::read('CakePluginTest.test_plugin.bootstrap')); } /** * Tests that it is possible to load plugin bootstrap by calling a callback function * * @return void */ public function testCallbackBootstrap() { CakePlugin::load('TestPlugin', array('bootstrap' => array($this, 'pluginBootstrap'))); $this->assertTrue(CakePlugin::loaded('TestPlugin')); $this->assertEquals('called plugin bootstrap callback', Configure::read('CakePluginTest.test_plugin.bootstrap')); } /** * Tests that loading a missing routes file throws a warning * * @return void * @expectedException PHPUNIT_FRAMEWORK_ERROR_WARNING */ public function testLoadMultipleWithDefaultsMissingFile() { CakePlugin::load(array('TestPlugin', 'TestPluginTwo'), array('bootstrap' => true, 'routes' => true)); CakePlugin::routes(); } /** * Test ignoring missing bootstrap/routes file * * @return void */ public function testIgnoreMissingFiles() { CakePlugin::loadAll(array(array( 'bootstrap' => true, 'routes' => true, 'ignoreMissing' => true ))); CakePlugin::routes(); } /** * Tests that CakePlugin::load() throws an exception on unknown plugin * * @return void * @expectedException MissingPluginException */ public function testLoadNotFound() { CakePlugin::load('MissingPlugin'); } /** * Tests that CakePlugin::path() returns the correct path for the loaded plugins * * @return void */ public function testPath() { CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS . 'TestPlugin' . DS; $this->assertEquals($expected, CakePlugin::path('TestPlugin')); $expected = CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS . 'TestPluginTwo' . DS; $this->assertEquals($expected, CakePlugin::path('TestPluginTwo')); } /** * Tests that CakePlugin::path() throws an exception on unknown plugin * * @return void * @expectedException MissingPluginException */ public function testPathNotFound() { CakePlugin::path('TestPlugin'); } /** * Tests that CakePlugin::loadAll() will load all plugins in the configured folder * * @return void */ public function testLoadAll() { CakePlugin::loadAll(); $expected = array('PluginJs', 'TestPlugin', 'TestPluginTwo'); $this->assertEquals($expected, CakePlugin::loaded()); } /** * Tests that CakePlugin::loadAll() will load all plugins in the configured folder with bootstrap loading * * @return void */ public function testLoadAllWithDefaults() { $defaults = array('bootstrap' => true); CakePlugin::loadAll(array($defaults)); $expected = array('PluginJs', 'TestPlugin', 'TestPluginTwo'); $this->assertEquals($expected, CakePlugin::loaded()); $this->assertEquals('loaded js plugin bootstrap', Configure::read('CakePluginTest.js_plugin.bootstrap')); $this->assertEquals('loaded plugin bootstrap', Configure::read('CakePluginTest.test_plugin.bootstrap')); $this->assertEquals('loaded plugin two bootstrap', Configure::read('CakePluginTest.test_plugin_two.bootstrap')); } /** * Tests that CakePlugin::loadAll() will load all plugins in the configured folder with defaults * and merges in global defaults. * * @return void */ public function testLoadAllWithDefaultsAndOverride() { CakePlugin::loadAll(array(array('bootstrap' => true), 'TestPlugin' => array('routes' => true))); CakePlugin::routes(); $expected = array('PluginJs', 'TestPlugin', 'TestPluginTwo'); $this->assertEquals($expected, CakePlugin::loaded()); $this->assertEquals('loaded js plugin bootstrap', Configure::read('CakePluginTest.js_plugin.bootstrap')); $this->assertEquals('loaded plugin routes', Configure::read('CakePluginTest.test_plugin.routes')); $this->assertEquals('loaded plugin bootstrap', Configure::read('CakePluginTest.test_plugin.bootstrap')); $this->assertEquals('loaded plugin two bootstrap', Configure::read('CakePluginTest.test_plugin_two.bootstrap')); } /** * Tests that CakePlugin::loadAll() will load all plugins in the configured folder with defaults * and overrides for a plugin * * @return void */ public function testLoadAllWithDefaultsAndOverrideComplex() { CakePlugin::loadAll(array(array('bootstrap' => true), 'TestPlugin' => array('routes' => true, 'bootstrap' => false))); CakePlugin::routes(); $expected = array('PluginJs', 'TestPlugin', 'TestPluginTwo'); $this->assertEquals($expected, CakePlugin::loaded()); $this->assertEquals('loaded js plugin bootstrap', Configure::read('CakePluginTest.js_plugin.bootstrap')); $this->assertEquals('loaded plugin routes', Configure::read('CakePluginTest.test_plugin.routes')); $this->assertEquals(null, Configure::read('CakePluginTest.test_plugin.bootstrap')); $this->assertEquals('loaded plugin two bootstrap', Configure::read('CakePluginTest.test_plugin_two.bootstrap')); } /** * Auxiliary function to test plugin bootstrap callbacks * * @return void */ public function pluginBootstrap() { Configure::write('CakePluginTest.test_plugin.bootstrap', 'called plugin bootstrap callback'); } } cakephp-2.8.0/lib/Cake/Test/Case/Core/ConfigureTest.php000066400000000000000000000343421265552240500225350ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Core * @since CakePHP(tm) v 1.2.0.5432 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('PhpReader', 'Configure'); /** * ConfigureTest * * @package Cake.Test.Case.Core */ class ConfigureTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); Configure::write('Cache.disable', true); App::build(); App::objects('plugin', null, true); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); if (file_exists(TMP . 'cache' . DS . 'persistent' . DS . 'cake_core_core_paths')) { unlink(TMP . 'cache' . DS . 'persistent' . DS . 'cake_core_core_paths'); } if (file_exists(TMP . 'cache' . DS . 'persistent' . DS . 'cake_core_dir_map')) { unlink(TMP . 'cache' . DS . 'persistent' . DS . 'cake_core_dir_map'); } if (file_exists(TMP . 'cache' . DS . 'persistent' . DS . 'cake_core_file_map')) { unlink(TMP . 'cache' . DS . 'persistent' . DS . 'cake_core_file_map'); } if (file_exists(TMP . 'cache' . DS . 'persistent' . DS . 'cake_core_object_map')) { unlink(TMP . 'cache' . DS . 'persistent' . DS . 'cake_core_object_map'); } if (file_exists(TMP . 'cache' . DS . 'persistent' . DS . 'test.config.php')) { unlink(TMP . 'cache' . DS . 'persistent' . DS . 'test.config.php'); } if (file_exists(TMP . 'cache' . DS . 'persistent' . DS . 'test.php')) { unlink(TMP . 'cache' . DS . 'persistent' . DS . 'test.php'); } Configure::drop('test'); } /** * Test to ensure bootrapping doesn't overwrite prior configs set under 'App' key * * @return void */ public function testBootstrap() { $expected = array( 'foo' => 'bar' ); Configure::write('App', $expected); Configure::bootstrap(true); $result = Configure::read('App'); $this->assertEquals($expected['foo'], $result['foo']); $this->assertFalse($result['base']); } /** * testRead method * * @return void */ public function testRead() { $expected = 'ok'; Configure::write('level1.level2.level3_1', $expected); Configure::write('level1.level2.level3_2', 'something_else'); $result = Configure::read('level1.level2.level3_1'); $this->assertEquals($expected, $result); $result = Configure::read('level1.level2.level3_2'); $this->assertEquals('something_else', $result); $result = Configure::read('debug'); $this->assertTrue($result >= 0); $result = Configure::read(); $this->assertTrue(is_array($result)); $this->assertTrue(isset($result['debug'])); $this->assertTrue(isset($result['level1'])); $result = Configure::read('something_I_just_made_up_now'); $this->assertEquals(null, $result, 'Missing key should return null.'); } /** * testWrite method * * @return void */ public function testWrite() { $writeResult = Configure::write('SomeName.someKey', 'myvalue'); $this->assertTrue($writeResult); $result = Configure::read('SomeName.someKey'); $this->assertEquals('myvalue', $result); $writeResult = Configure::write('SomeName.someKey', null); $this->assertTrue($writeResult); $result = Configure::read('SomeName.someKey'); $this->assertEquals(null, $result); $expected = array('One' => array('Two' => array('Three' => array('Four' => array('Five' => 'cool'))))); $writeResult = Configure::write('Key', $expected); $this->assertTrue($writeResult); $result = Configure::read('Key'); $this->assertEquals($expected, $result); $result = Configure::read('Key.One'); $this->assertEquals($expected['One'], $result); $result = Configure::read('Key.One.Two'); $this->assertEquals($expected['One']['Two'], $result); $result = Configure::read('Key.One.Two.Three.Four.Five'); $this->assertEquals('cool', $result); Configure::write('one.two.three.four', '4'); $result = Configure::read('one.two.three.four'); $this->assertEquals('4', $result); } /** * Test the consume method. * * @return void */ public function testConsume() { $this->assertNull(Configure::consume('DoesNotExist'), 'Should be null on empty value'); Configure::write('Test', array('key' => 'value', 'key2' => 'value2')); $result = Configure::consume('Test.key'); $this->assertEquals('value', $result); $result = Configure::read('Test.key2'); $this->assertEquals('value2', $result, 'Other values should remain.'); $result = Configure::consume('Test'); $expected = array('key2' => 'value2'); $this->assertEquals($expected, $result); } /** * testConsumeEmpty * * @return void */ public function testConsumeEmpty() { Configure::write('Test', array('key' => 'value', 'key2' => 'value2')); $result = Configure::consume(''); $this->assertNull($result); $result = Configure::consume(null); $this->assertNull($result); } /** * test setting display_errors with debug. * * @return void */ public function testDebugSettingDisplayErrors() { Configure::write('debug', 0); $result = ini_get('display_errors'); $this->assertEquals(0, $result); Configure::write('debug', 2); $result = ini_get('display_errors'); $this->assertEquals(1, $result); } /** * testDelete method * * @return void */ public function testDelete() { Configure::write('SomeName.someKey', 'myvalue'); $result = Configure::read('SomeName.someKey'); $this->assertEquals('myvalue', $result); Configure::delete('SomeName.someKey'); $result = Configure::read('SomeName.someKey'); $this->assertNull($result); Configure::write('SomeName', array('someKey' => 'myvalue', 'otherKey' => 'otherValue')); $result = Configure::read('SomeName.someKey'); $this->assertEquals('myvalue', $result); $result = Configure::read('SomeName.otherKey'); $this->assertEquals('otherValue', $result); Configure::delete('SomeName'); $result = Configure::read('SomeName.someKey'); $this->assertNull($result); $result = Configure::read('SomeName.otherKey'); $this->assertNull($result); } /** * testCheck method * * @return void */ public function testCheck() { Configure::write('ConfigureTestCase', 'value'); $this->assertTrue(Configure::check('ConfigureTestCase')); $this->assertFalse(Configure::check('NotExistingConfigureTestCase')); } /** * testCheckingSavedEmpty method * * @return void */ public function testCheckingSavedEmpty() { $this->assertTrue(Configure::write('ConfigureTestCase', 0)); $this->assertTrue(Configure::check('ConfigureTestCase')); $this->assertTrue(Configure::write('ConfigureTestCase', '0')); $this->assertTrue(Configure::check('ConfigureTestCase')); $this->assertTrue(Configure::write('ConfigureTestCase', false)); $this->assertTrue(Configure::check('ConfigureTestCase')); $this->assertTrue(Configure::write('ConfigureTestCase', null)); $this->assertFalse(Configure::check('ConfigureTestCase')); } /** * testCheckKeyWithSpaces method * * @return void */ public function testCheckKeyWithSpaces() { $this->assertTrue(Configure::write('Configure Test', "test")); $this->assertTrue(Configure::check('Configure Test')); Configure::delete('Configure Test'); $this->assertTrue(Configure::write('Configure Test.Test Case', "test")); $this->assertTrue(Configure::check('Configure Test.Test Case')); } /** * testCheckEmpty * * @return void */ public function testCheckEmpty() { $this->assertFalse(Configure::check('')); $this->assertFalse(Configure::check(null)); } /** * testLoad method * * @expectedException RuntimeException * @return void */ public function testLoadExceptionOnNonExistantFile() { Configure::config('test', new PhpReader()); Configure::load('non_existing_configuration_file', 'test'); } /** * test load method for default config creation * * @return void */ public function testLoadDefaultConfig() { try { Configure::load('non_existing_configuration_file'); } catch (Exception $e) { $result = Configure::configured('default'); $this->assertTrue($result); } } /** * test load with merging * * @return void */ public function testLoadWithMerge() { Configure::config('test', new PhpReader(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS)); $result = Configure::load('var_test', 'test'); $this->assertTrue($result); $this->assertEquals('value', Configure::read('Read')); $result = Configure::load('var_test2', 'test', true); $this->assertTrue($result); $this->assertEquals('value2', Configure::read('Read')); $this->assertEquals('buried2', Configure::read('Deep.Second.SecondDeepest')); $this->assertEquals('buried', Configure::read('Deep.Deeper.Deepest')); $this->assertEquals('Overwrite', Configure::read('TestAcl.classname')); $this->assertEquals('one', Configure::read('TestAcl.custom')); } /** * test loading with overwrite * * @return void */ public function testLoadNoMerge() { Configure::config('test', new PhpReader(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS)); $result = Configure::load('var_test', 'test'); $this->assertTrue($result); $this->assertEquals('value', Configure::read('Read')); $result = Configure::load('var_test2', 'test', false); $this->assertTrue($result); $this->assertEquals('value2', Configure::read('Read')); $this->assertEquals('buried2', Configure::read('Deep.Second.SecondDeepest')); $this->assertNull(Configure::read('Deep.Deeper.Deepest')); } /** * testLoad method * * @return void */ public function testLoadPlugin() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); Configure::config('test', new PhpReader()); CakePlugin::load('TestPlugin'); $result = Configure::load('TestPlugin.load', 'test'); $this->assertTrue($result); $expected = '/test_app/plugins/test_plugin/config/load.php'; $config = Configure::read('plugin_load'); $this->assertEquals($expected, $config); $result = Configure::load('TestPlugin.more.load', 'test'); $this->assertTrue($result); $expected = '/test_app/plugins/test_plugin/config/more.load.php'; $config = Configure::read('plugin_more_load'); $this->assertEquals($expected, $config); CakePlugin::unload(); } /** * testStore method * * @return void */ public function testStoreAndRestore() { Configure::write('Cache.disable', false); Configure::write('Testing', 'yummy'); $this->assertTrue(Configure::store('store_test', 'default')); Configure::delete('Testing'); $this->assertNull(Configure::read('Testing')); Configure::restore('store_test', 'default'); $this->assertEquals('yummy', Configure::read('Testing')); Cache::delete('store_test', 'default'); } /** * test that store and restore only store/restore the provided data. * * @return void */ public function testStoreAndRestoreWithData() { Configure::write('Cache.disable', false); Configure::write('testing', 'value'); Configure::store('store_test', 'default', array('store_test' => 'one')); Configure::delete('testing'); $this->assertNull(Configure::read('store_test'), 'Calling store with data shouldn\'t modify runtime.'); Configure::restore('store_test', 'default'); $this->assertEquals('one', Configure::read('store_test')); $this->assertNull(Configure::read('testing'), 'Values that were not stored are not restored.'); Cache::delete('store_test', 'default'); } /** * testVersion method * * @return void */ public function testVersion() { $result = Configure::version(); $this->assertTrue(version_compare($result, '1.2', '>=')); } /** * test adding new readers. * * @return void */ public function testReaderSetup() { $reader = new PhpReader(); Configure::config('test', $reader); $configured = Configure::configured(); $this->assertTrue(in_array('test', $configured)); $this->assertTrue(Configure::configured('test')); $this->assertFalse(Configure::configured('fake_garbage')); $this->assertTrue(Configure::drop('test')); $this->assertFalse(Configure::drop('test'), 'dropping things that do not exist should return false.'); } /** * test reader() throwing exceptions on missing interface. * * @expectedException PHPUnit_Framework_Error * @throws PHPUnit_Framework_Error * @return void */ public function testReaderExceptionOnIncorrectClass() { $reader = new StdClass(); try { Configure::config('test', $reader); } catch (Throwable $t) { throw new PHPUnit_Framework_Error($t); } } /** * Test that clear wipes all values. * * @return void */ public function testClear() { Configure::write('test', 'value'); $this->assertTrue(Configure::clear()); $this->assertNull(Configure::read('debug')); $this->assertNull(Configure::read('test')); } /** * testDumpNoAdapter * * @expectedException ConfigureException * @return void */ public function testDumpNoAdapter() { Configure::dump(TMP . 'test.php', 'does_not_exist'); } /** * test dump integrated with the PhpReader. * * @return void */ public function testDump() { Configure::config('test_reader', new PhpReader(TMP)); $result = Configure::dump('config_test.php', 'test_reader'); $this->assertTrue($result > 0); $result = file_get_contents(TMP . 'config_test.php'); $this->assertContains('assertContains('$config = ', $result); if (file_exists(TMP . 'config_test.php')) { unlink(TMP . 'config_test.php'); } } /** * Test dumping only some of the data. * * @return void */ public function testDumpPartial() { Configure::config('test_reader', new PhpReader(TMP)); $result = Configure::dump('config_test.php', 'test_reader', array('Error')); $this->assertTrue($result > 0); $result = file_get_contents(TMP . 'config_test.php'); $this->assertContains('assertContains('$config = ', $result); $this->assertContains('Error', $result); $this->assertNotContains('debug', $result); if (file_exists(TMP . 'config_test.php')) { unlink(TMP . 'config_test.php'); } } } cakephp-2.8.0/lib/Cake/Test/Case/Core/ObjectTest.php000066400000000000000000000441701265552240500220220ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Core * @since CakePHP(tm) v 1.2.0.5432 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Object', 'Core'); App::uses('Router', 'Routing'); App::uses('Controller', 'Controller'); App::uses('Model', 'Model'); /** * RequestActionPost class * * @package Cake.Test.Case.Core */ class RequestActionPost extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'posts'; } /** * RequestActionController class * * @package Cake.Test.Case.Core */ class RequestActionController extends Controller { /** * uses property * * @var array */ public $uses = array('RequestActionPost'); /** * test_request_action method * * @return void */ public function test_request_action() { return 'This is a test'; } /** * another_ra_test method * * @param mixed $id * @param mixed $other * @return void */ public function another_ra_test($id, $other) { return $id + $other; } /** * normal_request_action method * * @return string Hello World! */ public function normal_request_action() { return 'Hello World'; } /** * returns $this->here * * @return string $this->here. */ public function return_here() { return $this->here; } /** * paginate_request_action method * * @return true */ public function paginate_request_action() { $this->paginate(); return true; } /** * post pass, testing post passing * * @return array */ public function post_pass() { return $this->request->data; } /** * test param passing and parsing. * * @return array */ public function params_pass() { return $this->request; } public function param_check() { $this->autoRender = false; $content = ''; if (isset($this->request->params[0])) { $content = 'return found'; } $this->response->body($content); } } /** * TestObject class * * @package Cake.Test.Case.Core */ class TestObject extends Object { /** * firstName property * * @var string */ public $firstName = 'Joel'; /** * lastName property * * @var string */ public $lastName = 'Moss'; /** * methodCalls property * * @var array */ public $methodCalls = array(); /** * emptyMethod method * * @return void */ public function emptyMethod() { $this->methodCalls[] = 'emptyMethod'; } /** * oneParamMethod method * * @param mixed $param * @return void */ public function oneParamMethod($param) { $this->methodCalls[] = array('oneParamMethod' => array($param)); } /** * twoParamMethod method * * @param mixed $param * @param mixed $paramTwo * @return void */ public function twoParamMethod($param, $paramTwo) { $this->methodCalls[] = array('twoParamMethod' => array($param, $paramTwo)); } /** * threeParamMethod method * * @param mixed $param * @param mixed $paramTwo * @param mixed $paramThree * @return void */ public function threeParamMethod($param, $paramTwo, $paramThree) { $this->methodCalls[] = array('threeParamMethod' => array($param, $paramTwo, $paramThree)); } /** * fourParamMethod method * * @param mixed $param * @param mixed $paramTwo * @param mixed $paramThree * @param mixed $paramFour * @return void */ public function fourParamMethod($param, $paramTwo, $paramThree, $paramFour) { $this->methodCalls[] = array('fourParamMethod' => array($param, $paramTwo, $paramThree, $paramFour)); } /** * fiveParamMethod method * * @param mixed $param * @param mixed $paramTwo * @param mixed $paramThree * @param mixed $paramFour * @param mixed $paramFive * @return void */ public function fiveParamMethod($param, $paramTwo, $paramThree, $paramFour, $paramFive) { $this->methodCalls[] = array('fiveParamMethod' => array($param, $paramTwo, $paramThree, $paramFour, $paramFive)); } /** * crazyMethod method * * @param mixed $param * @param mixed $paramTwo * @param mixed $paramThree * @param mixed $paramFour * @param mixed $paramFive * @param mixed $paramSix * @param mixed $paramSeven * @return void */ public function crazyMethod($param, $paramTwo, $paramThree, $paramFour, $paramFive, $paramSix, $paramSeven = null) { $this->methodCalls[] = array('crazyMethod' => array($param, $paramTwo, $paramThree, $paramFour, $paramFive, $paramSix, $paramSeven)); } /** * methodWithOptionalParam method * * @param mixed $param * @return void */ public function methodWithOptionalParam($param = null) { $this->methodCalls[] = array('methodWithOptionalParam' => array($param)); } /** * Set properties. * * @param array $properties The $properties. * @return void */ public function set($properties = array()) { return parent::_set($properties); } } /** * ObjectTestModel class * * @package Cake.Test.Case.Core */ class ObjectTestModel extends CakeTestModel { public $useTable = false; } /** * Object Test class * * @package Cake.Test.Case.Core */ class ObjectTest extends CakeTestCase { /** * fixtures * * @var string */ public $fixtures = array('core.post', 'core.test_plugin_comment', 'core.comment'); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->object = new TestObject(); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); CakePlugin::unload(); unset($this->object); } /** * testLog method * * @return void */ public function testLog() { if (file_exists(LOGS . 'error.log')) { unlink(LOGS . 'error.log'); } $this->assertTrue($this->object->log('Test warning 1')); $this->assertTrue($this->object->log(array('Test' => 'warning 2'))); $result = file(LOGS . 'error.log'); $this->assertRegExp('/^2[0-9]{3}-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+ Error: Test warning 1$/', $result[0]); $this->assertRegExp('/^2[0-9]{3}-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+ Error: Array$/', $result[1]); $this->assertRegExp('/^\($/', $result[2]); $this->assertRegExp('/\[Test\] => warning 2$/', $result[3]); $this->assertRegExp('/^\)$/', $result[4]); unlink(LOGS . 'error.log'); $this->assertTrue($this->object->log('Test warning 1', LOG_WARNING)); $this->assertTrue($this->object->log(array('Test' => 'warning 2'), LOG_WARNING)); $result = file(LOGS . 'error.log'); $this->assertRegExp('/^2[0-9]{3}-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+ Warning: Test warning 1$/', $result[0]); $this->assertRegExp('/^2[0-9]{3}-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+ Warning: Array$/', $result[1]); $this->assertRegExp('/^\($/', $result[2]); $this->assertRegExp('/\[Test\] => warning 2$/', $result[3]); $this->assertRegExp('/^\)$/', $result[4]); unlink(LOGS . 'error.log'); } /** * testSet method * * @return void */ public function testSet() { $this->object->set('a string'); $this->assertEquals('Joel', $this->object->firstName); $this->object->set(array('firstName')); $this->assertEquals('Joel', $this->object->firstName); $this->object->set(array('firstName' => 'Ashley')); $this->assertEquals('Ashley', $this->object->firstName); $this->object->set(array('firstName' => 'Joel', 'lastName' => 'Moose')); $this->assertEquals('Joel', $this->object->firstName); $this->assertEquals('Moose', $this->object->lastName); } /** * testToString method * * @return void */ public function testToString() { $result = strtolower($this->object->toString()); $this->assertEquals('testobject', $result); } /** * testMethodDispatching method * * @return void */ public function testMethodDispatching() { $this->object->emptyMethod(); $expected = array('emptyMethod'); $this->assertSame($expected, $this->object->methodCalls); $this->object->oneParamMethod('Hello'); $expected[] = array('oneParamMethod' => array('Hello')); $this->assertSame($expected, $this->object->methodCalls); $this->object->twoParamMethod(true, false); $expected[] = array('twoParamMethod' => array(true, false)); $this->assertSame($expected, $this->object->methodCalls); $this->object->threeParamMethod(true, false, null); $expected[] = array('threeParamMethod' => array(true, false, null)); $this->assertSame($expected, $this->object->methodCalls); $this->object->crazyMethod(1, 2, 3, 4, 5, 6, 7); $expected[] = array('crazyMethod' => array(1, 2, 3, 4, 5, 6, 7)); $this->assertSame($expected, $this->object->methodCalls); $this->object = new TestObject(); $this->assertSame($this->object->methodCalls, array()); $this->object->dispatchMethod('emptyMethod'); $expected = array('emptyMethod'); $this->assertSame($expected, $this->object->methodCalls); $this->object->dispatchMethod('oneParamMethod', array('Hello')); $expected[] = array('oneParamMethod' => array('Hello')); $this->assertSame($expected, $this->object->methodCalls); $this->object->dispatchMethod('twoParamMethod', array(true, false)); $expected[] = array('twoParamMethod' => array(true, false)); $this->assertSame($expected, $this->object->methodCalls); $this->object->dispatchMethod('threeParamMethod', array(true, false, null)); $expected[] = array('threeParamMethod' => array(true, false, null)); $this->assertSame($expected, $this->object->methodCalls); $this->object->dispatchMethod('fourParamMethod', array(1, 2, 3, 4)); $expected[] = array('fourParamMethod' => array(1, 2, 3, 4)); $this->assertSame($expected, $this->object->methodCalls); $this->object->dispatchMethod('fiveParamMethod', array(1, 2, 3, 4, 5)); $expected[] = array('fiveParamMethod' => array(1, 2, 3, 4, 5)); $this->assertSame($expected, $this->object->methodCalls); $this->object->dispatchMethod('crazyMethod', array(1, 2, 3, 4, 5, 6, 7)); $expected[] = array('crazyMethod' => array(1, 2, 3, 4, 5, 6, 7)); $this->assertSame($expected, $this->object->methodCalls); $this->object->dispatchMethod('methodWithOptionalParam', array('Hello')); $expected[] = array('methodWithOptionalParam' => array("Hello")); $this->assertSame($expected, $this->object->methodCalls); $this->object->dispatchMethod('methodWithOptionalParam'); $expected[] = array('methodWithOptionalParam' => array(null)); $this->assertSame($expected, $this->object->methodCalls); } /** * testRequestAction method * * @return void */ public function testRequestAction() { App::build(array( 'Model' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS), 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS), 'Controller' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Controller' . DS) ), App::RESET); $this->assertNull(Router::getRequest(), 'request stack should be empty.'); $result = $this->object->requestAction(''); $this->assertFalse($result); $result = $this->object->requestAction('/request_action/test_request_action'); $expected = 'This is a test'; $this->assertEquals($expected, $result); $result = $this->object->requestAction( Configure::read('App.fullBaseUrl') . '/request_action/test_request_action' ); $expected = 'This is a test'; $this->assertEquals($expected, $result); $result = $this->object->requestAction('/request_action/another_ra_test/2/5'); $expected = 7; $this->assertEquals($expected, $result); $result = $this->object->requestAction('/tests_apps/index', array('return')); $expected = 'This is the TestsAppsController index view '; $this->assertEquals($expected, $result); $result = $this->object->requestAction('/tests_apps/some_method'); $expected = 5; $this->assertEquals($expected, $result); $result = $this->object->requestAction('/request_action/paginate_request_action'); $this->assertTrue($result); $result = $this->object->requestAction('/request_action/normal_request_action'); $expected = 'Hello World'; $this->assertEquals($expected, $result); $this->assertNull(Router::getRequest(), 'requests were not popped off the stack, this will break url generation'); } /** * test requestAction() and plugins. * * @return void */ public function testRequestActionPlugins() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), ), App::RESET); CakePlugin::load('TestPlugin'); Router::reload(); $result = $this->object->requestAction('/test_plugin/tests/index', array('return')); $expected = 'test plugin index'; $this->assertEquals($expected, $result); $result = $this->object->requestAction('/test_plugin/tests/index/some_param', array('return')); $expected = 'test plugin index'; $this->assertEquals($expected, $result); $result = $this->object->requestAction( array('controller' => 'tests', 'action' => 'index', 'plugin' => 'test_plugin'), array('return') ); $expected = 'test plugin index'; $this->assertEquals($expected, $result); $result = $this->object->requestAction('/test_plugin/tests/some_method'); $expected = 25; $this->assertEquals($expected, $result); $result = $this->object->requestAction( array('controller' => 'tests', 'action' => 'some_method', 'plugin' => 'test_plugin') ); $expected = 25; $this->assertEquals($expected, $result); } /** * test requestAction() with arrays. * * @return void */ public function testRequestActionArray() { App::build(array( 'Model' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS), 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS), 'Controller' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Controller' . DS), 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load(array('TestPlugin')); $result = $this->object->requestAction( array('controller' => 'request_action', 'action' => 'test_request_action') ); $expected = 'This is a test'; $this->assertEquals($expected, $result); $result = $this->object->requestAction( array('controller' => 'request_action', 'action' => 'another_ra_test'), array('pass' => array('5', '7')) ); $expected = 12; $this->assertEquals($expected, $result); $result = $this->object->requestAction( array('controller' => 'tests_apps', 'action' => 'index'), array('return') ); $expected = 'This is the TestsAppsController index view '; $this->assertEquals($expected, $result); $result = $this->object->requestAction(array('controller' => 'tests_apps', 'action' => 'some_method')); $expected = 5; $this->assertEquals($expected, $result); $result = $this->object->requestAction( array('controller' => 'request_action', 'action' => 'normal_request_action') ); $expected = 'Hello World'; $this->assertEquals($expected, $result); $result = $this->object->requestAction( array('controller' => 'request_action', 'action' => 'paginate_request_action') ); $this->assertTrue($result); $result = $this->object->requestAction( array('controller' => 'request_action', 'action' => 'paginate_request_action'), array('pass' => array(5), 'named' => array('param' => 'value')) ); $this->assertTrue($result); } /** * Test that requestAction() does not forward the 0 => return value. * * @return void */ public function testRequestActionRemoveReturnParam() { $result = $this->object->requestAction( '/request_action/param_check', array('return') ); $this->assertEquals('', $result, 'Return key was found'); } /** * Test that requestAction() is populating $this->params properly * * @return void */ public function testRequestActionParamParseAndPass() { $result = $this->object->requestAction('/request_action/params_pass'); $this->assertEquals('request_action/params_pass', $result->url); $this->assertEquals('request_action', $result['controller']); $this->assertEquals('params_pass', $result['action']); $this->assertEquals(null, $result['plugin']); $result = $this->object->requestAction('/request_action/params_pass/sort:desc/limit:5'); $expected = array('sort' => 'desc', 'limit' => 5); $this->assertEquals($expected, $result['named']); $result = $this->object->requestAction( array('controller' => 'request_action', 'action' => 'params_pass'), array('named' => array('sort' => 'desc', 'limit' => 5)) ); $this->assertEquals($expected, $result['named']); } /** * Test that requestAction handles get parameters correctly. * * @return void */ public function testRequestActionGetParameters() { $result = $this->object->requestAction( '/request_action/params_pass?get=value&limit=5' ); $this->assertEquals('value', $result->query['get']); $result = $this->object->requestAction( array('controller' => 'request_action', 'action' => 'params_pass'), array('url' => array('get' => 'value', 'limit' => 5)) ); $this->assertEquals('value', $result->query['get']); } /** * test that requestAction does not fish data out of the POST * superglobal. * * @return void */ public function testRequestActionNoPostPassing() { $_tmp = $_POST; $_POST = array('data' => array( 'item' => 'value' )); $result = $this->object->requestAction(array('controller' => 'request_action', 'action' => 'post_pass')); $this->assertEmpty($result); $result = $this->object->requestAction( array('controller' => 'request_action', 'action' => 'post_pass'), array('data' => $_POST['data']) ); $expected = $_POST['data']; $this->assertEquals($expected, $result); $result = $this->object->requestAction('/request_action/post_pass'); $expected = $_POST['data']; $this->assertEquals($expected, $result); $_POST = $_tmp; } /** * Test requestAction with post data. * * @return void */ public function testRequestActionPostWithData() { $data = array( 'Post' => array('id' => 2) ); $result = $this->object->requestAction( array('controller' => 'request_action', 'action' => 'post_pass'), array('data' => $data) ); $this->assertEquals($data, $result); $result = $this->object->requestAction( '/request_action/post_pass', array('data' => $data) ); $this->assertEquals($data, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Error/000077500000000000000000000000001265552240500174365ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Error/ErrorHandlerTest.php000066400000000000000000000234001265552240500233750ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Error * @since CakePHP(tm) v 1.2.0.5432 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('ErrorHandler', 'Error'); App::uses('Controller', 'Controller'); App::uses('Router', 'Routing'); App::uses('Debugger', 'Utility'); /** * A faulty ExceptionRenderer to test nesting. */ class FaultyExceptionRenderer extends ExceptionRenderer { /** * Dummy rendering implementation. * * @return void * @throws Exception */ public function render() { throw new Exception('Error from renderer.'); } } /** * ErrorHandlerTest class * * @package Cake.Test.Case.Error */ class ErrorHandlerTest extends CakeTestCase { protected $_restoreError = false; /** * setup create a request object to get out of router later. * * @return void */ public function setUp() { parent::setUp(); App::build(array( 'View' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS ) ), App::RESET); Router::reload(); $request = new CakeRequest(null, false); $request->base = ''; Router::setRequestInfo($request); Configure::write('debug', 2); CakeLog::disable('stdout'); CakeLog::disable('stderr'); } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); if ($this->_restoreError) { restore_error_handler(); } CakeLog::enable('stdout'); CakeLog::enable('stderr'); } /** * test error handling when debug is on, an error should be printed from Debugger. * * @return void */ public function testHandleErrorDebugOn() { set_error_handler('ErrorHandler::handleError'); $this->_restoreError = true; Debugger::getInstance()->output('html'); ob_start(); $wrong .= ''; $result = ob_get_clean(); $this->assertRegExp('/
/', $result);
		$this->assertRegExp('/Notice<\/b>/', $result);
		$this->assertRegExp('/variable:\s+wrong/', $result);
	}

/**
 * provides errors for mapping tests.
 *
 * @return void
 */
	public static function errorProvider() {
		return array(
			array(E_USER_NOTICE, 'Notice'),
			array(E_USER_WARNING, 'Warning'),
		);
	}

/**
 * test error mappings
 *
 * @dataProvider errorProvider
 * @return void
 */
	public function testErrorMapping($error, $expected) {
		set_error_handler('ErrorHandler::handleError');
		$this->_restoreError = true;

		Debugger::getInstance()->output('html');

		ob_start();
		trigger_error('Test error', $error);

		$result = ob_get_clean();
		$this->assertRegExp('/' . $expected . '<\/b>/', $result);
	}

/**
 * test error prepended by @
 *
 * @return void
 */
	public function testErrorSuppressed() {
		set_error_handler('ErrorHandler::handleError');
		$this->_restoreError = true;

		ob_start();
		//@codingStandardsIgnoreStart
		@include 'invalid.file';
		//@codingStandardsIgnoreEnd
		$result = ob_get_clean();
		$this->assertTrue(empty($result));
	}

/**
 * Test that errors go into CakeLog when debug = 0.
 *
 * @return void
 */
	public function testHandleErrorDebugOff() {
		Configure::write('debug', 0);
		Configure::write('Error.trace', false);
		if (file_exists(LOGS . 'debug.log')) {
			unlink(LOGS . 'debug.log');
		}

		set_error_handler('ErrorHandler::handleError');
		$this->_restoreError = true;

		$out .= '';

		$result = file(LOGS . 'debug.log');
		$this->assertEquals(1, count($result));
		$this->assertRegExp(
			'/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} (Notice|Debug): Notice \(8\): Undefined variable:\s+out in \[.+ line \d+\]$/',
			$result[0]
		);
		if (file_exists(LOGS . 'debug.log')) {
			unlink(LOGS . 'debug.log');
		}
	}

/**
 * Test that errors going into CakeLog include traces.
 *
 * @return void
 */
	public function testHandleErrorLoggingTrace() {
		Configure::write('debug', 0);
		Configure::write('Error.trace', true);
		if (file_exists(LOGS . 'debug.log')) {
			unlink(LOGS . 'debug.log');
		}

		set_error_handler('ErrorHandler::handleError');
		$this->_restoreError = true;

		$out .= '';

		$result = file(LOGS . 'debug.log');
		$this->assertRegExp(
			'/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} (Notice|Debug): Notice \(8\): Undefined variable:\s+out in \[.+ line \d+\]$/',
			$result[0]
		);
		$this->assertRegExp('/^Trace:/', $result[1]);
		$this->assertRegExp('/^ErrorHandlerTest\:\:testHandleErrorLoggingTrace\(\)/', $result[2]);
		if (file_exists(LOGS . 'debug.log')) {
			unlink(LOGS . 'debug.log');
		}
	}

/**
 * test handleException generating a page.
 *
 * @return void
 */
	public function testHandleException() {
		$error = new NotFoundException('Kaboom!');
		ob_start();
		ErrorHandler::handleException($error);
		$result = ob_get_clean();
		$this->assertRegExp('/Kaboom!/', $result, 'message missing.');
	}

/**
 * test handleException generating log.
 *
 * @return void
 */
	public function testHandleExceptionLog() {
		if (file_exists(LOGS . 'error.log')) {
			unlink(LOGS . 'error.log');
		}
		Configure::write('Exception.log', true);
		$error = new NotFoundException('Kaboom!');

		ob_start();
		ErrorHandler::handleException($error);
		$result = ob_get_clean();
		$this->assertRegExp('/Kaboom!/', $result, 'message missing.');

		$log = file(LOGS . 'error.log');
		$this->assertContains('[NotFoundException] Kaboom!', $log[0], 'message missing.');
		$this->assertContains('ErrorHandlerTest->testHandleExceptionLog', $log[2], 'Stack trace missing.');
	}

/**
 * test handleException generating log.
 *
 * @return void
 */
	public function testHandleExceptionLogSkipping() {
		if (file_exists(LOGS . 'error.log')) {
			unlink(LOGS . 'error.log');
		}
		Configure::write('Exception.log', true);
		Configure::write('Exception.skipLog', array('NotFoundException'));
		$notFound = new NotFoundException('Kaboom!');
		$forbidden = new ForbiddenException('Fooled you!');

		ob_start();
		ErrorHandler::handleException($notFound);
		$result = ob_get_clean();
		$this->assertRegExp('/Kaboom!/', $result, 'message missing.');

		ob_start();
		ErrorHandler::handleException($forbidden);
		$result = ob_get_clean();
		$this->assertRegExp('/Fooled you!/', $result, 'message missing.');

		$log = file(LOGS . 'error.log');
		$this->assertNotContains('[NotFoundException] Kaboom!', $log[0], 'message should not be logged.');
		$this->assertContains('[ForbiddenException] Fooled you!', $log[0], 'message missing.');
	}

/**
 * tests it is possible to load a plugin exception renderer
 *
 * @return void
 */
	public function testLoadPluginHandler() {
		App::build(array(
			'Plugin' => array(
				CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS
			)
		), App::RESET);
		CakePlugin::load('TestPlugin');
		Configure::write('Exception.renderer', 'TestPlugin.TestPluginExceptionRenderer');
		$error = new NotFoundException('Kaboom!');
		ob_start();
		ErrorHandler::handleException($error);
		$result = ob_get_clean();
		$this->assertEquals('Rendered by test plugin', $result);
		CakePlugin::unload();
	}

/**
 * test handleFatalError generating a page.
 *
 * These tests start two buffers as handleFatalError blows the outer one up.
 *
 * @return void
 */
	public function testHandleFatalErrorPage() {
		$line = __LINE__;

		ob_start();
		ob_start();
		Configure::write('debug', 1);
		ErrorHandler::handleFatalError(E_ERROR, 'Something wrong', __FILE__, $line);
		$result = ob_get_clean();
		$this->assertContains('Something wrong', $result, 'message missing.');
		$this->assertContains(__FILE__, $result, 'filename missing.');
		$this->assertContains((string)$line, $result, 'line missing.');

		ob_start();
		ob_start();
		Configure::write('debug', 0);
		ErrorHandler::handleFatalError(E_ERROR, 'Something wrong', __FILE__, $line);
		$result = ob_get_clean();
		$this->assertNotContains('Something wrong', $result, 'message must not appear.');
		$this->assertNotContains(__FILE__, $result, 'filename must not appear.');
		$this->assertContains('An Internal Error Has Occurred', $result);
	}

/**
 * test handleException generating log.
 *
 * @return void
 */
	public function testHandleFatalErrorLog() {
		if (file_exists(LOGS . 'error.log')) {
			unlink(LOGS . 'error.log');
		}

		ob_start();
		ErrorHandler::handleFatalError(E_ERROR, 'Something wrong', __FILE__, __LINE__);
		ob_clean();

		$log = file(LOGS . 'error.log');
		$this->assertContains(__FILE__, $log[0], 'missing filename');
		$this->assertContains('[FatalErrorException] Something wrong', $log[1], 'message missing.');
	}

/**
 * testExceptionRendererNestingDebug method
 *
 * @return void
 */
	public function testExceptionRendererNestingDebug() {
		Configure::write('debug', 2);
		Configure::write('Exception.renderer', 'FaultyExceptionRenderer');

		$result = false;
		try {
			ob_start();
			ob_start();
			ErrorHandler::handleFatalError(E_USER_ERROR, 'Initial error', __FILE__, __LINE__);
		} catch (Exception $e) {
			$result = $e instanceof FatalErrorException;
		}

		restore_error_handler();
		$this->assertTrue($result);
	}

/**
 * testExceptionRendererNestingProduction method
 *
 * @return void
 */
	public function testExceptionRendererNestingProduction() {
		Configure::write('debug', 0);
		Configure::write('Exception.renderer', 'FaultyExceptionRenderer');

		$result = false;
		try {
			ob_start();
			ob_start();
			ErrorHandler::handleFatalError(E_USER_ERROR, 'Initial error', __FILE__, __LINE__);
		} catch (Exception $e) {
			$result = $e instanceof InternalErrorException;
		}

		restore_error_handler();
		$this->assertTrue($result);
	}

}
cakephp-2.8.0/lib/Cake/Test/Case/Error/ExceptionRendererTest.php000066400000000000000000000621041265552240500244370ustar00rootroot00000000000000
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 * @link          http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
 * @package       Cake.Test.Case.Error
 * @since         CakePHP(tm) v 2.0
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 */

App::uses('ExceptionRenderer', 'Error');
App::uses('Controller', 'Controller');
App::uses('Component', 'Controller');
App::uses('Router', 'Routing');

/**
 * Short description for class.
 *
 * @package       Cake.Test.Case.Error
 */
class AuthBlueberryUser extends CakeTestModel {

/**
 * useTable property
 *
 * @var string
 */
	public $useTable = false;
}

/**
 * BlueberryComponent class
 *
 * @package       Cake.Test.Case.Error
 */
class BlueberryComponent extends Component {

/**
 * testName property
 *
 * @return void
 */
	public $testName = null;

/**
 * initialize method
 *
 * @return void
 */
	public function initialize(Controller $controller) {
		$this->testName = 'BlueberryComponent';
	}

}

/**
 * TestErrorController class
 *
 * @package       Cake.Test.Case.Error
 */
class TestErrorController extends Controller {

/**
 * uses property
 *
 * @var array
 */
	public $uses = array();

/**
 * components property
 *
 * @return void
 */
	public $components = array('Blueberry');

/**
 * beforeRender method
 *
 * @return void
 */
	public function beforeRender() {
		echo $this->Blueberry->testName;
	}

/**
 * index method
 *
 * @return void
 */
	public function index() {
		$this->autoRender = false;
		return 'what up';
	}

}

/**
 * MyCustomExceptionRenderer class
 *
 * @package       Cake.Test.Case.Error
 */
class MyCustomExceptionRenderer extends ExceptionRenderer {

/**
 * custom error message type.
 *
 * @return void
 */
	public function missingWidgetThing() {
		echo 'widget thing is missing';
	}

}

/**
 * Exception class for testing app error handlers and custom errors.
 *
 * @package       Cake.Test.Case.Error
 */
class MissingWidgetThingException extends NotFoundException {
}

/**
 * ExceptionRendererTest class
 *
 * @package       Cake.Test.Case.Error
 */
class ExceptionRendererTest extends CakeTestCase {

	protected $_restoreError = false;

/**
 * setup create a request object to get out of router later.
 *
 * @return void
 */
	public function setUp() {
		parent::setUp();
		Configure::write('Config.language', 'eng');
		App::build(array(
			'View' => array(
				CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS
			)
		), App::RESET);
		Router::reload();

		$request = new CakeRequest(null, false);
		$request->base = '';
		Router::setRequestInfo($request);
		Configure::write('debug', 2);
	}

/**
 * tearDown
 *
 * @return void
 */
	public function tearDown() {
		parent::tearDown();
		if ($this->_restoreError) {
			restore_error_handler();
		}
	}

/**
 * Mocks out the response on the ExceptionRenderer object so headers aren't modified.
 *
 * @return void
 */
	protected function _mockResponse($error) {
		$error->controller->response = $this->getMock('CakeResponse', array('_sendHeader'));
		return $error;
	}

/**
 * test that methods declared in an ExceptionRenderer subclass are not converted
 * into error400 when debug > 0
 *
 * @return void
 */
	public function testSubclassMethodsNotBeingConvertedToError() {
		Configure::write('debug', 2);

		$exception = new MissingWidgetThingException('Widget not found');
		$ExceptionRenderer = $this->_mockResponse(new MyCustomExceptionRenderer($exception));

		ob_start();
		$ExceptionRenderer->render();
		$result = ob_get_clean();

		$this->assertEquals('widget thing is missing', $result);
	}

/**
 * test that subclass methods are not converted when debug = 0
 *
 * @return void
 */
	public function testSubclassMethodsNotBeingConvertedDebug0() {
		Configure::write('debug', 0);
		$exception = new MissingWidgetThingException('Widget not found');
		$ExceptionRenderer = $this->_mockResponse(new MyCustomExceptionRenderer($exception));

		$this->assertEquals('missingWidgetThing', $ExceptionRenderer->method);

		ob_start();
		$ExceptionRenderer->render();
		$result = ob_get_clean();

		$this->assertEquals('widget thing is missing', $result, 'Method declared in subclass converted to error400');
	}

/**
 * test that ExceptionRenderer subclasses properly convert framework errors.
 *
 * @return void
 */
	public function testSubclassConvertingFrameworkErrors() {
		Configure::write('debug', 0);

		$exception = new MissingControllerException('PostsController');
		$ExceptionRenderer = $this->_mockResponse(new MyCustomExceptionRenderer($exception));

		$this->assertEquals('error400', $ExceptionRenderer->method);

		ob_start();
		$ExceptionRenderer->render();
		$result = ob_get_clean();

		$this->assertRegExp('/Not Found/', $result, 'Method declared in error handler not converted to error400. %s');
	}

/**
 * test things in the constructor.
 *
 * @return void
 */
	public function testConstruction() {
		$exception = new NotFoundException('Page not found');
		$ExceptionRenderer = new ExceptionRenderer($exception);

		$this->assertInstanceOf('CakeErrorController', $ExceptionRenderer->controller);
		$this->assertEquals('error400', $ExceptionRenderer->method);
		$this->assertEquals($exception, $ExceptionRenderer->error);
	}

/**
 * test that method gets coerced when debug = 0
 *
 * @return void
 */
	public function testErrorMethodCoercion() {
		Configure::write('debug', 0);
		$exception = new MissingActionException('Page not found');
		$ExceptionRenderer = new ExceptionRenderer($exception);

		$this->assertInstanceOf('CakeErrorController', $ExceptionRenderer->controller);
		$this->assertEquals('error400', $ExceptionRenderer->method);
		$this->assertEquals($exception, $ExceptionRenderer->error);
	}

/**
 * test that helpers in custom CakeErrorController are not lost
 *
 * @return void
 */
	public function testCakeErrorHelpersNotLost() {
		$testApp = CAKE . 'Test' . DS . 'test_app' . DS;
		App::build(array(
			'Controller' => array(
				$testApp . 'Controller' . DS
			),
			'View/Helper' => array(
				$testApp . 'View' . DS . 'Helper' . DS
			),
			'View/Layouts' => array(
				$testApp . 'View' . DS . 'Layouts' . DS
			),
			'Error' => array(
				$testApp . 'Error' . DS
			),
		), App::RESET);

		App::uses('TestAppsExceptionRenderer', 'Error');
		$exception = new SocketException('socket exception');
		$renderer = new TestAppsExceptionRenderer($exception);

		ob_start();
		$renderer->render();
		$result = ob_get_clean();
		$this->assertContains('peeled', $result);
	}

/**
 * test that unknown exception types with valid status codes are treated correctly.
 *
 * @return void
 */
	public function testUnknownExceptionTypeWithExceptionThatHasA400Code() {
		$exception = new MissingWidgetThingException('coding fail.');
		$ExceptionRenderer = new ExceptionRenderer($exception);
		$ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
		$ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(404);

		ob_start();
		$ExceptionRenderer->render();
		$result = ob_get_clean();

		$this->assertFalse(method_exists($ExceptionRenderer, 'missingWidgetThing'), 'no method should exist.');
		$this->assertEquals('error400', $ExceptionRenderer->method, 'incorrect method coercion.');
		$this->assertContains('coding fail', $result, 'Text should show up.');
	}

/**
 * test that unknown exception types with valid status codes are treated correctly.
 *
 * @return void
 */
	public function testUnknownExceptionTypeWithNoCodeIsA500() {
		$exception = new OutOfBoundsException('foul ball.');
		$ExceptionRenderer = new ExceptionRenderer($exception);
		$ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
		$ExceptionRenderer->controller->response->expects($this->once())
			->method('statusCode')
			->with(500);

		ob_start();
		$ExceptionRenderer->render();
		$result = ob_get_clean();

		$this->assertEquals('error500', $ExceptionRenderer->method, 'incorrect method coercion.');
		$this->assertContains('foul ball.', $result, 'Text should show up as its debug mode.');
	}

/**
 * test that unknown exceptions have messages ignored.
 *
 * @return void
 */
	public function testUnknownExceptionInProduction() {
		Configure::write('debug', 0);

		$exception = new OutOfBoundsException('foul ball.');
		$ExceptionRenderer = new ExceptionRenderer($exception);
		$ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
		$ExceptionRenderer->controller->response->expects($this->once())
			->method('statusCode')
			->with(500);

		ob_start();
		$ExceptionRenderer->render();
		$result = ob_get_clean();

		$this->assertEquals('error500', $ExceptionRenderer->method, 'incorrect method coercion.');
		$this->assertNotContains('foul ball.', $result, 'Text should no show up.');
		$this->assertContains('Internal Error', $result, 'Generic message only.');
	}

/**
 * test that unknown exception types with valid status codes are treated correctly.
 *
 * @return void
 */
	public function testUnknownExceptionTypeWithCodeHigherThan500() {
		$exception = new OutOfBoundsException('foul ball.', 501);
		$ExceptionRenderer = new ExceptionRenderer($exception);
		$ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
		$ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(501);

		ob_start();
		$ExceptionRenderer->render();
		$result = ob_get_clean();

		$this->assertEquals('error500', $ExceptionRenderer->method, 'incorrect method coercion.');
		$this->assertContains('foul ball.', $result, 'Text should show up as its debug mode.');
	}

/**
 * testerror400 method
 *
 * @return void
 */
	public function testError400() {
		Router::reload();

		$request = new CakeRequest('posts/view/1000', false);
		Router::setRequestInfo($request);

		$exception = new NotFoundException('Custom message');
		$ExceptionRenderer = new ExceptionRenderer($exception);
		$ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader'));
		$ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(404);

		ob_start();
		$ExceptionRenderer->render();
		$result = ob_get_clean();

		$this->assertRegExp('/

Custom message<\/h2>/', $result); $this->assertRegExp("/'.*?\/posts\/view\/1000'<\/strong>/", $result); } /** * test that error400 only modifies the messages on CakeExceptions. * * @return void */ public function testerror400OnlyChangingCakeException() { Configure::write('debug', 0); $exception = new NotFoundException('Custom message'); $ExceptionRenderer = $this->_mockResponse(new ExceptionRenderer($exception)); ob_start(); $ExceptionRenderer->render(); $result = ob_get_clean(); $this->assertContains('Custom message', $result); $exception = new MissingActionException(array('controller' => 'PostsController', 'action' => 'index')); $ExceptionRenderer = $this->_mockResponse(new ExceptionRenderer($exception)); ob_start(); $ExceptionRenderer->render(); $result = ob_get_clean(); $this->assertContains('Not Found', $result); } /** * test that error400 doesn't expose XSS * * @return void */ public function testError400NoInjection() { Router::reload(); $request = new CakeRequest('pages/pink', false); Router::setRequestInfo($request); $exception = new NotFoundException('Custom message'); $ExceptionRenderer = $this->_mockResponse(new ExceptionRenderer($exception)); ob_start(); $ExceptionRenderer->render(); $result = ob_get_clean(); $this->assertNotRegExp('##', $result); } /** * testError500 method * * @return void */ public function testError500Message() { $exception = new InternalErrorException('An Internal Error Has Occurred'); $ExceptionRenderer = new ExceptionRenderer($exception); $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader')); $ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(500); ob_start(); $ExceptionRenderer->render(); $result = ob_get_clean(); $this->assertRegExp('/

An Internal Error Has Occurred<\/h2>/', $result); } /** * testExceptionResponseHeader method * * @return void */ public function testExceptionResponseHeader() { $exception = new MethodNotAllowedException('Only allowing POST and DELETE'); $exception->responseHeader(array('Allow: POST, DELETE')); $ExceptionRenderer = new ExceptionRenderer($exception); //Replace response object with mocked object add back the original headers which had been set in ExceptionRenderer constructor $headers = $ExceptionRenderer->controller->response->header(); $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('_sendHeader')); $ExceptionRenderer->controller->response->header($headers); $ExceptionRenderer->controller->response->expects($this->at(1))->method('_sendHeader')->with('Allow', 'POST, DELETE'); ob_start(); $ExceptionRenderer->render(); ob_get_clean(); } /** * testMissingController method * * @return void */ public function testMissingController() { $exception = new MissingControllerException(array('class' => 'PostsController')); $ExceptionRenderer = $this->_mockResponse(new ExceptionRenderer($exception)); ob_start(); $ExceptionRenderer->render(); $result = ob_get_clean(); $this->assertRegExp('/

Missing Controller<\/h2>/', $result); $this->assertRegExp('/PostsController<\/em>/', $result); } /** * Returns an array of tests to run for the various CakeException classes. * * @return void */ public static function testProvider() { return array( array( new MissingActionException(array('controller' => 'PostsController', 'action' => 'index')), array( '/

Missing Method in PostsController<\/h2>/', '/PostsController::<\/em>index\(\)<\/em>/' ), 404 ), array( new PrivateActionException(array('controller' => 'PostsController', 'action' => '_secretSauce')), array( '/

Private Method in PostsController<\/h2>/', '/PostsController::<\/em>_secretSauce\(\)<\/em>/' ), 404 ), array( new MissingTableException(array('table' => 'articles', 'class' => 'Article', 'ds' => 'test')), array( '/

Missing Database Table<\/h2>/', '/Table articles<\/em> for model Article<\/em> was not found in datasource test<\/em>/' ), 500 ), array( new MissingDatabaseException(array('connection' => 'default')), array( '/

Missing Database Connection<\/h2>/', '/Confirm you have created the file/' ), 500 ), array( new MissingViewException(array('file' => '/posts/about.ctp')), array( "/posts\/about.ctp/" ), 500 ), array( new MissingLayoutException(array('file' => 'layouts/my_layout.ctp')), array( "/Missing Layout/", "/layouts\/my_layout.ctp/" ), 500 ), array( new MissingConnectionException(array('class' => 'Mysql')), array( '/

Missing Database Connection<\/h2>/', '/A Database connection using "Mysql" was missing or unable to connect./', ), 500 ), array( new MissingConnectionException(array('class' => 'Mysql', 'enabled' => false)), array( '/

Missing Database Connection<\/h2>/', '/A Database connection using "Mysql" was missing or unable to connect./', '/Mysql driver is NOT enabled/' ), 500 ), array( new MissingDatasourceConfigException(array('config' => 'default')), array( '/

Missing Datasource Configuration<\/h2>/', '/The datasource configuration default<\/em> was not found in database.php/' ), 500 ), array( new MissingDatasourceException(array('class' => 'MyDatasource', 'plugin' => 'MyPlugin')), array( '/

Missing Datasource<\/h2>/', '/Datasource class MyPlugin.MyDatasource<\/em> could not be found/' ), 500 ), array( new MissingHelperException(array('class' => 'MyCustomHelper')), array( '/

Missing Helper<\/h2>/', '/MyCustomHelper<\/em> could not be found./', '/Create the class MyCustomHelper<\/em> below in file:/', '/(\/|\\\)MyCustomHelper.php/' ), 500 ), array( new MissingBehaviorException(array('class' => 'MyCustomBehavior')), array( '/

Missing Behavior<\/h2>/', '/Create the class MyCustomBehavior<\/em> below in file:/', '/(\/|\\\)MyCustomBehavior.php/' ), 500 ), array( new MissingComponentException(array('class' => 'SideboxComponent')), array( '/

Missing Component<\/h2>/', '/Create the class SideboxComponent<\/em> below in file:/', '/(\/|\\\)SideboxComponent.php/' ), 500 ), array( new Exception('boom'), array( '/Internal Error/' ), 500 ), array( new RuntimeException('another boom'), array( '/Internal Error/' ), 500 ), array( new CakeException('base class'), array('/Internal Error/'), 500 ), array( new ConfigureException('No file'), array('/Internal Error/'), 500 ) ); } /** * Test the various CakeException sub classes * * @dataProvider testProvider * @return void */ public function testCakeExceptionHandling($exception, $patterns, $code) { $ExceptionRenderer = new ExceptionRenderer($exception); $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader')); $ExceptionRenderer->controller->response->expects($this->once()) ->method('statusCode') ->with($code); ob_start(); $ExceptionRenderer->render(); $result = ob_get_clean(); foreach ($patterns as $pattern) { $this->assertRegExp($pattern, $result); } } /** * Test exceptions being raised when helpers are missing. * * @return void */ public function testMissingRenderSafe() { $exception = new MissingHelperException(array('class' => 'Fail')); $ExceptionRenderer = new ExceptionRenderer($exception); $ExceptionRenderer->controller = $this->getMock('Controller', array('render')); $ExceptionRenderer->controller->helpers = array('Fail', 'Boom'); $ExceptionRenderer->controller->request = $this->getMock('CakeRequest'); $ExceptionRenderer->controller->expects($this->at(0)) ->method('render') ->with('missingHelper') ->will($this->throwException($exception)); $response = $this->getMock('CakeResponse'); $response->expects($this->once()) ->method('body') ->with($this->stringContains('Helper class Fail')); $ExceptionRenderer->controller->response = $response; $ExceptionRenderer->render(); sort($ExceptionRenderer->controller->helpers); $this->assertEquals(array('Form', 'Html', 'Session'), $ExceptionRenderer->controller->helpers); } /** * Test that exceptions in beforeRender() are handled by outputMessageSafe * * @return void */ public function testRenderExceptionInBeforeRender() { $exception = new NotFoundException('Not there, sorry'); $ExceptionRenderer = new ExceptionRenderer($exception); $ExceptionRenderer->controller = $this->getMock('Controller', array('beforeRender')); $ExceptionRenderer->controller->request = $this->getMock('CakeRequest'); $ExceptionRenderer->controller->expects($this->any()) ->method('beforeRender') ->will($this->throwException($exception)); $response = $this->getMock('CakeResponse'); $response->expects($this->once()) ->method('body') ->with($this->stringContains('Not there, sorry')); $ExceptionRenderer->controller->response = $response; $ExceptionRenderer->render(); } /** * Test that missing subDir/layoutPath don't cause other fatal errors. * * @return void */ public function testMissingSubdirRenderSafe() { $exception = new NotFoundException(); $ExceptionRenderer = new ExceptionRenderer($exception); $ExceptionRenderer->controller = $this->getMock('Controller', array('render')); $ExceptionRenderer->controller->helpers = array('Fail', 'Boom'); $ExceptionRenderer->controller->layoutPath = 'json'; $ExceptionRenderer->controller->subDir = 'json'; $ExceptionRenderer->controller->viewClass = 'Json'; $ExceptionRenderer->controller->request = $this->getMock('CakeRequest'); $ExceptionRenderer->controller->expects($this->once()) ->method('render') ->with('error400') ->will($this->throwException($exception)); $response = $this->getMock('CakeResponse'); $response->expects($this->once()) ->method('body') ->with($this->stringContains('Not Found')); $response->expects($this->once()) ->method('type') ->with('html'); $ExceptionRenderer->controller->response = $response; $ExceptionRenderer->render(); $this->assertEquals('', $ExceptionRenderer->controller->layoutPath); $this->assertEquals('', $ExceptionRenderer->controller->subDir); $this->assertEquals('Errors', $ExceptionRenderer->controller->viewPath); } /** * Test that missing plugin disables Controller::$plugin if the two are the same plugin. * * @return void */ public function testMissingPluginRenderSafe() { $exception = new NotFoundException(); $ExceptionRenderer = new ExceptionRenderer($exception); $ExceptionRenderer->controller = $this->getMock('Controller', array('render')); $ExceptionRenderer->controller->plugin = 'TestPlugin'; $ExceptionRenderer->controller->request = $this->getMock('CakeRequest'); $exception = new MissingPluginException(array('plugin' => 'TestPlugin')); $ExceptionRenderer->controller->expects($this->once()) ->method('render') ->with('error400') ->will($this->throwException($exception)); $response = $this->getMock('CakeResponse'); $response->expects($this->once()) ->method('body') ->with($this->logicalAnd( $this->logicalNot($this->stringContains('test plugin error500')), $this->stringContains('Not Found') )); $ExceptionRenderer->controller->response = $response; $ExceptionRenderer->render(); } /** * Test that missing plugin doesn't disable Controller::$plugin if the two aren't the same plugin. * * @return void */ public function testMissingPluginRenderSafeWithPlugin() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); $exception = new NotFoundException(); $ExceptionRenderer = new ExceptionRenderer($exception); $ExceptionRenderer->controller = $this->getMock('Controller', array('render')); $ExceptionRenderer->controller->plugin = 'TestPlugin'; $ExceptionRenderer->controller->request = $this->getMock('CakeRequest'); $exception = new MissingPluginException(array('plugin' => 'TestPluginTwo')); $ExceptionRenderer->controller->expects($this->once()) ->method('render') ->with('error400') ->will($this->throwException($exception)); $response = $this->getMock('CakeResponse'); $response->expects($this->once()) ->method('body') ->with($this->logicalAnd( $this->stringContains('test plugin error500'), $this->stringContains('Not Found') )); $ExceptionRenderer->controller->response = $response; $ExceptionRenderer->render(); CakePlugin::unload(); } /** * Test that exceptions can be rendered when an request hasn't been registered * with Router * * @return void */ public function testRenderWithNoRequest() { Router::reload(); $this->assertNull(Router::getRequest(false)); $exception = new Exception('Terrible'); $ExceptionRenderer = new ExceptionRenderer($exception); $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader')); $ExceptionRenderer->controller->response->expects($this->once()) ->method('statusCode') ->with(500); ob_start(); $ExceptionRenderer->render(); $result = ob_get_clean(); $this->assertContains('Internal Error', $result); } /** * Tests the output of rendering a PDOException * * @return void */ public function testPDOException() { $exception = new PDOException('There was an error in the SQL query'); $exception->queryString = 'SELECT * from poo_query < 5 and :seven'; $exception->params = array('seven' => 7); $ExceptionRenderer = new ExceptionRenderer($exception); $ExceptionRenderer->controller->response = $this->getMock('CakeResponse', array('statusCode', '_sendHeader')); $ExceptionRenderer->controller->response->expects($this->once())->method('statusCode')->with(500); ob_start(); $ExceptionRenderer->render(); $result = ob_get_clean(); $this->assertContains('

Database Error

', $result); $this->assertContains('There was an error in the SQL query', $result); $this->assertContains(h('SELECT * from poo_query < 5 and :seven'), $result); $this->assertContains("'seven' => (int) 7", $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Event/000077500000000000000000000000001265552240500174265ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Event/CakeEventManagerTest.php000066400000000000000000000412111265552240500241360ustar00rootroot00000000000000callStack[] = __FUNCTION__; } /** * Test function to be used in event dispatching * * @return void */ public function secondListenerFunction() { $this->callStack[] = __FUNCTION__; } /** * Auxiliary function to help in stopPropagation testing * * @param CakeEvent $event * @return void */ public function stopListener($event) { $event->stopPropagation(); } } /** * Mock used for testing the subscriber objects * * @package Cake.Test.Case.Event */ class CustomTestEventListener extends CakeEventTestListener implements CakeEventListener { public function implementedEvents() { return array( 'fake.event' => 'listenerFunction', 'another.event' => array('callable' => 'secondListenerFunction', 'passParams' => true), 'multiple.handlers' => array( array('callable' => 'listenerFunction'), array('callable' => 'thirdListenerFunction') ) ); } /** * Test function to be used in event dispatching * * @return void */ public function thirdListenerFunction() { $this->callStack[] = __FUNCTION__; } } /** * Tests the CakeEventManager class functionality */ class CakeEventManagerTest extends CakeTestCase { /** * Tests the attach() method for a single event key in multiple queues * * @return void */ public function testAttachListeners() { $manager = new CakeEventManager(); $manager->attach('fakeFunction', 'fake.event'); $expected = array( array('callable' => 'fakeFunction', 'passParams' => false) ); $this->assertEquals($expected, $manager->listeners('fake.event')); $manager->attach('fakeFunction2', 'fake.event'); $expected[] = array('callable' => 'fakeFunction2', 'passParams' => false); $this->assertEquals($expected, $manager->listeners('fake.event')); $manager->attach('inQ5', 'fake.event', array('priority' => 5)); $manager->attach('inQ1', 'fake.event', array('priority' => 1)); $manager->attach('otherInQ5', 'fake.event', array('priority' => 5)); $expected = array_merge( array( array('callable' => 'inQ1', 'passParams' => false), array('callable' => 'inQ5', 'passParams' => false), array('callable' => 'otherInQ5', 'passParams' => false) ), $expected ); $this->assertEquals($expected, $manager->listeners('fake.event')); } /** * Tests the attach() method for multiple event key in multiple queues * * @return void */ public function testAttachMultipleEventKeys() { $manager = new CakeEventManager(); $manager->attach('fakeFunction', 'fake.event'); $manager->attach('fakeFunction2', 'another.event'); $manager->attach('fakeFunction3', 'another.event', array('priority' => 1, 'passParams' => true)); $expected = array( array('callable' => 'fakeFunction', 'passParams' => false) ); $this->assertEquals($expected, $manager->listeners('fake.event')); $expected = array( array('callable' => 'fakeFunction3', 'passParams' => true), array('callable' => 'fakeFunction2', 'passParams' => false) ); $this->assertEquals($expected, $manager->listeners('another.event')); } /** * Tests detaching an event from a event key queue * * @return void */ public function testDetach() { $manager = new CakeEventManager(); $manager->attach(array('AClass', 'aMethod'), 'fake.event'); $manager->attach(array('AClass', 'anotherMethod'), 'another.event'); $manager->attach('fakeFunction', 'another.event', array('priority' => 1)); $manager->detach(array('AClass', 'aMethod'), 'fake.event'); $this->assertEquals(array(), $manager->listeners('fake.event')); $manager->detach(array('AClass', 'anotherMethod'), 'another.event'); $expected = array( array('callable' => 'fakeFunction', 'passParams' => false) ); $this->assertEquals($expected, $manager->listeners('another.event')); $manager->detach('fakeFunction', 'another.event'); $this->assertEquals(array(), $manager->listeners('another.event')); } /** * Tests detaching an event from all event queues * * @return void */ public function testDetachFromAll() { $manager = new CakeEventManager(); $manager->attach(array('AClass', 'aMethod'), 'fake.event'); $manager->attach(array('AClass', 'aMethod'), 'another.event'); $manager->attach('fakeFunction', 'another.event', array('priority' => 1)); $manager->detach(array('AClass', 'aMethod')); $expected = array( array('callable' => 'fakeFunction', 'passParams' => false) ); $this->assertEquals($expected, $manager->listeners('another.event')); $this->assertEquals(array(), $manager->listeners('fake.event')); } /** * Tests event dispatching * * @return void * @triggers fake.event */ public function testDispatch() { $manager = new CakeEventManager(); $listener = $this->getMock('CakeEventTestListener'); $anotherListener = $this->getMock('CakeEventTestListener'); $manager->attach(array($listener, 'listenerFunction'), 'fake.event'); $manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event'); $event = new CakeEvent('fake.event'); $listener->expects($this->once())->method('listenerFunction')->with($event); $anotherListener->expects($this->once())->method('listenerFunction')->with($event); $manager->dispatch($event); } /** * Tests event dispatching using event key name * * @return void */ public function testDispatchWithKeyName() { $manager = new CakeEventManager(); $listener = new CakeEventTestListener(); $manager->attach(array($listener, 'listenerFunction'), 'fake.event'); $event = 'fake.event'; $manager->dispatch($event); $expected = array('listenerFunction'); $this->assertEquals($expected, $listener->callStack); } /** * Tests event dispatching with a return value * * @return void * @triggers fake.event */ public function testDispatchReturnValue() { $this->skipIf( version_compare(PHPUnit_Runner_Version::id(), '3.7', '<'), 'These tests fail in PHPUnit 3.6' ); $manager = new CakeEventManager(); $listener = $this->getMock('CakeEventTestListener'); $anotherListener = $this->getMock('CakeEventTestListener'); $manager->attach(array($listener, 'listenerFunction'), 'fake.event'); $manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event'); $event = new CakeEvent('fake.event'); $listener->expects($this->at(0))->method('listenerFunction') ->with($event) ->will($this->returnValue('something special')); $anotherListener->expects($this->at(0)) ->method('listenerFunction') ->with($event); $manager->dispatch($event); $this->assertEquals('something special', $event->result); } /** * Tests that returning false in a callback stops the event * * @return void * @triggers fake.event */ public function testDispatchFalseStopsEvent() { $this->skipIf( version_compare(PHPUnit_Runner_Version::id(), '3.7', '<'), 'These tests fail in PHPUnit 3.6' ); $manager = new CakeEventManager(); $listener = $this->getMock('CakeEventTestListener'); $anotherListener = $this->getMock('CakeEventTestListener'); $manager->attach(array($listener, 'listenerFunction'), 'fake.event'); $manager->attach(array($anotherListener, 'listenerFunction'), 'fake.event'); $event = new CakeEvent('fake.event'); $listener->expects($this->at(0))->method('listenerFunction') ->with($event) ->will($this->returnValue(false)); $anotherListener->expects($this->never()) ->method('listenerFunction'); $manager->dispatch($event); $this->assertTrue($event->isStopped()); } /** * Tests event dispatching using priorities * * @return void * @triggers fake.event */ public function testDispatchPrioritized() { $manager = new CakeEventManager(); $listener = new CakeEventTestListener(); $manager->attach(array($listener, 'listenerFunction'), 'fake.event'); $manager->attach(array($listener, 'secondListenerFunction'), 'fake.event', array('priority' => 5)); $event = new CakeEvent('fake.event'); $manager->dispatch($event); $expected = array('secondListenerFunction', 'listenerFunction'); $this->assertEquals($expected, $listener->callStack); } /** * Tests event dispatching with passed params * * @return void * @triggers fake.event $this, array('some' => 'data') */ public function testDispatchPassingParams() { $manager = new CakeEventManager(); $listener = $this->getMock('CakeEventTestListener'); $anotherListener = $this->getMock('CakeEventTestListener'); $manager->attach(array($listener, 'listenerFunction'), 'fake.event'); $manager->attach(array($anotherListener, 'secondListenerFunction'), 'fake.event', array('passParams' => true)); $event = new CakeEvent('fake.event', $this, array('some' => 'data')); $listener->expects($this->once())->method('listenerFunction')->with($event); $anotherListener->expects($this->once())->method('secondListenerFunction')->with('data'); $manager->dispatch($event); } /** * Tests subscribing a listener object and firing the events it subscribed to * * @return void * @triggers fake.event * @triggers another.event $this, array('some' => 'data') * @triggers multiple.handlers */ public function testAttachSubscriber() { $manager = new CakeEventManager(); $listener = $this->getMock('CustomTestEventListener', array('secondListenerFunction')); $manager->attach($listener); $event = new CakeEvent('fake.event'); $manager->dispatch($event); $expected = array('listenerFunction'); $this->assertEquals($expected, $listener->callStack); $listener->expects($this->at(0))->method('secondListenerFunction')->with('data'); $event = new CakeEvent('another.event', $this, array('some' => 'data')); $manager->dispatch($event); $manager = new CakeEventManager(); $listener = $this->getMock('CustomTestEventListener', array('listenerFunction', 'thirdListenerFunction')); $manager->attach($listener); $event = new CakeEvent('multiple.handlers'); $listener->expects($this->once())->method('listenerFunction')->with($event); $listener->expects($this->once())->method('thirdListenerFunction')->with($event); $manager->dispatch($event); } /** * Tests subscribing a listener object and firing the events it subscribed to * * @return void */ public function testDetachSubscriber() { $manager = new CakeEventManager(); $listener = $this->getMock('CustomTestEventListener', array('secondListenerFunction')); $manager->attach($listener); $expected = array( array('callable' => array($listener, 'secondListenerFunction'), 'passParams' => true) ); $this->assertEquals($expected, $manager->listeners('another.event')); $expected = array( array('callable' => array($listener, 'listenerFunction'), 'passParams' => false) ); $this->assertEquals($expected, $manager->listeners('fake.event')); $manager->detach($listener); $this->assertEquals(array(), $manager->listeners('fake.event')); $this->assertEquals(array(), $manager->listeners('another.event')); } /** * Tests that it is possible to get/set the manager singleton * * @return void */ public function testGlobalDispatcherGetter() { $this->assertInstanceOf('CakeEventManager', CakeEventManager::instance()); $manager = new CakeEventManager(); CakeEventManager::instance($manager); $this->assertSame($manager, CakeEventManager::instance()); } /** * Tests that the global event manager gets the event too from any other manager * * @return void * @triggers fake.event */ public function testDispatchWithGlobal() { $generalManager = $this->getMock('CakeEventManager', array('prioritisedListeners')); $manager = new CakeEventManager(); $event = new CakeEvent('fake.event'); CakeEventManager::instance($generalManager); $generalManager->expects($this->once())->method('prioritisedListeners')->with('fake.event'); $manager->dispatch($event); CakeEventManager::instance(new CakeEventManager()); } /** * Tests that stopping an event will not notify the rest of the listeners * * @return void * @triggers fake.event */ public function testStopPropagation() { $generalManager = $this->getMock('CakeEventManager'); $manager = new CakeEventManager(); $listener = new CakeEventTestListener(); CakeEventManager::instance($generalManager); $generalManager->expects($this->any()) ->method('prioritisedListeners') ->with('fake.event') ->will($this->returnValue(array())); $manager->attach(array($listener, 'listenerFunction'), 'fake.event'); $manager->attach(array($listener, 'stopListener'), 'fake.event', array('priority' => 8)); $manager->attach(array($listener, 'secondListenerFunction'), 'fake.event', array('priority' => 5)); $event = new CakeEvent('fake.event'); $manager->dispatch($event); $expected = array('secondListenerFunction'); $this->assertEquals($expected, $listener->callStack); CakeEventManager::instance(new CakeEventManager()); } /** * Tests event dispatching using priorities * * @return void * @triggers fake.event */ public function testDispatchPrioritizedWithGlobal() { $generalManager = $this->getMock('CakeEventManager'); $manager = new CakeEventManager(); $listener = new CustomTestEventListener(); $event = new CakeEvent('fake.event'); CakeEventManager::instance($generalManager); $generalManager->expects($this->any()) ->method('prioritisedListeners') ->with('fake.event') ->will($this->returnValue( array(11 => array( array('callable' => array($listener, 'secondListenerFunction'), 'passParams' => false) )) )); $manager->attach(array($listener, 'listenerFunction'), 'fake.event'); $manager->attach(array($listener, 'thirdListenerFunction'), 'fake.event', array('priority' => 15)); $manager->dispatch($event); $expected = array('listenerFunction', 'secondListenerFunction', 'thirdListenerFunction'); $this->assertEquals($expected, $listener->callStack); CakeEventManager::instance(new CakeEventManager()); } /** * Tests event dispatching using priorities * * @return void * @triggers fake.event */ public function testDispatchGlobalBeforeLocal() { $generalManager = $this->getMock('CakeEventManager'); $manager = new CakeEventManager(); $listener = new CustomTestEventListener(); $event = new CakeEvent('fake.event'); CakeEventManager::instance($generalManager); $generalManager->expects($this->any()) ->method('prioritisedListeners') ->with('fake.event') ->will($this->returnValue( array(10 => array( array('callable' => array($listener, 'listenerFunction'), 'passParams' => false) )) )); $manager->attach(array($listener, 'secondListenerFunction'), 'fake.event'); $manager->dispatch($event); $expected = array('listenerFunction', 'secondListenerFunction'); $this->assertEquals($expected, $listener->callStack); CakeEventManager::instance(new CakeEventManager()); } /** * test callback */ public function onMyEvent($event) { $event->data['callback'] = 'ok'; } /** * Tests events dispatched by a local manager can be handled by * handler registered in the global event manager * @triggers my_event $manager */ public function testDispatchLocalHandledByGlobal() { $callback = array($this, 'onMyEvent'); CakeEventManager::instance()->attach($callback, 'my_event'); $manager = new CakeEventManager(); $event = new CakeEvent('my_event', $manager); $manager->dispatch($event); $this->assertEquals('ok', $event->data['callback']); } /** * Test that events are dispatched properly when there are global and local * listeners at the same priority. * * @return void * @triggers fake.event $this */ public function testDispatchWithGlobalAndLocalEvents() { $listener = new CustomTestEventListener(); CakeEventManager::instance()->attach($listener); $listener2 = new CakeEventTestListener(); $manager = new CakeEventManager(); $manager->attach(array($listener2, 'listenerFunction'), 'fake.event'); $manager->dispatch(new CakeEvent('fake.event', $this)); $this->assertEquals(array('listenerFunction'), $listener->callStack); $this->assertEquals(array('listenerFunction'), $listener2->callStack); } } cakephp-2.8.0/lib/Cake/Test/Case/Event/CakeEventTest.php000066400000000000000000000044001265552240500226420ustar00rootroot00000000000000assertEquals('fake.event', $event->name()); } /** * Tests the subject() method * * @return void * @triggers fake.event $this * @triggers fake.event */ public function testSubject() { $event = new CakeEvent('fake.event', $this); $this->assertSame($this, $event->subject()); $event = new CakeEvent('fake.event'); $this->assertNull($event->subject()); } /** * Tests the event propagation stopping property * * @return void * @triggers fake.event */ public function testPropagation() { $event = new CakeEvent('fake.event'); $this->assertFalse($event->isStopped()); $event->stopPropagation(); $this->assertTrue($event->isStopped()); } /** * Tests that it is possible to get/set custom data in a event * * @return void * @triggers fake.event $this, array('some' => 'data') */ public function testEventData() { $event = new CakeEvent('fake.event', $this, array('some' => 'data')); $this->assertEquals(array('some' => 'data'), $event->data); } /** * Tests that it is possible to get the name and subject directly * * @return void * @triggers fake.event $this */ public function testEventDirectPropertyAccess() { $event = new CakeEvent('fake.event', $this); $this->assertEquals($this, $event->subject); $this->assertEquals('fake.event', $event->name); } } cakephp-2.8.0/lib/Cake/Test/Case/I18n/000077500000000000000000000000001265552240500170645ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/I18n/I18nTest.php000066400000000000000000003236611265552240500211670ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.I18n * @since CakePHP(tm) v 1.2.0.5432 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('I18n', 'I18n'); App::uses('CakeSession', 'Model/Datasource'); /** * I18nTest class * * @package Cake.Test.Case.I18n */ class I18nTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); Cache::delete('object_map', '_cake_core_'); App::build(array( 'Locale' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Locale' . DS), 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load(array('TestPlugin')); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); Cache::delete('object_map', '_cake_core_'); App::build(); CakePlugin::unload(); } /** * testTranslationCaching method * * @return void */ public function testTranslationCaching() { Configure::write('Config.language', 'cache_test_po'); // reset internally stored entries I18n::clear(); Cache::clear(false, '_cake_core_'); $lang = Configure::read('Config.language'); Cache::config('_cake_core_', Cache::config('default')); // make some calls to translate using different domains $this->assertEquals('Dom 1 Foo', I18n::translate('dom1.foo', false, 'dom1')); $this->assertEquals('Dom 1 Bar', I18n::translate('dom1.bar', false, 'dom1')); $domains = I18n::domains(); $this->assertEquals('Dom 1 Foo', $domains['dom1']['cache_test_po']['LC_MESSAGES']['dom1.foo']['']); // reset internally stored entries I18n::clear(); // now only dom1 should be in cache $cachedDom1 = Cache::read('dom1_' . $lang, '_cake_core_'); $this->assertEquals('Dom 1 Foo', $cachedDom1['LC_MESSAGES']['dom1.foo']['']); $this->assertEquals('Dom 1 Bar', $cachedDom1['LC_MESSAGES']['dom1.bar']['']); // dom2 not in cache $this->assertFalse(Cache::read('dom2_' . $lang, '_cake_core_')); // translate a item of dom2 (adds dom2 to cache) $this->assertEquals('Dom 2 Foo', I18n::translate('dom2.foo', false, 'dom2')); // verify dom2 was cached through manual read from cache $cachedDom2 = Cache::read('dom2_' . $lang, '_cake_core_'); $this->assertEquals('Dom 2 Foo', $cachedDom2['LC_MESSAGES']['dom2.foo']['']); $this->assertEquals('Dom 2 Bar', $cachedDom2['LC_MESSAGES']['dom2.bar']['']); // modify cache entry manually to verify that dom1 entries now will be read from cache $cachedDom1['LC_MESSAGES']['dom1.foo'][''] = 'FOO'; Cache::write('dom1_' . $lang, $cachedDom1, '_cake_core_'); $this->assertEquals('FOO', I18n::translate('dom1.foo', false, 'dom1')); } /** * testDefaultStrings method * * @return void */ public function testDefaultStrings() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 1', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 = 0 or > 1', $plurals)); $this->assertTrue(in_array('1 = 1', $plurals)); $this->assertTrue(in_array('2 = 0 or > 1', $plurals)); $this->assertTrue(in_array('3 = 0 or > 1', $plurals)); $this->assertTrue(in_array('4 = 0 or > 1', $plurals)); $this->assertTrue(in_array('5 = 0 or > 1', $plurals)); $this->assertTrue(in_array('6 = 0 or > 1', $plurals)); $this->assertTrue(in_array('7 = 0 or > 1', $plurals)); $this->assertTrue(in_array('8 = 0 or > 1', $plurals)); $this->assertTrue(in_array('9 = 0 or > 1', $plurals)); $this->assertTrue(in_array('10 = 0 or > 1', $plurals)); $this->assertTrue(in_array('11 = 0 or > 1', $plurals)); $this->assertTrue(in_array('12 = 0 or > 1', $plurals)); $this->assertTrue(in_array('13 = 0 or > 1', $plurals)); $this->assertTrue(in_array('14 = 0 or > 1', $plurals)); $this->assertTrue(in_array('15 = 0 or > 1', $plurals)); $this->assertTrue(in_array('16 = 0 or > 1', $plurals)); $this->assertTrue(in_array('17 = 0 or > 1', $plurals)); $this->assertTrue(in_array('18 = 0 or > 1', $plurals)); $this->assertTrue(in_array('19 = 0 or > 1', $plurals)); $this->assertTrue(in_array('20 = 0 or > 1', $plurals)); $this->assertTrue(in_array('21 = 0 or > 1', $plurals)); $this->assertTrue(in_array('22 = 0 or > 1', $plurals)); $this->assertTrue(in_array('23 = 0 or > 1', $plurals)); $this->assertTrue(in_array('24 = 0 or > 1', $plurals)); $this->assertTrue(in_array('25 = 0 or > 1', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 1 (from core)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('1 = 1 (from core)', $corePlurals)); $this->assertTrue(in_array('2 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('3 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('4 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('5 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('6 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('7 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('8 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('9 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('10 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('11 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('12 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('13 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('14 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('15 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('16 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('17 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('18 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('19 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('20 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('21 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('22 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('23 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('24 = 0 or > 1 (from core)', $corePlurals)); $this->assertTrue(in_array('25 = 0 or > 1 (from core)', $corePlurals)); } /** * testPoRulesZero method * * @return void */ public function testPoRulesZero() { Configure::write('Config.language', 'rule_0_po'); $this->assertRulesZero(); } /** * testMoRulesZero method * * @return void */ public function testMoRulesZero() { Configure::write('Config.language', 'rule_0_mo'); $this->assertRulesZero(); } /** * Assertions for rules zero. * * @return void */ public function assertRulesZero() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 0 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('1 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('2 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('3 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('4 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('5 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('6 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('7 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('8 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('9 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('10 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('11 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('12 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('13 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('14 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('15 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('16 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('17 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('18 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('19 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('20 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('21 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('22 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('23 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('24 ends with any # (translated)', $plurals)); $this->assertTrue(in_array('25 ends with any # (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 0 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 ends with any # (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 ends with any # (from core translated)', $corePlurals)); } /** * testPoRulesOne method * * @return void */ public function testPoRulesOne() { Configure::write('Config.language', 'rule_1_po'); $this->assertRulesOne(); } /** * testMoRulesOne method * * @return void */ public function testMoRulesOne() { Configure::write('Config.language', 'rule_1_mo'); $this->assertRulesOne(); } /** * Assertions for plural rule one * * @return void */ public function assertRulesOne() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 1 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('1 = 1 (translated)', $plurals)); $this->assertTrue(in_array('2 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('3 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('4 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('5 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('6 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('7 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('8 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('9 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('10 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('11 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('12 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('13 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('14 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('15 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('16 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('17 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('18 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('19 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('20 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('21 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('22 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('23 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('24 = 0 or > 1 (translated)', $plurals)); $this->assertTrue(in_array('25 = 0 or > 1 (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 1 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 = 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 = 0 or > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 = 0 or > 1 (from core translated)', $corePlurals)); } /** * testMoRulesTwo method * * @return void */ public function testMoRulesTwo() { Configure::write('Config.language', 'rule_2_mo'); $this->assertRulesTwo(); } /** * testPoRulesTwo method * * @return void */ public function testPoRulesTwo() { Configure::write('Config.language', 'rule_2_po'); $this->assertRulesTwo(); } /** * Assertions for rules Two * * @return void */ public function assertRulesTwo() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 2 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 = 0 or 1 (translated)', $plurals)); $this->assertTrue(in_array('1 = 0 or 1 (translated)', $plurals)); $this->assertTrue(in_array('2 > 1 (translated)', $plurals)); $this->assertTrue(in_array('3 > 1 (translated)', $plurals)); $this->assertTrue(in_array('4 > 1 (translated)', $plurals)); $this->assertTrue(in_array('5 > 1 (translated)', $plurals)); $this->assertTrue(in_array('6 > 1 (translated)', $plurals)); $this->assertTrue(in_array('7 > 1 (translated)', $plurals)); $this->assertTrue(in_array('8 > 1 (translated)', $plurals)); $this->assertTrue(in_array('9 > 1 (translated)', $plurals)); $this->assertTrue(in_array('10 > 1 (translated)', $plurals)); $this->assertTrue(in_array('11 > 1 (translated)', $plurals)); $this->assertTrue(in_array('12 > 1 (translated)', $plurals)); $this->assertTrue(in_array('13 > 1 (translated)', $plurals)); $this->assertTrue(in_array('14 > 1 (translated)', $plurals)); $this->assertTrue(in_array('15 > 1 (translated)', $plurals)); $this->assertTrue(in_array('16 > 1 (translated)', $plurals)); $this->assertTrue(in_array('17 > 1 (translated)', $plurals)); $this->assertTrue(in_array('18 > 1 (translated)', $plurals)); $this->assertTrue(in_array('19 > 1 (translated)', $plurals)); $this->assertTrue(in_array('20 > 1 (translated)', $plurals)); $this->assertTrue(in_array('21 > 1 (translated)', $plurals)); $this->assertTrue(in_array('22 > 1 (translated)', $plurals)); $this->assertTrue(in_array('23 > 1 (translated)', $plurals)); $this->assertTrue(in_array('24 > 1 (translated)', $plurals)); $this->assertTrue(in_array('25 > 1 (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 2 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 = 0 or 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 = 0 or 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 > 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 > 1 (from core translated)', $corePlurals)); } /** * testPoRulesThree method * * @return void */ public function testPoRulesThree() { Configure::write('Config.language', 'rule_3_po'); $this->assertRulesThree(); } /** * testMoRulesThree method * * @return void */ public function testMoRulesThree() { Configure::write('Config.language', 'rule_3_mo'); $this->assertRulesThree(); } /** * Assert rules for plural three. * * @return void */ public function assertRulesThree() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 3 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 = 0 (translated)', $plurals)); $this->assertTrue(in_array('1 ends 1 but not 11 (translated)', $plurals)); $this->assertTrue(in_array('2 everything else (translated)', $plurals)); $this->assertTrue(in_array('3 everything else (translated)', $plurals)); $this->assertTrue(in_array('4 everything else (translated)', $plurals)); $this->assertTrue(in_array('5 everything else (translated)', $plurals)); $this->assertTrue(in_array('6 everything else (translated)', $plurals)); $this->assertTrue(in_array('7 everything else (translated)', $plurals)); $this->assertTrue(in_array('8 everything else (translated)', $plurals)); $this->assertTrue(in_array('9 everything else (translated)', $plurals)); $this->assertTrue(in_array('10 everything else (translated)', $plurals)); $this->assertTrue(in_array('11 everything else (translated)', $plurals)); $this->assertTrue(in_array('12 everything else (translated)', $plurals)); $this->assertTrue(in_array('13 everything else (translated)', $plurals)); $this->assertTrue(in_array('14 everything else (translated)', $plurals)); $this->assertTrue(in_array('15 everything else (translated)', $plurals)); $this->assertTrue(in_array('16 everything else (translated)', $plurals)); $this->assertTrue(in_array('17 everything else (translated)', $plurals)); $this->assertTrue(in_array('18 everything else (translated)', $plurals)); $this->assertTrue(in_array('19 everything else (translated)', $plurals)); $this->assertTrue(in_array('20 everything else (translated)', $plurals)); $this->assertTrue(in_array('21 ends 1 but not 11 (translated)', $plurals)); $this->assertTrue(in_array('22 everything else (translated)', $plurals)); $this->assertTrue(in_array('23 everything else (translated)', $plurals)); $this->assertTrue(in_array('24 everything else (translated)', $plurals)); $this->assertTrue(in_array('25 everything else (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 3 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 = 0 (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 ends 1 but not 11 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 ends 1 but not 11 (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 everything else (from core translated)', $corePlurals)); } /** * testPoRulesFour method * * @return void */ public function testPoRulesFour() { Configure::write('Config.language', 'rule_4_po'); $this->assertRulesFour(); } /** * testMoRulesFour method * * @return void */ public function testMoRulesFour() { Configure::write('Config.language', 'rule_4_mo'); $this->assertRulesFour(); } /** * Run the assertions for Rule 4 plurals. * * @return void */ public function assertRulesFour() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 4 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 everything else (translated)', $plurals)); $this->assertTrue(in_array('1 = 1 (translated)', $plurals)); $this->assertTrue(in_array('2 = 2 (translated)', $plurals)); $this->assertTrue(in_array('3 everything else (translated)', $plurals)); $this->assertTrue(in_array('4 everything else (translated)', $plurals)); $this->assertTrue(in_array('5 everything else (translated)', $plurals)); $this->assertTrue(in_array('6 everything else (translated)', $plurals)); $this->assertTrue(in_array('7 everything else (translated)', $plurals)); $this->assertTrue(in_array('8 everything else (translated)', $plurals)); $this->assertTrue(in_array('9 everything else (translated)', $plurals)); $this->assertTrue(in_array('10 everything else (translated)', $plurals)); $this->assertTrue(in_array('11 everything else (translated)', $plurals)); $this->assertTrue(in_array('12 everything else (translated)', $plurals)); $this->assertTrue(in_array('13 everything else (translated)', $plurals)); $this->assertTrue(in_array('14 everything else (translated)', $plurals)); $this->assertTrue(in_array('15 everything else (translated)', $plurals)); $this->assertTrue(in_array('16 everything else (translated)', $plurals)); $this->assertTrue(in_array('17 everything else (translated)', $plurals)); $this->assertTrue(in_array('18 everything else (translated)', $plurals)); $this->assertTrue(in_array('19 everything else (translated)', $plurals)); $this->assertTrue(in_array('20 everything else (translated)', $plurals)); $this->assertTrue(in_array('21 everything else (translated)', $plurals)); $this->assertTrue(in_array('22 everything else (translated)', $plurals)); $this->assertTrue(in_array('23 everything else (translated)', $plurals)); $this->assertTrue(in_array('24 everything else (translated)', $plurals)); $this->assertTrue(in_array('25 everything else (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 4 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 = 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 = 2 (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 everything else (from core translated)', $corePlurals)); } /** * testPoRulesFive method * * @return void */ public function testPoRulesFive() { Configure::write('Config.language', 'rule_5_po'); $this->assertRulesFive(); } /** * testMoRulesFive method * * @return void */ public function testMoRulesFive() { Configure::write('Config.language', 'rule_5_mo'); $this->assertRulesFive(); } /** * Run the assertions for rule 5 plurals * * @return void */ public function assertRulesFive() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 5 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('0 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('1 = 1 (translated)', $plurals)); $this->assertTrue(in_array('2 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('3 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('4 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('5 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('6 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('7 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('8 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('9 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('10 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('11 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('12 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('13 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('14 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('15 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('16 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('17 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('18 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('19 = 0 or ends in 01-19 (translated)', $plurals)); $this->assertTrue(in_array('20 everything else (translated)', $plurals)); $this->assertTrue(in_array('21 everything else (translated)', $plurals)); $this->assertTrue(in_array('22 everything else (translated)', $plurals)); $this->assertTrue(in_array('23 everything else (translated)', $plurals)); $this->assertTrue(in_array('24 everything else (translated)', $plurals)); $this->assertTrue(in_array('25 everything else (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 5 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('0 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 = 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 = 0 or ends in 01-19 (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 everything else (from core translated)', $corePlurals)); } /** * testPoRulesSix method * * @return void */ public function testPoRulesSix() { Configure::write('Config.language', 'rule_6_po'); $this->assertRulesSix(); } /** * testMoRulesSix method * * @return void */ public function testMoRulesSix() { Configure::write('Config.language', 'rule_6_mo'); $this->assertRulesSix(); } /** * Assertions for the sixth plural rules. * * @return void */ public function assertRulesSix() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 6 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 ends in 0 or ends in 10-20 (translated)', $plurals)); $this->assertTrue(in_array('1 ends in 1, not 11 (translated)', $plurals)); $this->assertTrue(in_array('2 everything else (translated)', $plurals)); $this->assertTrue(in_array('3 everything else (translated)', $plurals)); $this->assertTrue(in_array('4 everything else (translated)', $plurals)); $this->assertTrue(in_array('5 everything else (translated)', $plurals)); $this->assertTrue(in_array('6 everything else (translated)', $plurals)); $this->assertTrue(in_array('7 everything else (translated)', $plurals)); $this->assertTrue(in_array('8 everything else (translated)', $plurals)); $this->assertTrue(in_array('9 everything else (translated)', $plurals)); $this->assertTrue(in_array('10 ends in 0 or ends in 10-20 (translated)', $plurals)); $this->assertTrue(in_array('11 ends in 0 or ends in 10-20 (translated)', $plurals)); $this->assertTrue(in_array('12 ends in 0 or ends in 10-20 (translated)', $plurals)); $this->assertTrue(in_array('13 ends in 0 or ends in 10-20 (translated)', $plurals)); $this->assertTrue(in_array('14 ends in 0 or ends in 10-20 (translated)', $plurals)); $this->assertTrue(in_array('15 ends in 0 or ends in 10-20 (translated)', $plurals)); $this->assertTrue(in_array('16 ends in 0 or ends in 10-20 (translated)', $plurals)); $this->assertTrue(in_array('17 ends in 0 or ends in 10-20 (translated)', $plurals)); $this->assertTrue(in_array('18 ends in 0 or ends in 10-20 (translated)', $plurals)); $this->assertTrue(in_array('19 ends in 0 or ends in 10-20 (translated)', $plurals)); $this->assertTrue(in_array('20 ends in 0 or ends in 10-20 (translated)', $plurals)); $this->assertTrue(in_array('21 ends in 1, not 11 (translated)', $plurals)); $this->assertTrue(in_array('22 everything else (translated)', $plurals)); $this->assertTrue(in_array('23 everything else (translated)', $plurals)); $this->assertTrue(in_array('24 everything else (translated)', $plurals)); $this->assertTrue(in_array('25 everything else (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 6 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 ends in 0 or ends in 10-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 ends in 1, not 11 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 ends in 0 or ends in 10-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 ends in 0 or ends in 10-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 ends in 0 or ends in 10-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 ends in 0 or ends in 10-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 ends in 0 or ends in 10-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 ends in 0 or ends in 10-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 ends in 0 or ends in 10-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 ends in 0 or ends in 10-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 ends in 0 or ends in 10-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 ends in 0 or ends in 10-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 ends in 0 or ends in 10-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 ends in 1, not 11 (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 everything else (from core translated)', $corePlurals)); } /** * testPoRulesSeven method * * @return void */ public function testPoRulesSeven() { Configure::write('Config.language', 'rule_7_po'); $this->assertRulesSeven(); } /** * testMoRulesSeven method * * @return void */ public function testMoRulesSeven() { Configure::write('Config.language', 'rule_7_mo'); $this->assertRulesSeven(); } /** * Run assertions for seventh plural rules * * @return void */ public function assertRulesSeven() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 7 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 everything else (translated)', $plurals)); $this->assertTrue(in_array('1 ends in 1, not 11 (translated)', $plurals)); $this->assertTrue(in_array('2 ends in 2-4, not 12-14 (translated)', $plurals)); $this->assertTrue(in_array('3 ends in 2-4, not 12-14 (translated)', $plurals)); $this->assertTrue(in_array('4 ends in 2-4, not 12-14 (translated)', $plurals)); $this->assertTrue(in_array('5 everything else (translated)', $plurals)); $this->assertTrue(in_array('6 everything else (translated)', $plurals)); $this->assertTrue(in_array('7 everything else (translated)', $plurals)); $this->assertTrue(in_array('8 everything else (translated)', $plurals)); $this->assertTrue(in_array('9 everything else (translated)', $plurals)); $this->assertTrue(in_array('10 everything else (translated)', $plurals)); $this->assertTrue(in_array('11 everything else (translated)', $plurals)); $this->assertTrue(in_array('12 everything else (translated)', $plurals)); $this->assertTrue(in_array('13 everything else (translated)', $plurals)); $this->assertTrue(in_array('14 everything else (translated)', $plurals)); $this->assertTrue(in_array('15 everything else (translated)', $plurals)); $this->assertTrue(in_array('16 everything else (translated)', $plurals)); $this->assertTrue(in_array('17 everything else (translated)', $plurals)); $this->assertTrue(in_array('18 everything else (translated)', $plurals)); $this->assertTrue(in_array('19 everything else (translated)', $plurals)); $this->assertTrue(in_array('20 everything else (translated)', $plurals)); $this->assertTrue(in_array('21 ends in 1, not 11 (translated)', $plurals)); $this->assertTrue(in_array('22 ends in 2-4, not 12-14 (translated)', $plurals)); $this->assertTrue(in_array('23 ends in 2-4, not 12-14 (translated)', $plurals)); $this->assertTrue(in_array('24 ends in 2-4, not 12-14 (translated)', $plurals)); $this->assertTrue(in_array('25 everything else (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 7 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 ends in 1, not 11 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 ends in 2-4, not 12-14 (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 ends in 2-4, not 12-14 (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 ends in 2-4, not 12-14 (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 ends in 1, not 11 (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 ends in 2-4, not 12-14 (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 ends in 2-4, not 12-14 (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 ends in 2-4, not 12-14 (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 everything else (from core translated)', $corePlurals)); } /** * testPoRulesEight method * * @return void */ public function testPoRulesEight() { Configure::write('Config.language', 'rule_8_po'); $this->assertRulesEight(); } /** * testMoRulesEight method * * @return void */ public function testMoRulesEight() { Configure::write('Config.language', 'rule_8_mo'); $this->assertRulesEight(); } /** * Run assertions for the eighth plural rule. * * @return void */ public function assertRulesEight() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 8 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 everything else (translated)', $plurals)); $this->assertTrue(in_array('1 is 1 (translated)', $plurals)); $this->assertTrue(in_array('2 is 2-4 (translated)', $plurals)); $this->assertTrue(in_array('3 is 2-4 (translated)', $plurals)); $this->assertTrue(in_array('4 is 2-4 (translated)', $plurals)); $this->assertTrue(in_array('5 everything else (translated)', $plurals)); $this->assertTrue(in_array('6 everything else (translated)', $plurals)); $this->assertTrue(in_array('7 everything else (translated)', $plurals)); $this->assertTrue(in_array('8 everything else (translated)', $plurals)); $this->assertTrue(in_array('9 everything else (translated)', $plurals)); $this->assertTrue(in_array('10 everything else (translated)', $plurals)); $this->assertTrue(in_array('11 everything else (translated)', $plurals)); $this->assertTrue(in_array('12 everything else (translated)', $plurals)); $this->assertTrue(in_array('13 everything else (translated)', $plurals)); $this->assertTrue(in_array('14 everything else (translated)', $plurals)); $this->assertTrue(in_array('15 everything else (translated)', $plurals)); $this->assertTrue(in_array('16 everything else (translated)', $plurals)); $this->assertTrue(in_array('17 everything else (translated)', $plurals)); $this->assertTrue(in_array('18 everything else (translated)', $plurals)); $this->assertTrue(in_array('19 everything else (translated)', $plurals)); $this->assertTrue(in_array('20 everything else (translated)', $plurals)); $this->assertTrue(in_array('21 everything else (translated)', $plurals)); $this->assertTrue(in_array('22 everything else (translated)', $plurals)); $this->assertTrue(in_array('23 everything else (translated)', $plurals)); $this->assertTrue(in_array('24 everything else (translated)', $plurals)); $this->assertTrue(in_array('25 everything else (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 8 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 is 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 is 2-4 (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 is 2-4 (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 is 2-4 (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 everything else (from core translated)', $corePlurals)); } /** * testPoRulesNine method * * @return void */ public function testPoRulesNine() { Configure::write('Config.language', 'rule_9_po'); $this->assertRulesNine(); } /** * testMoRulesNine method * * @return void */ public function testMoRulesNine() { Configure::write('Config.language', 'rule_9_mo'); $this->assertRulesNine(); } /** * Assert plural rules nine * * @return void */ public function assertRulesNine() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 9 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 everything else (translated)', $plurals)); $this->assertTrue(in_array('0 everything else (translated)', $plurals)); $this->assertTrue(in_array('1 is 1 (translated)', $plurals)); $this->assertTrue(in_array('2 ends in 2-4, not 12-14 (translated)', $plurals)); $this->assertTrue(in_array('3 ends in 2-4, not 12-14 (translated)', $plurals)); $this->assertTrue(in_array('4 ends in 2-4, not 12-14 (translated)', $plurals)); $this->assertTrue(in_array('5 everything else (translated)', $plurals)); $this->assertTrue(in_array('6 everything else (translated)', $plurals)); $this->assertTrue(in_array('7 everything else (translated)', $plurals)); $this->assertTrue(in_array('8 everything else (translated)', $plurals)); $this->assertTrue(in_array('9 everything else (translated)', $plurals)); $this->assertTrue(in_array('10 everything else (translated)', $plurals)); $this->assertTrue(in_array('11 everything else (translated)', $plurals)); $this->assertTrue(in_array('12 everything else (translated)', $plurals)); $this->assertTrue(in_array('13 everything else (translated)', $plurals)); $this->assertTrue(in_array('14 everything else (translated)', $plurals)); $this->assertTrue(in_array('15 everything else (translated)', $plurals)); $this->assertTrue(in_array('16 everything else (translated)', $plurals)); $this->assertTrue(in_array('17 everything else (translated)', $plurals)); $this->assertTrue(in_array('18 everything else (translated)', $plurals)); $this->assertTrue(in_array('19 everything else (translated)', $plurals)); $this->assertTrue(in_array('20 everything else (translated)', $plurals)); $this->assertTrue(in_array('21 everything else (translated)', $plurals)); $this->assertTrue(in_array('22 ends in 2-4, not 12-14 (translated)', $plurals)); $this->assertTrue(in_array('23 ends in 2-4, not 12-14 (translated)', $plurals)); $this->assertTrue(in_array('24 ends in 2-4, not 12-14 (translated)', $plurals)); $this->assertTrue(in_array('25 everything else (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 9 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('0 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('0 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 is 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 ends in 2-4, not 12-14 (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 ends in 2-4, not 12-14 (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 ends in 2-4, not 12-14 (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 ends in 2-4, not 12-14 (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 ends in 2-4, not 12-14 (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 ends in 2-4, not 12-14 (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 everything else (from core translated)', $corePlurals)); } /** * testPoRulesTen method * * @return void */ public function testPoRulesTen() { Configure::write('Config.language', 'rule_10_po'); $this->assertRulesTen(); } /** * testMoRulesTen method * * @return void */ public function testMoRulesTen() { Configure::write('Config.language', 'rule_10_mo'); $this->assertRulesTen(); } /** * Assertions for plural rules 10 * * @return void */ public function assertRulesTen() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 10 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 everything else (translated)', $plurals)); $this->assertTrue(in_array('0 everything else (translated)', $plurals)); $this->assertTrue(in_array('1 ends in 1 (translated)', $plurals)); $this->assertTrue(in_array('2 ends in 2 (translated)', $plurals)); $this->assertTrue(in_array('3 ends in 03-04 (translated)', $plurals)); $this->assertTrue(in_array('4 ends in 03-04 (translated)', $plurals)); $this->assertTrue(in_array('5 everything else (translated)', $plurals)); $this->assertTrue(in_array('6 everything else (translated)', $plurals)); $this->assertTrue(in_array('7 everything else (translated)', $plurals)); $this->assertTrue(in_array('8 everything else (translated)', $plurals)); $this->assertTrue(in_array('9 everything else (translated)', $plurals)); $this->assertTrue(in_array('10 everything else (translated)', $plurals)); $this->assertTrue(in_array('11 everything else (translated)', $plurals)); $this->assertTrue(in_array('12 everything else (translated)', $plurals)); $this->assertTrue(in_array('13 everything else (translated)', $plurals)); $this->assertTrue(in_array('14 everything else (translated)', $plurals)); $this->assertTrue(in_array('15 everything else (translated)', $plurals)); $this->assertTrue(in_array('16 everything else (translated)', $plurals)); $this->assertTrue(in_array('17 everything else (translated)', $plurals)); $this->assertTrue(in_array('18 everything else (translated)', $plurals)); $this->assertTrue(in_array('19 everything else (translated)', $plurals)); $this->assertTrue(in_array('20 everything else (translated)', $plurals)); $this->assertTrue(in_array('21 everything else (translated)', $plurals)); $this->assertTrue(in_array('22 everything else (translated)', $plurals)); $this->assertTrue(in_array('23 everything else (translated)', $plurals)); $this->assertTrue(in_array('24 everything else (translated)', $plurals)); $this->assertTrue(in_array('25 everything else (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 10 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('0 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 ends in 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 ends in 2 (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 ends in 03-04 (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 ends in 03-04 (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 everything else (from core translated)', $corePlurals)); } /** * testPoRulesEleven method * * @return void */ public function testPoRulesEleven() { Configure::write('Config.language', 'rule_11_po'); $this->assertRulesEleven(); } /** * testMoRulesEleven method * * @return void */ public function testMoRulesEleven() { Configure::write('Config.language', 'rule_11_mo'); $this->assertRulesEleven(); } /** * Assertions for plural rules eleven * * @return void */ public function assertRulesEleven() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 11 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 everything else (translated)', $plurals)); $this->assertTrue(in_array('1 is 1 (translated)', $plurals)); $this->assertTrue(in_array('2 is 2 (translated)', $plurals)); $this->assertTrue(in_array('3 is 3-6 (translated)', $plurals)); $this->assertTrue(in_array('4 is 3-6 (translated)', $plurals)); $this->assertTrue(in_array('5 is 3-6 (translated)', $plurals)); $this->assertTrue(in_array('6 is 3-6 (translated)', $plurals)); $this->assertTrue(in_array('7 is 7-10 (translated)', $plurals)); $this->assertTrue(in_array('8 is 7-10 (translated)', $plurals)); $this->assertTrue(in_array('9 is 7-10 (translated)', $plurals)); $this->assertTrue(in_array('10 is 7-10 (translated)', $plurals)); $this->assertTrue(in_array('11 everything else (translated)', $plurals)); $this->assertTrue(in_array('12 everything else (translated)', $plurals)); $this->assertTrue(in_array('13 everything else (translated)', $plurals)); $this->assertTrue(in_array('14 everything else (translated)', $plurals)); $this->assertTrue(in_array('15 everything else (translated)', $plurals)); $this->assertTrue(in_array('16 everything else (translated)', $plurals)); $this->assertTrue(in_array('17 everything else (translated)', $plurals)); $this->assertTrue(in_array('18 everything else (translated)', $plurals)); $this->assertTrue(in_array('19 everything else (translated)', $plurals)); $this->assertTrue(in_array('20 everything else (translated)', $plurals)); $this->assertTrue(in_array('21 everything else (translated)', $plurals)); $this->assertTrue(in_array('22 everything else (translated)', $plurals)); $this->assertTrue(in_array('23 everything else (translated)', $plurals)); $this->assertTrue(in_array('24 everything else (translated)', $plurals)); $this->assertTrue(in_array('25 everything else (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 11 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 is 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 is 2 (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 is 3-6 (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 is 3-6 (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 is 3-6 (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 is 3-6 (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 is 7-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 is 7-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 is 7-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 is 7-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 everything else (from core translated)', $corePlurals)); } /** * testPoRulesTwelve method * * @return void */ public function testPoRulesTwelve() { Configure::write('Config.language', 'rule_12_po'); $this->assertRulesTwelve(); } /** * testMoRulesTwelve method * * @return void */ public function testMoRulesTwelve() { Configure::write('Config.language', 'rule_12_mo'); $this->assertRulesTwelve(); } /** * Assertions for plural rules twelve * * @return void */ public function assertRulesTwelve() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 12 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 is 0 or 3-10 (translated)', $plurals)); $this->assertTrue(in_array('1 is 1 (translated)', $plurals)); $this->assertTrue(in_array('2 is 2 (translated)', $plurals)); $this->assertTrue(in_array('3 is 0 or 3-10 (translated)', $plurals)); $this->assertTrue(in_array('4 is 0 or 3-10 (translated)', $plurals)); $this->assertTrue(in_array('5 is 0 or 3-10 (translated)', $plurals)); $this->assertTrue(in_array('6 is 0 or 3-10 (translated)', $plurals)); $this->assertTrue(in_array('7 is 0 or 3-10 (translated)', $plurals)); $this->assertTrue(in_array('8 is 0 or 3-10 (translated)', $plurals)); $this->assertTrue(in_array('9 is 0 or 3-10 (translated)', $plurals)); $this->assertTrue(in_array('10 is 0 or 3-10 (translated)', $plurals)); $this->assertTrue(in_array('11 everything else (translated)', $plurals)); $this->assertTrue(in_array('12 everything else (translated)', $plurals)); $this->assertTrue(in_array('13 everything else (translated)', $plurals)); $this->assertTrue(in_array('14 everything else (translated)', $plurals)); $this->assertTrue(in_array('15 everything else (translated)', $plurals)); $this->assertTrue(in_array('16 everything else (translated)', $plurals)); $this->assertTrue(in_array('17 everything else (translated)', $plurals)); $this->assertTrue(in_array('18 everything else (translated)', $plurals)); $this->assertTrue(in_array('19 everything else (translated)', $plurals)); $this->assertTrue(in_array('20 everything else (translated)', $plurals)); $this->assertTrue(in_array('21 everything else (translated)', $plurals)); $this->assertTrue(in_array('22 everything else (translated)', $plurals)); $this->assertTrue(in_array('23 everything else (translated)', $plurals)); $this->assertTrue(in_array('24 everything else (translated)', $plurals)); $this->assertTrue(in_array('25 everything else (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 12 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 is 0 or 3-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 is 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 is 2 (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 is 0 or 3-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 is 0 or 3-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 is 0 or 3-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 is 0 or 3-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 is 0 or 3-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 is 0 or 3-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 is 0 or 3-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 is 0 or 3-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 everything else (from core translated)', $corePlurals)); } /** * testMoRulesThirteen method * * @return void */ public function testmoRulesThirteen() { Configure::write('Config.language', 'rule_13_mo'); $this->assertRulesThirteen(); } /** * testPoRulesThirteen method * * @return void */ public function testPoRulesThirteen() { Configure::write('Config.language', 'rule_13_po'); $this->assertRulesThirteen(); } /** * Assertions for plural rules thirteen * * @return void */ public function assertRulesThirteen() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 13 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 is 0 or ends in 01-10 (translated)', $plurals)); $this->assertTrue(in_array('1 is 1 (translated)', $plurals)); $this->assertTrue(in_array('2 is 0 or ends in 01-10 (translated)', $plurals)); $this->assertTrue(in_array('3 is 0 or ends in 01-10 (translated)', $plurals)); $this->assertTrue(in_array('4 is 0 or ends in 01-10 (translated)', $plurals)); $this->assertTrue(in_array('5 is 0 or ends in 01-10 (translated)', $plurals)); $this->assertTrue(in_array('6 is 0 or ends in 01-10 (translated)', $plurals)); $this->assertTrue(in_array('7 is 0 or ends in 01-10 (translated)', $plurals)); $this->assertTrue(in_array('8 is 0 or ends in 01-10 (translated)', $plurals)); $this->assertTrue(in_array('9 is 0 or ends in 01-10 (translated)', $plurals)); $this->assertTrue(in_array('10 is 0 or ends in 01-10 (translated)', $plurals)); $this->assertTrue(in_array('11 ends in 11-20 (translated)', $plurals)); $this->assertTrue(in_array('12 ends in 11-20 (translated)', $plurals)); $this->assertTrue(in_array('13 ends in 11-20 (translated)', $plurals)); $this->assertTrue(in_array('14 ends in 11-20 (translated)', $plurals)); $this->assertTrue(in_array('15 ends in 11-20 (translated)', $plurals)); $this->assertTrue(in_array('16 ends in 11-20 (translated)', $plurals)); $this->assertTrue(in_array('17 ends in 11-20 (translated)', $plurals)); $this->assertTrue(in_array('18 ends in 11-20 (translated)', $plurals)); $this->assertTrue(in_array('19 ends in 11-20 (translated)', $plurals)); $this->assertTrue(in_array('20 ends in 11-20 (translated)', $plurals)); $this->assertTrue(in_array('21 everything else (translated)', $plurals)); $this->assertTrue(in_array('22 everything else (translated)', $plurals)); $this->assertTrue(in_array('23 everything else (translated)', $plurals)); $this->assertTrue(in_array('24 everything else (translated)', $plurals)); $this->assertTrue(in_array('25 everything else (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 13 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 is 0 or ends in 01-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 is 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 is 0 or ends in 01-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 is 0 or ends in 01-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 is 0 or ends in 01-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 is 0 or ends in 01-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 is 0 or ends in 01-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 is 0 or ends in 01-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 is 0 or ends in 01-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 is 0 or ends in 01-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 is 0 or ends in 01-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 ends in 11-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 ends in 11-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 ends in 11-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 ends in 11-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 ends in 11-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 ends in 11-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 ends in 11-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 ends in 11-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 ends in 11-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 ends in 11-20 (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 everything else (from core translated)', $corePlurals)); } /** * testMoRulesFourteen method * * @return void */ public function testMoRulesFourteen() { Configure::write('Config.language', 'rule_14_mo'); $this->assertRulesFourteen(); } /** * testPoRulesFourteen method * * @return void */ public function testPoRulesFourteen() { Configure::write('Config.language', 'rule_14_po'); $this->assertRulesFourteen(); } /** * Assertions for plural rules fourteen * * @return void */ public function assertRulesFourteen() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 14 (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 everything else (translated)', $plurals)); $this->assertTrue(in_array('1 ends in 1 (translated)', $plurals)); $this->assertTrue(in_array('2 ends in 2 (translated)', $plurals)); $this->assertTrue(in_array('3 everything else (translated)', $plurals)); $this->assertTrue(in_array('4 everything else (translated)', $plurals)); $this->assertTrue(in_array('5 everything else (translated)', $plurals)); $this->assertTrue(in_array('6 everything else (translated)', $plurals)); $this->assertTrue(in_array('7 everything else (translated)', $plurals)); $this->assertTrue(in_array('8 everything else (translated)', $plurals)); $this->assertTrue(in_array('9 everything else (translated)', $plurals)); $this->assertTrue(in_array('10 everything else (translated)', $plurals)); $this->assertTrue(in_array('11 ends in 1 (translated)', $plurals)); $this->assertTrue(in_array('12 ends in 2 (translated)', $plurals)); $this->assertTrue(in_array('13 everything else (translated)', $plurals)); $this->assertTrue(in_array('14 everything else (translated)', $plurals)); $this->assertTrue(in_array('15 everything else (translated)', $plurals)); $this->assertTrue(in_array('16 everything else (translated)', $plurals)); $this->assertTrue(in_array('17 everything else (translated)', $plurals)); $this->assertTrue(in_array('18 everything else (translated)', $plurals)); $this->assertTrue(in_array('19 everything else (translated)', $plurals)); $this->assertTrue(in_array('20 everything else (translated)', $plurals)); $this->assertTrue(in_array('21 ends in 1 (translated)', $plurals)); $this->assertTrue(in_array('22 ends in 2 (translated)', $plurals)); $this->assertTrue(in_array('23 everything else (translated)', $plurals)); $this->assertTrue(in_array('24 everything else (translated)', $plurals)); $this->assertTrue(in_array('25 everything else (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 14 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertTrue(in_array('0 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 ends in 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 ends in 2 (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 ends in 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 ends in 2 (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('21 ends in 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('22 ends in 2 (from core translated)', $corePlurals)); $this->assertTrue(in_array('23 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('24 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('25 everything else (from core translated)', $corePlurals)); } /** * testMoRulesFifteen method * * @return void */ public function testMoRulesFifteen() { Configure::write('Config.language', 'rule_15_mo'); $this->assertRulesFifteen(); } /** * testPoRulesFifteen method * * @return void */ public function testPoRulesFifteen() { Configure::write('Config.language', 'rule_15_po'); $this->assertRulesFifteen(); } /** * Assertions for plural rules fifteen * * @return void */ public function assertRulesFifteen() { $singular = $this->_singular(); $this->assertEquals('Plural Rule 15 (translated)', $singular); $plurals = $this->_plural(111); $this->assertTrue(in_array('0 is 0 (translated)', $plurals)); $this->assertTrue(in_array('1 is 1 (translated)', $plurals)); $this->assertTrue(in_array('2 is 2 (translated)', $plurals)); $this->assertTrue(in_array('3 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('4 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('5 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('6 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('7 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('8 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('9 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('10 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('11 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('12 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('13 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('14 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('15 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('16 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('17 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('18 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('19 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('20 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('31 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('42 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('53 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('64 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('75 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('86 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('97 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('98 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('99 ends with 11-99 (translated)', $plurals)); $this->assertTrue(in_array('100 everything else (translated)', $plurals)); $this->assertTrue(in_array('101 everything else (translated)', $plurals)); $this->assertTrue(in_array('102 everything else (translated)', $plurals)); $this->assertTrue(in_array('103 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('104 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('105 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('106 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('107 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('108 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('109 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('110 ends with 03-10 (translated)', $plurals)); $this->assertTrue(in_array('111 ends with 11-99 (translated)', $plurals)); $coreSingular = $this->_singularFromCore(); $this->assertEquals('Plural Rule 15 (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(111); $this->assertTrue(in_array('0 is 0 (from core translated)', $corePlurals)); $this->assertTrue(in_array('1 is 1 (from core translated)', $corePlurals)); $this->assertTrue(in_array('2 is 2 (from core translated)', $corePlurals)); $this->assertTrue(in_array('3 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('4 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('5 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('6 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('7 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('8 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('9 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('10 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('11 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('12 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('13 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('14 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('15 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('16 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('17 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('18 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('19 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('20 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('31 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('42 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('53 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('64 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('75 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('86 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('97 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('98 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('99 ends with 11-99 (from core translated)', $corePlurals)); $this->assertTrue(in_array('100 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('101 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('102 everything else (from core translated)', $corePlurals)); $this->assertTrue(in_array('103 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('104 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('105 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('106 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('107 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('108 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('109 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('110 ends with 03-10 (from core translated)', $corePlurals)); $this->assertTrue(in_array('111 ends with 11-99 (from core translated)', $corePlurals)); } /** * testSetLanguageWithSession method * * @return void */ public function testSetLanguageWithSession() { CakeSession::write('Config.language', 'po'); $singular = $this->_singular(); $this->assertEquals('Po (translated)', $singular); $plurals = $this->_plural(); $this->assertTrue(in_array('0 everything else (po translated)', $plurals)); $this->assertTrue(in_array('1 is 1 (po translated)', $plurals)); $this->assertTrue(in_array('2 is 2-4 (po translated)', $plurals)); $this->assertTrue(in_array('3 is 2-4 (po translated)', $plurals)); $this->assertTrue(in_array('4 is 2-4 (po translated)', $plurals)); $this->assertTrue(in_array('5 everything else (po translated)', $plurals)); $this->assertTrue(in_array('6 everything else (po translated)', $plurals)); $this->assertTrue(in_array('7 everything else (po translated)', $plurals)); $this->assertTrue(in_array('8 everything else (po translated)', $plurals)); $this->assertTrue(in_array('9 everything else (po translated)', $plurals)); $this->assertTrue(in_array('10 everything else (po translated)', $plurals)); $this->assertTrue(in_array('11 everything else (po translated)', $plurals)); $this->assertTrue(in_array('12 everything else (po translated)', $plurals)); $this->assertTrue(in_array('13 everything else (po translated)', $plurals)); $this->assertTrue(in_array('14 everything else (po translated)', $plurals)); $this->assertTrue(in_array('15 everything else (po translated)', $plurals)); $this->assertTrue(in_array('16 everything else (po translated)', $plurals)); $this->assertTrue(in_array('17 everything else (po translated)', $plurals)); $this->assertTrue(in_array('18 everything else (po translated)', $plurals)); $this->assertTrue(in_array('19 everything else (po translated)', $plurals)); $this->assertTrue(in_array('20 everything else (po translated)', $plurals)); $this->assertTrue(in_array('21 everything else (po translated)', $plurals)); $this->assertTrue(in_array('22 everything else (po translated)', $plurals)); $this->assertTrue(in_array('23 everything else (po translated)', $plurals)); $this->assertTrue(in_array('24 everything else (po translated)', $plurals)); $this->assertTrue(in_array('25 everything else (po translated)', $plurals)); CakeSession::delete('Config.language'); } /** * testNoCoreTranslation method * * @return void */ public function testNoCoreTranslation() { Configure::write('Config.language', 'po'); $singular = $this->_singular(); $this->assertEquals('Po (translated)', $singular); $coreSingular = $this->_singularFromCore(); $this->assertNotEquals('Po (from core translated)', $coreSingular); $corePlurals = $this->_pluralFromCore(); $this->assertFalse(in_array('0 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('1 is 1 (from core translated)', $corePlurals)); $this->assertFalse(in_array('2 is 2-4 (from core translated)', $corePlurals)); $this->assertFalse(in_array('3 is 2-4 (from core translated)', $corePlurals)); $this->assertFalse(in_array('4 is 2-4 (from core translated)', $corePlurals)); $this->assertFalse(in_array('5 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('6 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('7 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('8 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('9 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('10 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('11 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('12 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('13 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('14 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('15 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('16 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('17 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('18 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('19 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('20 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('21 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('22 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('23 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('24 everything else (from core translated)', $corePlurals)); $this->assertFalse(in_array('25 everything else (from core translated)', $corePlurals)); } /** * testPluginTranslation method * * @return void */ public function testPluginTranslation() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); Configure::write('Config.language', 'po'); $singular = $this->_domainSingular(); $this->assertEquals('Plural Rule 1 (from plugin)', $singular); $plurals = $this->_domainPlural(); $this->assertTrue(in_array('0 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('1 = 1 (from plugin)', $plurals)); $this->assertTrue(in_array('2 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('3 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('4 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('5 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('6 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('7 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('8 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('9 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('10 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('11 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('12 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('13 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('14 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('15 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('16 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('17 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('18 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('19 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('20 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('21 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('22 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('23 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('24 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('25 = 0 or > 1 (from plugin)', $plurals)); } /** * Test that Configure::read('I18n.preferApp') will prefer app. * * @return void */ public function testPluginTranslationPreferApp() { // Reset internally stored entries I18n::clear(); Cache::clear(false, '_cake_core_'); Configure::write('I18n.preferApp', true); App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); Configure::write('Config.language', 'po'); $singular = $this->_domainSingular(); $this->assertEquals('Plural Rule 1', $singular); $plurals = $this->_domainPlural(); $this->assertTrue(in_array('0 = 0 or > 1', $plurals)); } /** * testPoMultipleLineTranslation method * * @return void */ public function testPoMultipleLineTranslation() { Configure::write('Config.language', 'po'); $string = "This is a multiline translation\n"; $string .= "broken up over multiple lines.\n"; $string .= "This is the third line.\n"; $string .= "This is the forth line."; $result = __($string); $expected = "This is a multiline translation\n"; $expected .= "broken up over multiple lines.\n"; $expected .= "This is the third line.\n"; $expected .= "This is the forth line. (translated)"; $this->assertEquals($expected, $result); // Windows Newline is \r\n $string = "This is a multiline translation\r\n"; $string .= "broken up over multiple lines.\r\n"; $string .= "This is the third line.\r\n"; $string .= "This is the forth line."; $result = __($string); $this->assertEquals($expected, $result); $singular = "valid\nsecond line"; $plural = "valids\nsecond line"; $result = __n($singular, $plural, 1); $expected = "v\nsecond line"; $this->assertEquals($expected, $result); $result = __n($singular, $plural, 2); $expected = "vs\nsecond line"; $this->assertEquals($expected, $result); $string = "This is a multiline translation\n"; $string .= "broken up over multiple lines.\n"; $string .= "This is the third line.\n"; $string .= "This is the forth line."; $singular = "%d = 1\n" . $string; $plural = "%d = 0 or > 1\n" . $string; $result = __n($singular, $plural, 1); $expected = "%d is 1\n" . $string; $this->assertEquals($expected, $result); $result = __n($singular, $plural, 2); $expected = "%d is 2-4\n" . $string; $this->assertEquals($expected, $result); // Windows Newline is \r\n $string = "This is a multiline translation\r\n"; $string .= "broken up over multiple lines.\r\n"; $string .= "This is the third line.\r\n"; $string .= "This is the forth line."; $singular = "%d = 1\r\n" . $string; $plural = "%d = 0 or > 1\r\n" . $string; $result = __n($singular, $plural, 1); $expected = "%d is 1\n" . str_replace("\r\n", "\n", $string); $this->assertEquals($expected, $result); $result = __n($singular, $plural, 2); $expected = "%d is 2-4\n" . str_replace("\r\n", "\n", $string); $this->assertEquals($expected, $result); } /** * testPoNoTranslationNeeded method * * @return void */ public function testPoNoTranslationNeeded() { Configure::write('Config.language', 'po'); $result = __('No Translation needed'); $this->assertEquals('No Translation needed', $result); } /** * testPoQuotedString method * * @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"')); } /** * testFloatValue method * * @return void */ public function testFloatValue() { Configure::write('Config.language', 'rule_9_po'); $result = __n('%d = 1', '%d = 0 or > 1', (float)1); $expected = '%d is 1 (translated)'; $this->assertEquals($expected, $result); $result = __n('%d = 1', '%d = 0 or > 1', (float)2); $expected = "%d ends in 2-4, not 12-14 (translated)"; $this->assertEquals($expected, $result); $result = __n('%d = 1', '%d = 0 or > 1', (float)5); $expected = "%d everything else (translated)"; $this->assertEquals($expected, $result); } /** * testCategory method * * @return void */ public function testCategory() { Configure::write('Config.language', 'po'); // Test with default (I18n constant) category. $category = $this->_category(); $this->assertEquals('Monetary Po (translated)', $category); // Test with category number represenation. $category = $this->_category(3); $this->assertEquals('Monetary Po (translated)', $category); } /** * testPluginCategory method * * @return void */ public function testPluginCategory() { Configure::write('Config.language', 'po'); $singular = $this->_domainCategorySingular(); $this->assertEquals('Monetary Plural Rule 1 (from plugin)', $singular); $plurals = $this->_domainCategoryPlural(); $this->assertTrue(in_array('Monetary 0 = 0 or > 1 (from plugin)', $plurals)); $this->assertTrue(in_array('Monetary 1 = 1 (from plugin)', $plurals)); } /** * testCategoryThenSingular method * * @return void */ public function testCategoryThenSingular() { Configure::write('Config.language', 'po'); $category = $this->_category(); $this->assertEquals('Monetary Po (translated)', $category); $singular = $this->_singular(); $this->assertEquals('Po (translated)', $singular); } /** * testTimeDefinition method * * @return void */ public function testTimeDefinition() { Configure::write('Config.language', 'po'); $result = __c('d_fmt', 5); $expected = '%m/%d/%Y'; $this->assertEquals($expected, $result); $result = __c('am_pm', 5); $expected = array('AM', 'PM'); $this->assertEquals($expected, $result); $result = __c('abmon', 5); $expected = array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'); $this->assertEquals($expected, $result); } /** * testTimeDefinitionJapanese method * * @return void */ public function testTimeDefinitionJapanese() { Configure::write('Config.language', 'ja_jp'); $result = __c('d_fmt', 5); $expected = "%Yๅนด%mๆœˆ%dๆ—ฅ"; $this->assertEquals($expected, $result); $result = __c('am_pm', 5); $expected = array("ๅˆๅ‰", "ๅˆๅพŒ"); $this->assertEquals($expected, $result); $result = __c('abmon', 5); $expected = array(" 1ๆœˆ", " 2ๆœˆ", " 3ๆœˆ", " 4ๆœˆ", " 5ๆœˆ", " 6ๆœˆ", " 7ๆœˆ", " 8ๆœˆ", " 9ๆœˆ", "10ๆœˆ", "11ๆœˆ", "12ๆœˆ"); $this->assertEquals($expected, $result); } /** * testTranslateLanguageParam method * * @return void */ public function testTranslateLanguageParam() { Configure::write('Config.language', 'rule_0_po'); $result = I18n::translate('Plural Rule 1', null, null, I18n::LC_MESSAGES); $expected = 'Plural Rule 0 (translated)'; $this->assertEquals($expected, $result); $result = I18n::translate('Plural Rule 1', null, null, I18n::LC_MESSAGES, null, 'rule_1_po'); $expected = 'Plural Rule 1 (translated)'; $this->assertEquals($expected, $result); } /** * Test that the '' domain causes exceptions. * * @expectedException CakeException * @return void */ public function testTranslateEmptyDomain() { I18n::translate('Plural Rule 1', null, ''); } /** * testLoadLocaleDefinition method * * @return void */ public function testLoadLocaleDefinition() { $path = current(App::path('locales')); $result = I18n::loadLocaleDefinition($path . 'nld' . DS . 'LC_TIME'); $expected = array('zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'); $this->assertSame($expected, $result['day']); } /** * Test basic context support * * @return void */ public function testContext() { Configure::write('Config.language', 'nld'); $this->assertSame("brief", __x('mail', 'letter')); $this->assertSame("letter", __x('character', 'letter')); $this->assertSame("bal", __x('spherical object', 'ball')); $this->assertSame("danspartij", __x('social gathering', 'ball')); $this->assertSame("balans", __('balance')); $this->assertSame("saldo", __x('money', 'balance')); } /** * Test basic context support using mo files. * * @return void */ public function testContextMoFile() { Configure::write('Config.language', 'nld_mo'); $this->assertSame("brief", __x('mail', 'letter')); $this->assertSame("letter", __x('character', 'letter')); $this->assertSame("bal", __x('spherical object', 'ball')); $this->assertSame("danspartij", __x('social gathering', 'ball')); $this->assertSame("balans", __('balance')); $this->assertSame("saldo", __x('money', 'balance')); // MO file is sorted by msgid, 'zoo' should be last $this->assertSame("dierentuin", __('zoo')); } /** * Singular method * * @return void */ protected function _domainCategorySingular($domain = 'test_plugin', $category = 3) { $singular = __dc($domain, 'Plural Rule 1', $category); return $singular; } /** * Plural method * * @return void */ protected function _domainCategoryPlural($domain = 'test_plugin', $category = 3) { $plurals = array(); for ($number = 0; $number <= 25; $number++) { $plurals[] = sprintf(__dcn($domain, '%d = 1', '%d = 0 or > 1', (float)$number, $category), (float)$number); } return $plurals; } /** * Singular method * * @return void */ protected function _domainSingular($domain = 'test_plugin') { $singular = __d($domain, 'Plural Rule 1'); return $singular; } /** * Plural method * * @return void */ protected function _domainPlural($domain = 'test_plugin') { $plurals = array(); for ($number = 0; $number <= 25; $number++) { $plurals[] = sprintf(__dn($domain, '%d = 1', '%d = 0 or > 1', (float)$number), (float)$number); } return $plurals; } /** * category method * * @return void */ protected function _category($category = I18n::LC_MONETARY) { $singular = __c('Plural Rule 1', $category); return $singular; } /** * Singular method * * @return void */ protected function _singular() { $singular = __('Plural Rule 1'); return $singular; } /** * Plural method * * @param int $upTo For numbers upto (default to 25) * @return void */ protected function _plural($upTo = 25) { $plurals = array(); for ($number = 0; $number <= $upTo; $number++) { $plurals[] = sprintf(__n('%d = 1', '%d = 0 or > 1', (float)$number), (float)$number); } return $plurals; } /** * singularFromCore method * * @return void */ protected function _singularFromCore() { $singular = __('Plural Rule 1 (from core)'); return $singular; } /** * pluralFromCore method * * @param int $upTo For numbers upto (default to 25) * @return void */ protected function _pluralFromCore($upTo = 25) { $plurals = array(); for ($number = 0; $number <= $upTo; $number++) { $plurals[] = sprintf(__n('%d = 1 (from core)', '%d = 0 or > 1 (from core)', (float)$number), (float)$number); } return $plurals; } } cakephp-2.8.0/lib/Cake/Test/Case/I18n/L10nTest.php000066400000000000000000001317121265552240500211540ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.I18n * @since CakePHP(tm) v 1.2.0.5432 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('L10n', 'I18n'); /** * L10nTest class * * @package Cake.Test.Case.I18n */ class L10nTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); Configure::delete('Config.language'); } /** * testGet method * * @return void */ public function testGet() { $localize = new L10n(); // Catalog Entry $lang = $localize->get('en'); $this->assertEquals('en', $lang); $this->assertEquals('English', $localize->language); $this->assertEquals(array('eng'), $localize->languagePath); $this->assertEquals('eng', $localize->locale); // Map Entry $localize->get('eng'); $this->assertEquals('English', $localize->language); $this->assertEquals(array('eng'), $localize->languagePath); $this->assertEquals('eng', $localize->locale); // Catalog Entry $localize->get('en-ca'); $this->assertEquals('English (Canadian)', $localize->language); $this->assertEquals(array('en_ca', 'eng'), $localize->languagePath); $this->assertEquals('en_ca', $localize->locale); // Default Entry $localize->default = 'en-us'; $lang = $localize->get('use_default'); $this->assertEquals('en-us', $lang); $this->assertEquals('English (United States)', $localize->language); $this->assertEquals(array('en_us', 'eng'), $localize->languagePath); $this->assertEquals('en_us', $localize->locale); $localize->get('es'); $localize->get(''); $this->assertEquals('en-us', $localize->lang); } /** * testGetAutoLanguage method * * @return void */ public function testGetAutoLanguage() { $serverBackup = $_SERVER; $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'inexistent,en-ca'; $localize = new L10n(); $lang = $localize->get(); $this->assertEquals('en-ca', $lang); $this->assertEquals('English (Canadian)', $localize->language); $this->assertEquals(array('en_ca', 'eng'), $localize->languagePath); $this->assertEquals('en_ca', $localize->locale); $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'es_mx'; $lang = $localize->get(); $this->assertEquals('es-mx', $lang); $this->assertEquals('Spanish (Mexican)', $localize->language); $this->assertEquals(array('es_mx', 'spa'), $localize->languagePath); $this->assertEquals('es_mx', $localize->locale); $localize = new L10n(); $localize->default = 'en-us'; $lang = $localize->get(); $this->assertEquals(array('es_mx', 'spa', 'eng'), $localize->languagePath); $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'en_xy,en_ca'; $localize->get(); $this->assertEquals('English', $localize->language); $this->assertEquals(array('eng'), $localize->languagePath); $this->assertEquals('eng', $localize->locale); $_SERVER = $serverBackup; } /** * testGet method with deprecated constant DEFAULT_LANGUAGE * * @return void */ public function testGetWithDeprecatedConstant() { $this->skipIf(defined('DEFAULT_LANGUAGE'), 'Cannot re-define already defined constant.'); define('DEFAULT_LANGUAGE', 'en-us'); $localize = new L10n(); $lang = $localize->get('use_default'); $this->assertEquals('en-us', $lang); $this->assertEquals('English (United States)', $localize->language); $this->assertEquals(array('en_us', 'eng'), $localize->languagePath); $this->assertEquals('en_us', $localize->locale); $localize = new L10n(); $lang = $localize->get(); $this->assertEquals('en-us', $lang); $this->assertEquals('English (United States)', $localize->language); $this->assertEquals(array('en_us', 'eng'), $localize->languagePath); $this->assertEquals('en_us', $localize->locale); } /** * testMap method * * @return void */ public function testMap() { $localize = new L10n(); $result = $localize->map(array('afr', 'af')); $expected = array('afr' => 'af', 'af' => 'afr'); $this->assertEquals($expected, $result); $result = $localize->map(array('sqi', 'sq')); $expected = array('sqi' => 'sq', 'sq' => 'sqi'); $this->assertEquals($expected, $result); $result = $localize->map(array('alb', 'sq')); $expected = array('alb' => 'sq', 'sq' => 'sqi'); $this->assertEquals($expected, $result); $result = $localize->map(array('ara', 'ar')); $expected = array('ara' => 'ar', 'ar' => 'ara'); $this->assertEquals($expected, $result); $result = $localize->map(array('hye', 'hy')); $expected = array('hye' => 'hy', 'hy' => 'hye'); $this->assertEquals($expected, $result); $result = $localize->map(array('eus', 'eu')); $expected = array('eus' => 'eu', 'eu' => 'eus'); $this->assertEquals($expected, $result); $result = $localize->map(array('baq', 'eu')); $expected = array('baq' => 'eu', 'eu' => 'eus'); $this->assertEquals($expected, $result); $result = $localize->map(array('bos', 'bs')); $expected = array('bos' => 'bs', 'bs' => 'bos'); $this->assertEquals($expected, $result); $result = $localize->map(array('bul', 'bg')); $expected = array('bul' => 'bg', 'bg' => 'bul'); $this->assertEquals($expected, $result); $result = $localize->map(array('bel', 'be')); $expected = array('bel' => 'be', 'be' => 'bel'); $this->assertEquals($expected, $result); $result = $localize->map(array('cat', 'ca')); $expected = array('cat' => 'ca', 'ca' => 'cat'); $this->assertEquals($expected, $result); $result = $localize->map(array('chi', 'zh')); $expected = array('chi' => 'zh', 'zh' => 'zho'); $this->assertEquals($expected, $result); $result = $localize->map(array('zho', 'zh')); $expected = array('zho' => 'zh', 'zh' => 'zho'); $this->assertEquals($expected, $result); $result = $localize->map(array('hrv', 'hr')); $expected = array('hrv' => 'hr', 'hr' => 'hrv'); $this->assertEquals($expected, $result); $result = $localize->map(array('ces', 'cs')); $expected = array('ces' => 'cs', 'cs' => 'ces'); $this->assertEquals($expected, $result); $result = $localize->map(array('cze', 'cs')); $expected = array('cze' => 'cs', 'cs' => 'ces'); $this->assertEquals($expected, $result); $result = $localize->map(array('dan', 'da')); $expected = array('dan' => 'da', 'da' => 'dan'); $this->assertEquals($expected, $result); $result = $localize->map(array('dut', 'nl')); $expected = array('dut' => 'nl', 'nl' => 'nld'); $this->assertEquals($expected, $result); $result = $localize->map(array('nld', 'nl')); $expected = array('nld' => 'nl', 'nl' => 'nld'); $this->assertEquals($expected, $result); $result = $localize->map(array('nld')); $expected = array('nld' => 'nl'); $this->assertEquals($expected, $result); $result = $localize->map(array('dut')); $expected = array('dut' => 'nl'); $this->assertEquals($expected, $result); $result = $localize->map(array('eng', 'en')); $expected = array('eng' => 'en', 'en' => 'eng'); $this->assertEquals($expected, $result); $result = $localize->map(array('est', 'et')); $expected = array('est' => 'et', 'et' => 'est'); $this->assertEquals($expected, $result); $result = $localize->map(array('fao', 'fo')); $expected = array('fao' => 'fo', 'fo' => 'fao'); $this->assertEquals($expected, $result); $result = $localize->map(array('fas', 'fa')); $expected = array('fas' => 'fa', 'fa' => 'fas'); $this->assertEquals($expected, $result); $result = $localize->map(array('per', 'fa')); $expected = array('per' => 'fa', 'fa' => 'fas'); $this->assertEquals($expected, $result); $result = $localize->map(array('fin', 'fi')); $expected = array('fin' => 'fi', 'fi' => 'fin'); $this->assertEquals($expected, $result); $result = $localize->map(array('fra', 'fr')); $expected = array('fra' => 'fr', 'fr' => 'fra'); $this->assertEquals($expected, $result); $result = $localize->map(array('fre', 'fr')); $expected = array('fre' => 'fr', 'fr' => 'fra'); $this->assertEquals($expected, $result); $result = $localize->map(array('gla', 'gd')); $expected = array('gla' => 'gd', 'gd' => 'gla'); $this->assertEquals($expected, $result); $result = $localize->map(array('glg', 'gl')); $expected = array('glg' => 'gl', 'gl' => 'glg'); $this->assertEquals($expected, $result); $result = $localize->map(array('deu', 'de')); $expected = array('deu' => 'de', 'de' => 'deu'); $this->assertEquals($expected, $result); $result = $localize->map(array('ger', 'de')); $expected = array('ger' => 'de', 'de' => 'deu'); $this->assertEquals($expected, $result); $result = $localize->map(array('ell', 'el')); $expected = array('ell' => 'el', 'el' => 'gre'); $this->assertEquals($expected, $result); $result = $localize->map(array('gre', 'el')); $expected = array('gre' => 'el', 'el' => 'gre'); $this->assertEquals($expected, $result); $result = $localize->map(array('heb', 'he')); $expected = array('heb' => 'he', 'he' => 'heb'); $this->assertEquals($expected, $result); $result = $localize->map(array('hin', 'hi')); $expected = array('hin' => 'hi', 'hi' => 'hin'); $this->assertEquals($expected, $result); $result = $localize->map(array('hun', 'hu')); $expected = array('hun' => 'hu', 'hu' => 'hun'); $this->assertEquals($expected, $result); $result = $localize->map(array('ice', 'is')); $expected = array('ice' => 'is', 'is' => 'isl'); $this->assertEquals($expected, $result); $result = $localize->map(array('isl', 'is')); $expected = array('isl' => 'is', 'is' => 'isl'); $this->assertEquals($expected, $result); $result = $localize->map(array('ind', 'id')); $expected = array('ind' => 'id', 'id' => 'ind'); $this->assertEquals($expected, $result); $result = $localize->map(array('gle', 'ga')); $expected = array('gle' => 'ga', 'ga' => 'gle'); $this->assertEquals($expected, $result); $result = $localize->map(array('ita', 'it')); $expected = array('ita' => 'it', 'it' => 'ita'); $this->assertEquals($expected, $result); $result = $localize->map(array('jpn', 'ja')); $expected = array('jpn' => 'ja', 'ja' => 'jpn'); $this->assertEquals($expected, $result); $result = $localize->map(array('kaz', 'kk')); $expected = array('kaz' => 'kk', 'kk' => 'kaz'); $this->assertEquals($expected, $result); $result = $localize->map(array('kor', 'ko')); $expected = array('kor' => 'ko', 'ko' => 'kor'); $this->assertEquals($expected, $result); $result = $localize->map(array('lav', 'lv')); $expected = array('lav' => 'lv', 'lv' => 'lav'); $this->assertEquals($expected, $result); $result = $localize->map(array('lit', 'lt')); $expected = array('lit' => 'lt', 'lt' => 'lit'); $this->assertEquals($expected, $result); $result = $localize->map(array('mac', 'mk')); $expected = array('mac' => 'mk', 'mk' => 'mkd'); $this->assertEquals($expected, $result); $result = $localize->map(array('mkd', 'mk')); $expected = array('mkd' => 'mk', 'mk' => 'mkd'); $this->assertEquals($expected, $result); $result = $localize->map(array('may', 'ms')); $expected = array('may' => 'ms', 'ms' => 'msa'); $this->assertEquals($expected, $result); $result = $localize->map(array('msa', 'ms')); $expected = array('msa' => 'ms', 'ms' => 'msa'); $this->assertEquals($expected, $result); $result = $localize->map(array('mlt', 'mt')); $expected = array('mlt' => 'mt', 'mt' => 'mlt'); $this->assertEquals($expected, $result); $result = $localize->map(array('nor', 'no')); $expected = array('nor' => 'no', 'no' => 'nor'); $this->assertEquals($expected, $result); $result = $localize->map(array('nob', 'nb')); $expected = array('nob' => 'nb', 'nb' => 'nob'); $this->assertEquals($expected, $result); $result = $localize->map(array('nno', 'nn')); $expected = array('nno' => 'nn', 'nn' => 'nno'); $this->assertEquals($expected, $result); $result = $localize->map(array('pol', 'pl')); $expected = array('pol' => 'pl', 'pl' => 'pol'); $this->assertEquals($expected, $result); $result = $localize->map(array('por', 'pt')); $expected = array('por' => 'pt', 'pt' => 'por'); $this->assertEquals($expected, $result); $result = $localize->map(array('roh', 'rm')); $expected = array('roh' => 'rm', 'rm' => 'roh'); $this->assertEquals($expected, $result); $result = $localize->map(array('ron', 'ro')); $expected = array('ron' => 'ro', 'ro' => 'ron'); $this->assertEquals($expected, $result); $result = $localize->map(array('rum', 'ro')); $expected = array('rum' => 'ro', 'ro' => 'ron'); $this->assertEquals($expected, $result); $result = $localize->map(array('rus', 'ru')); $expected = array('rus' => 'ru', 'ru' => 'rus'); $this->assertEquals($expected, $result); $result = $localize->map(array('sme', 'se')); $expected = array('sme' => 'se', 'se' => 'sme'); $this->assertEquals($expected, $result); $result = $localize->map(array('srp', 'sr')); $expected = array('srp' => 'sr', 'sr' => 'srp'); $this->assertEquals($expected, $result); $result = $localize->map(array('slk', 'sk')); $expected = array('slk' => 'sk', 'sk' => 'slk'); $this->assertEquals($expected, $result); $result = $localize->map(array('slo', 'sk')); $expected = array('slo' => 'sk', 'sk' => 'slk'); $this->assertEquals($expected, $result); $result = $localize->map(array('slv', 'sl')); $expected = array('slv' => 'sl', 'sl' => 'slv'); $this->assertEquals($expected, $result); $result = $localize->map(array('wen', 'sb')); $expected = array('wen' => 'sb', 'sb' => 'wen'); $this->assertEquals($expected, $result); $result = $localize->map(array('spa', 'es')); $expected = array('spa' => 'es', 'es' => 'spa'); $this->assertEquals($expected, $result); $result = $localize->map(array('swe', 'sv')); $expected = array('swe' => 'sv', 'sv' => 'swe'); $this->assertEquals($expected, $result); $result = $localize->map(array('tha', 'th')); $expected = array('tha' => 'th', 'th' => 'tha'); $this->assertEquals($expected, $result); $result = $localize->map(array('tso', 'ts')); $expected = array('tso' => 'ts', 'ts' => 'tso'); $this->assertEquals($expected, $result); $result = $localize->map(array('tsn', 'tn')); $expected = array('tsn' => 'tn', 'tn' => 'tsn'); $this->assertEquals($expected, $result); $result = $localize->map(array('tur', 'tr')); $expected = array('tur' => 'tr', 'tr' => 'tur'); $this->assertEquals($expected, $result); $result = $localize->map(array('ukr', 'uk')); $expected = array('ukr' => 'uk', 'uk' => 'ukr'); $this->assertEquals($expected, $result); $result = $localize->map(array('urd', 'ur')); $expected = array('urd' => 'ur', 'ur' => 'urd'); $this->assertEquals($expected, $result); $result = $localize->map(array('ven', 've')); $expected = array('ven' => 've', 've' => 'ven'); $this->assertEquals($expected, $result); $result = $localize->map(array('vie', 'vi')); $expected = array('vie' => 'vi', 'vi' => 'vie'); $this->assertEquals($expected, $result); $result = $localize->map(array('xho', 'xh')); $expected = array('xho' => 'xh', 'xh' => 'xho'); $this->assertEquals($expected, $result); $result = $localize->map(array('cy', 'cym')); $expected = array('cym' => 'cy', 'cy' => 'cym'); $this->assertEquals($expected, $result); $result = $localize->map(array('yid', 'yi')); $expected = array('yid' => 'yi', 'yi' => 'yid'); $this->assertEquals($expected, $result); $result = $localize->map(array('zul', 'zu')); $expected = array('zul' => 'zu', 'zu' => 'zul'); $this->assertEquals($expected, $result); } /** * testCatalog method * * @return void */ public function testCatalog() { $localize = new L10n(); $result = $localize->catalog(array('af')); $expected = array( 'af' => array('language' => 'Afrikaans', 'locale' => 'afr', 'localeFallback' => 'afr', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('ar', 'ar-ae', 'ar-bh', 'ar-dz', 'ar-eg', 'ar-iq', 'ar-jo', 'ar-kw', 'ar-lb', 'ar-ly', 'ar-ma', 'ar-om', 'ar-qa', 'ar-sa', 'ar-sy', 'ar-tn', 'ar-ye')); $expected = array( 'ar' => array('language' => 'Arabic', 'locale' => 'ara', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-ae' => array('language' => 'Arabic (U.A.E.)', 'locale' => 'ar_ae', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-bh' => array('language' => 'Arabic (Bahrain)', 'locale' => 'ar_bh', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-dz' => array('language' => 'Arabic (Algeria)', 'locale' => 'ar_dz', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-eg' => array('language' => 'Arabic (Egypt)', 'locale' => 'ar_eg', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-iq' => array('language' => 'Arabic (Iraq)', 'locale' => 'ar_iq', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-jo' => array('language' => 'Arabic (Jordan)', 'locale' => 'ar_jo', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-kw' => array('language' => 'Arabic (Kuwait)', 'locale' => 'ar_kw', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-lb' => array('language' => 'Arabic (Lebanon)', 'locale' => 'ar_lb', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-ly' => array('language' => 'Arabic (Libya)', 'locale' => 'ar_ly', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-ma' => array('language' => 'Arabic (Morocco)', 'locale' => 'ar_ma', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-om' => array('language' => 'Arabic (Oman)', 'locale' => 'ar_om', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-qa' => array('language' => 'Arabic (Qatar)', 'locale' => 'ar_qa', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-sa' => array('language' => 'Arabic (Saudi Arabia)', 'locale' => 'ar_sa', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-sy' => array('language' => 'Arabic (Syria)', 'locale' => 'ar_sy', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-tn' => array('language' => 'Arabic (Tunisia)', 'locale' => 'ar_tn', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'ar-ye' => array('language' => 'Arabic (Yemen)', 'locale' => 'ar_ye', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('be')); $expected = array( 'be' => array('language' => 'Byelorussian', 'locale' => 'bel', 'localeFallback' => 'bel', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('bg')); $expected = array( 'bg' => array('language' => 'Bulgarian', 'locale' => 'bul', 'localeFallback' => 'bul', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('bs')); $expected = array( 'bs' => array('language' => 'Bosnian', 'locale' => 'bos', 'localeFallback' => 'bos', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('ca')); $expected = array( 'ca' => array('language' => 'Catalan', 'locale' => 'cat', 'localeFallback' => 'cat', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('cs')); $expected = array( 'cs' => array('language' => 'Czech', 'locale' => 'ces', 'localeFallback' => 'ces', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('da')); $expected = array( 'da' => array('language' => 'Danish', 'locale' => 'dan', 'localeFallback' => 'dan', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('de', 'de-at', 'de-ch', 'de-de', 'de-li', 'de-lu')); $expected = array( 'de' => array('language' => 'German (Standard)', 'locale' => 'deu', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'), 'de-at' => array('language' => 'German (Austria)', 'locale' => 'de_at', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'), 'de-ch' => array('language' => 'German (Swiss)', 'locale' => 'de_ch', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'), 'de-de' => array('language' => 'German (Germany)', 'locale' => 'de_de', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'), 'de-li' => array('language' => 'German (Liechtenstein)', 'locale' => 'de_li', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'), 'de-lu' => array('language' => 'German (Luxembourg)', 'locale' => 'de_lu', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('el')); $expected = array( 'el' => array('language' => 'Greek', 'locale' => 'ell', 'localeFallback' => 'ell', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('en', 'en-au', 'en-bz', 'en-ca', 'en-gb', 'en-ie', 'en-jm', 'en-nz', 'en-tt', 'en-us', 'en-za')); $expected = array( 'en' => array('language' => 'English', 'locale' => 'eng', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-au' => array('language' => 'English (Australian)', 'locale' => 'en_au', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-bz' => array('language' => 'English (Belize)', 'locale' => 'en_bz', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-ca' => array('language' => 'English (Canadian)', 'locale' => 'en_ca', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-gb' => array('language' => 'English (British)', 'locale' => 'en_gb', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-ie' => array('language' => 'English (Ireland)', 'locale' => 'en_ie', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-jm' => array('language' => 'English (Jamaica)', 'locale' => 'en_jm', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-nz' => array('language' => 'English (New Zealand)', 'locale' => 'en_nz', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-tt' => array('language' => 'English (Trinidad)', 'locale' => 'en_tt', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-us' => array('language' => 'English (United States)', 'locale' => 'en_us', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'en-za' => array('language' => 'English (South Africa)', 'locale' => 'en_za', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('es', 'es-ar', 'es-bo', 'es-cl', 'es-co', 'es-cr', 'es-do', 'es-ec', 'es-es', 'es-gt', 'es-hn', 'es-mx', 'es-ni', 'es-pa', 'es-pe', 'es-pr', 'es-py', 'es-sv', 'es-uy', 'es-ve')); $expected = array( 'es' => array('language' => 'Spanish (Spain - Traditional)', 'locale' => 'spa', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-ar' => array('language' => 'Spanish (Argentina)', 'locale' => 'es_ar', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-bo' => array('language' => 'Spanish (Bolivia)', 'locale' => 'es_bo', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-cl' => array('language' => 'Spanish (Chile)', 'locale' => 'es_cl', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-co' => array('language' => 'Spanish (Colombia)', 'locale' => 'es_co', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-cr' => array('language' => 'Spanish (Costa Rica)', 'locale' => 'es_cr', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-do' => array('language' => 'Spanish (Dominican Republic)', 'locale' => 'es_do', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-ec' => array('language' => 'Spanish (Ecuador)', 'locale' => 'es_ec', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-es' => array('language' => 'Spanish (Spain)', 'locale' => 'es_es', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-gt' => array('language' => 'Spanish (Guatemala)', 'locale' => 'es_gt', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-hn' => array('language' => 'Spanish (Honduras)', 'locale' => 'es_hn', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-mx' => array('language' => 'Spanish (Mexican)', 'locale' => 'es_mx', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-ni' => array('language' => 'Spanish (Nicaragua)', 'locale' => 'es_ni', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-pa' => array('language' => 'Spanish (Panama)', 'locale' => 'es_pa', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-pe' => array('language' => 'Spanish (Peru)', 'locale' => 'es_pe', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-pr' => array('language' => 'Spanish (Puerto Rico)', 'locale' => 'es_pr', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-py' => array('language' => 'Spanish (Paraguay)', 'locale' => 'es_py', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-sv' => array('language' => 'Spanish (El Salvador)', 'locale' => 'es_sv', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-uy' => array('language' => 'Spanish (Uruguay)', 'locale' => 'es_uy', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-ve' => array('language' => 'Spanish (Venezuela)', 'locale' => 'es_ve', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('et')); $expected = array( 'et' => array('language' => 'Estonian', 'locale' => 'est', 'localeFallback' => 'est', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('eu')); $expected = array( 'eu' => array('language' => 'Basque', 'locale' => 'eus', 'localeFallback' => 'eus', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('fa')); $expected = array( 'fa' => array('language' => 'Farsi', 'locale' => 'fas', 'localeFallback' => 'fas', 'charset' => 'utf-8', 'direction' => 'rtl') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('fi')); $expected = array( 'fi' => array('language' => 'Finnish', 'locale' => 'fin', 'localeFallback' => 'fin', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('fo')); $expected = array( 'fo' => array('language' => 'Faeroese', 'locale' => 'fao', 'localeFallback' => 'fao', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('fr', 'fr-be', 'fr-ca', 'fr-ch', 'fr-fr', 'fr-lu')); $expected = array( 'fr' => array('language' => 'French (Standard)', 'locale' => 'fra', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'), 'fr-be' => array('language' => 'French (Belgium)', 'locale' => 'fr_be', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'), 'fr-ca' => array('language' => 'French (Canadian)', 'locale' => 'fr_ca', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'), 'fr-ch' => array('language' => 'French (Swiss)', 'locale' => 'fr_ch', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'), 'fr-fr' => array('language' => 'French (France)', 'locale' => 'fr_fr', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr'), 'fr-lu' => array('language' => 'French (Luxembourg)', 'locale' => 'fr_lu', 'localeFallback' => 'fra', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('ga')); $expected = array( 'ga' => array('language' => 'Irish', 'locale' => 'gle', 'localeFallback' => 'gle', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('gd', 'gd-ie')); $expected = array( 'gd' => array('language' => 'Gaelic (Scots)', 'locale' => 'gla', 'localeFallback' => 'gla', 'charset' => 'utf-8', 'direction' => 'ltr'), 'gd-ie' => array('language' => 'Gaelic (Irish)', 'locale' => 'gd_ie', 'localeFallback' => 'gla', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('gl')); $expected = array( 'gl' => array('language' => 'Galician', 'locale' => 'glg', 'localeFallback' => 'glg', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('he')); $expected = array( 'he' => array('language' => 'Hebrew', 'locale' => 'heb', 'localeFallback' => 'heb', 'charset' => 'utf-8', 'direction' => 'rtl') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('hi')); $expected = array( 'hi' => array('language' => 'Hindi', 'locale' => 'hin', 'localeFallback' => 'hin', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('hr')); $expected = array( 'hr' => array('language' => 'Croatian', 'locale' => 'hrv', 'localeFallback' => 'hrv', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('hu')); $expected = array( 'hu' => array('language' => 'Hungarian', 'locale' => 'hun', 'localeFallback' => 'hun', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('hy')); $expected = array( 'hy' => array('language' => 'Armenian - Armenia', 'locale' => 'hye', 'localeFallback' => 'hye', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('id')); $expected = array( 'id' => array('language' => 'Indonesian', 'locale' => 'ind', 'localeFallback' => 'ind', 'charset' => 'utf-8', 'direction' => 'ltr'), ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('is')); $expected = array( 'is' => array('language' => 'Icelandic', 'locale' => 'isl', 'localeFallback' => 'isl', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('it', 'it-ch')); $expected = array( 'it' => array('language' => 'Italian', 'locale' => 'ita', 'localeFallback' => 'ita', 'charset' => 'utf-8', 'direction' => 'ltr'), 'it-ch' => array('language' => 'Italian (Swiss) ', 'locale' => 'it_ch', 'localeFallback' => 'ita', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('ja')); $expected = array( 'ja' => array('language' => 'Japanese', 'locale' => 'jpn', 'localeFallback' => 'jpn', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('kk')); $expected = array( 'kk' => array('language' => 'Kazakh', 'locale' => 'kaz', 'localeFallback' => 'kaz', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('ko', 'ko-kp', 'ko-kr')); $expected = array( 'ko' => array('language' => 'Korean', 'locale' => 'kor', 'localeFallback' => 'kor', 'charset' => 'kr', 'direction' => 'ltr'), 'ko-kp' => array('language' => 'Korea (North)', 'locale' => 'ko_kp', 'localeFallback' => 'kor', 'charset' => 'kr', 'direction' => 'ltr'), 'ko-kr' => array('language' => 'Korea (South)', 'locale' => 'ko_kr', 'localeFallback' => 'kor', 'charset' => 'kr', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('koi8-r', 'ru', 'ru-mo')); $expected = array( 'koi8-r' => array('language' => 'Russian', 'locale' => 'koi8_r', 'localeFallback' => 'rus', 'charset' => 'koi8-r', 'direction' => 'ltr'), 'ru' => array('language' => 'Russian', 'locale' => 'rus', 'localeFallback' => 'rus', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ru-mo' => array('language' => 'Russian (Moldavia)', 'locale' => 'ru_mo', 'localeFallback' => 'rus', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('lt')); $expected = array( 'lt' => array('language' => 'Lithuanian', 'locale' => 'lit', 'localeFallback' => 'lit', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('lv')); $expected = array( 'lv' => array('language' => 'Latvian', 'locale' => 'lav', 'localeFallback' => 'lav', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('mk', 'mk-mk')); $expected = array( 'mk' => array('language' => 'FYRO Macedonian', 'locale' => 'mkd', 'localeFallback' => 'mkd', 'charset' => 'utf-8', 'direction' => 'ltr'), 'mk-mk' => array('language' => 'Macedonian', 'locale' => 'mk_mk', 'localeFallback' => 'mkd', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('ms')); $expected = array( 'ms' => array('language' => 'Malaysian', 'locale' => 'msa', 'localeFallback' => 'msa', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('mt')); $expected = array( 'mt' => array('language' => 'Maltese', 'locale' => 'mlt', 'localeFallback' => 'mlt', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('nl', 'nl-be')); $expected = array( 'nl' => array('language' => 'Dutch (Standard)', 'locale' => 'nld', 'localeFallback' => 'nld', 'charset' => 'utf-8', 'direction' => 'ltr'), 'nl-be' => array('language' => 'Dutch (Belgium)', 'locale' => 'nl_be', 'localeFallback' => 'nld', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog('nl'); $expected = array('language' => 'Dutch (Standard)', 'locale' => 'nld', 'localeFallback' => 'nld', 'charset' => 'utf-8', 'direction' => 'ltr'); $this->assertEquals($expected, $result); $result = $localize->catalog('nld'); $expected = array('language' => 'Dutch (Standard)', 'locale' => 'nld', 'localeFallback' => 'nld', 'charset' => 'utf-8', 'direction' => 'ltr'); $this->assertEquals($expected, $result); $result = $localize->catalog('dut'); $expected = array('language' => 'Dutch (Standard)', 'locale' => 'nld', 'localeFallback' => 'nld', 'charset' => 'utf-8', 'direction' => 'ltr'); $this->assertEquals($expected, $result); $result = $localize->catalog(array('nb')); $expected = array( 'nb' => array('language' => 'Norwegian Bokmal', 'locale' => 'nob', 'localeFallback' => 'nor', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('nn', 'no')); $expected = array( 'nn' => array('language' => 'Norwegian Nynorsk', 'locale' => 'nno', 'localeFallback' => 'nor', 'charset' => 'utf-8', 'direction' => 'ltr'), 'no' => array('language' => 'Norwegian', 'locale' => 'nor', 'localeFallback' => 'nor', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('pl')); $expected = array( 'pl' => array('language' => 'Polish', 'locale' => 'pol', 'localeFallback' => 'pol', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('pt', 'pt-br')); $expected = array( 'pt' => array('language' => 'Portuguese (Portugal)', 'locale' => 'por', 'localeFallback' => 'por', 'charset' => 'utf-8', 'direction' => 'ltr'), 'pt-br' => array('language' => 'Portuguese (Brazil)', 'locale' => 'pt_br', 'localeFallback' => 'por', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('rm')); $expected = array( 'rm' => array('language' => 'Rhaeto-Romanic', 'locale' => 'roh', 'localeFallback' => 'roh', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('ro', 'ro-mo')); $expected = array( 'ro' => array('language' => 'Romanian', 'locale' => 'ron', 'localeFallback' => 'ron', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ro-mo' => array('language' => 'Romanian (Moldavia)', 'locale' => 'ro_mo', 'localeFallback' => 'ron', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('sb')); $expected = array( 'sb' => array('language' => 'Sorbian', 'locale' => 'wen', 'localeFallback' => 'wen', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('sk')); $expected = array( 'sk' => array('language' => 'Slovak', 'locale' => 'slk', 'localeFallback' => 'slk', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('sl')); $expected = array( 'sl' => array('language' => 'Slovenian', 'locale' => 'slv', 'localeFallback' => 'slv', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('sq')); $expected = array( 'sq' => array('language' => 'Albanian', 'locale' => 'sqi', 'localeFallback' => 'sqi', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('sr')); $expected = array( 'sr' => array('language' => 'Serbian', 'locale' => 'srp', 'localeFallback' => 'srp', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('sv', 'sv-fi')); $expected = array( 'sv' => array('language' => 'Swedish', 'locale' => 'swe', 'localeFallback' => 'swe', 'charset' => 'utf-8', 'direction' => 'ltr'), 'sv-fi' => array('language' => 'Swedish (Finland)', 'locale' => 'sv_fi', 'localeFallback' => 'swe', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('se')); $expected = array( 'se' => array('language' => 'Sami', 'locale' => 'sme', 'localeFallback' => 'sme', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('th')); $expected = array( 'th' => array('language' => 'Thai', 'locale' => 'tha', 'localeFallback' => 'tha', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('tn')); $expected = array( 'tn' => array('language' => 'Tswana', 'locale' => 'tsn', 'localeFallback' => 'tsn', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('tr')); $expected = array( 'tr' => array('language' => 'Turkish', 'locale' => 'tur', 'localeFallback' => 'tur', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('ts')); $expected = array( 'ts' => array('language' => 'Tsonga', 'locale' => 'tso', 'localeFallback' => 'tso', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('uk')); $expected = array( 'uk' => array('language' => 'Ukrainian', 'locale' => 'ukr', 'localeFallback' => 'ukr', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('ur')); $expected = array( 'ur' => array('language' => 'Urdu', 'locale' => 'urd', 'localeFallback' => 'urd', 'charset' => 'utf-8', 'direction' => 'rtl') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('ve')); $expected = array( 've' => array('language' => 'Venda', 'locale' => 'ven', 'localeFallback' => 'ven', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('vi')); $expected = array( 'vi' => array('language' => 'Vietnamese', 'locale' => 'vie', 'localeFallback' => 'vie', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('cy')); $expected = array( 'cy' => array('language' => 'Welsh', 'locale' => 'cym', 'localeFallback' => 'cym', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('xh')); $expected = array( 'xh' => array('language' => 'Xhosa', 'locale' => 'xho', 'localeFallback' => 'xho', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('yi')); $expected = array( 'yi' => array('language' => 'Yiddish', 'locale' => 'yid', 'localeFallback' => 'yid', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('zh', 'zh-cn', 'zh-hk', 'zh-sg', 'zh-tw')); $expected = array( 'zh' => array('language' => 'Chinese', 'locale' => 'zho', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr'), 'zh-cn' => array('language' => 'Chinese (PRC)', 'locale' => 'zh_cn', 'localeFallback' => 'zho', 'charset' => 'GB2312', 'direction' => 'ltr'), 'zh-hk' => array('language' => 'Chinese (Hong Kong)', 'locale' => 'zh_hk', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr'), 'zh-sg' => array('language' => 'Chinese (Singapore)', 'locale' => 'zh_sg', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr'), 'zh-tw' => array('language' => 'Chinese (Taiwan)', 'locale' => 'zh_tw', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('zu')); $expected = array( 'zu' => array('language' => 'Zulu', 'locale' => 'zul', 'localeFallback' => 'zul', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('en-nz', 'es-do', 'ar-lb', 'zh-hk', 'pt-br')); $expected = array( 'en-nz' => array('language' => 'English (New Zealand)', 'locale' => 'en_nz', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'es-do' => array('language' => 'Spanish (Dominican Republic)', 'locale' => 'es_do', 'localeFallback' => 'spa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ar-lb' => array('language' => 'Arabic (Lebanon)', 'locale' => 'ar_lb', 'localeFallback' => 'ara', 'charset' => 'utf-8', 'direction' => 'rtl'), 'zh-hk' => array('language' => 'Chinese (Hong Kong)', 'locale' => 'zh_hk', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr'), 'pt-br' => array('language' => 'Portuguese (Brazil)', 'locale' => 'pt_br', 'localeFallback' => 'por', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); $result = $localize->catalog(array('eng', 'deu', 'zho', 'rum', 'zul', 'yid')); $expected = array( 'eng' => array('language' => 'English', 'locale' => 'eng', 'localeFallback' => 'eng', 'charset' => 'utf-8', 'direction' => 'ltr'), 'deu' => array('language' => 'German (Standard)', 'locale' => 'deu', 'localeFallback' => 'deu', 'charset' => 'utf-8', 'direction' => 'ltr'), 'zho' => array('language' => 'Chinese', 'locale' => 'zho', 'localeFallback' => 'zho', 'charset' => 'utf-8', 'direction' => 'ltr'), 'rum' => array('language' => 'Romanian', 'locale' => 'ron', 'localeFallback' => 'ron', 'charset' => 'utf-8', 'direction' => 'ltr'), 'zul' => array('language' => 'Zulu', 'locale' => 'zul', 'localeFallback' => 'zul', 'charset' => 'utf-8', 'direction' => 'ltr'), 'yid' => array('language' => 'Yiddish', 'locale' => 'yid', 'localeFallback' => 'yid', 'charset' => 'utf-8', 'direction' => 'ltr') ); $this->assertEquals($expected, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/I18n/MultibyteTest.php000066400000000000000000013711541265552240500224270ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.I18n * @since CakePHP(tm) v 1.2.0.6833 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Multibyte', 'I18n'); /** * MultibyteTest class * * @package Cake.Test.Case.I18n */ class MultibyteTest extends CakeTestCase { /** * testUtf8 method * * @return void */ public function testUtf8() { $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $result = Multibyte::utf8($string); $expected = array(33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126); $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $result = Multibyte::utf8($string); $expected = array(161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200); $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $result = Multibyte::utf8($string); $expected = array(201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300); $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $result = Multibyte::utf8($string); $expected = array(301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400); $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $result = Multibyte::utf8($string); $expected = array(401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500); $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $result = Multibyte::utf8($string); $expected = array(601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700); $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $result = Multibyte::utf8($string); $expected = array(1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051); $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $result = Multibyte::utf8($string); $expected = array(1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100); $this->assertEquals($expected, $result); $string = 'ีนีบีปีผีฝีพีฟ'; $result = Multibyte::utf8($string); $expected = array(1401, 1402, 1403, 1404, 1405, 1406, 1407); $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $result = Multibyte::utf8($string); $expected = array(1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615); $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $result = Multibyte::utf8($string); $expected = array(10032, 10033, 10034, 10035, 10036, 10037, 10038, 10039, 10040, 10041, 10042, 10043, 10044, 10045, 10046, 10047, 10048, 10049, 10050, 10051, 10052, 10053, 10054, 10055, 10056, 10057, 10058, 10059, 10060, 10061, 10062, 10063, 10064, 10065, 10066, 10067, 10068, 10069, 10070, 10071, 10072, 10073, 10074, 10075, 10076, 10077, 10078); $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $result = Multibyte::utf8($string); $expected = array(11904, 11905, 11906, 11907, 11908, 11909, 11910, 11911, 11912, 11913, 11914, 11915, 11916, 11917, 11918, 11919, 11920, 11921, 11922, 11923, 11924, 11925, 11926, 11927, 11928, 11929, 11931, 11932, 11933, 11934, 11935, 11936, 11937, 11938, 11939, 11940, 11941, 11942, 11943, 11944, 11945, 11946, 11947, 11948, 11949, 11950, 11951, 11952, 11953, 11954, 11955, 11956, 11957, 11958, 11959, 11960, 11961, 11962, 11963, 11964, 11965, 11966, 11967, 11968, 11969, 11970, 11971, 11972, 11973, 11974, 11975, 11976, 11977, 11978, 11979, 11980, 11981, 11982, 11983, 11984, 11985, 11986, 11987, 11988, 11989, 11990, 11991, 11992, 11993, 11994, 11995, 11996, 11997, 11998, 11999, 12000); $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $result = Multibyte::utf8($string); $expected = array(12101, 12102, 12103, 12104, 12105, 12106, 12107, 12108, 12109, 12110, 12111, 12112, 12113, 12114, 12115, 12116, 12117, 12118, 12119, 12120, 12121, 12122, 12123, 12124, 12125, 12126, 12127, 12128, 12129, 12130, 12131, 12132, 12133, 12134, 12135, 12136, 12137, 12138, 12139, 12140, 12141, 12142, 12143, 12144, 12145, 12146, 12147, 12148, 12149, 12150, 12151, 12152, 12153, 12154, 12155, 12156, 12157, 12158, 12159); $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $result = Multibyte::utf8($string); $expected = array(45601, 45602, 45603, 45604, 45605, 45606, 45607, 45608, 45609, 45610, 45611, 45612, 45613, 45614, 45615, 45616, 45617, 45618, 45619, 45620, 45621, 45622, 45623, 45624, 45625, 45626, 45627, 45628, 45629, 45630, 45631, 45632, 45633, 45634, 45635, 45636, 45637, 45638, 45639, 45640, 45641, 45642, 45643, 45644, 45645, 45646, 45647, 45648, 45649, 45650, 45651, 45652, 45653, 45654, 45655, 45656, 45657, 45658, 45659, 45660, 45661, 45662, 45663, 45664, 45665, 45666, 45667, 45668, 45669, 45670, 45671, 45672, 45673, 45674, 45675, 45676, 45677, 45678, 45679, 45680, 45681, 45682, 45683, 45684, 45685, 45686, 45687, 45688, 45689, 45690, 45691, 45692, 45693, 45694, 45695, 45696, 45697, 45698, 45699, 45700); $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $result = Multibyte::utf8($string); $expected = array(65136, 65137, 65138, 65139, 65140, 65141, 65142, 65143, 65144, 65145, 65146, 65147, 65148, 65149, 65150, 65151, 65152, 65153, 65154, 65155, 65156, 65157, 65158, 65159, 65160, 65161, 65162, 65163, 65164, 65165, 65166, 65167, 65168, 65169, 65170, 65171, 65172, 65173, 65174, 65175, 65176, 65177, 65178, 65179, 65180, 65181, 65182, 65183, 65184, 65185, 65186, 65187, 65188, 65189, 65190, 65191, 65192, 65193, 65194, 65195, 65196, 65197, 65198, 65199, 65200); $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $result = Multibyte::utf8($string); $expected = array(65201, 65202, 65203, 65204, 65205, 65206, 65207, 65208, 65209, 65210, 65211, 65212, 65213, 65214, 65215, 65216, 65217, 65218, 65219, 65220, 65221, 65222, 65223, 65224, 65225, 65226, 65227, 65228, 65229, 65230, 65231, 65232, 65233, 65234, 65235, 65236, 65237, 65238, 65239, 65240, 65241, 65242, 65243, 65244, 65245, 65246, 65247, 65248, 65249, 65250, 65251, 65252, 65253, 65254, 65255, 65256, 65257, 65258, 65259, 65260, 65261, 65262, 65263, 65264, 65265, 65266, 65267, 65268, 65269, 65270, 65271, 65272, 65273, 65274, 65275, 65276); $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $result = Multibyte::utf8($string); $expected = array(65345, 65346, 65347, 65348, 65349, 65350, 65351, 65352, 65353, 65354, 65355, 65356, 65357, 65358, 65359, 65360, 65361, 65362, 65363, 65364, 65365, 65366, 65367, 65368, 65369, 65370); $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $result = Multibyte::utf8($string); $expected = array(65377, 65378, 65379, 65380, 65381, 65382, 65383, 65384, 65385, 65386, 65387, 65388, 65389, 65390, 65391, 65392, 65393, 65394, 65395, 65396, 65397, 65398, 65399, 65400); $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $result = Multibyte::utf8($string); $expected = array(65401, 65402, 65403, 65404, 65405, 65406, 65407, 65408, 65409, 65410, 65411, 65412, 65413, 65414, 65415, 65416, 65417, 65418, 65419, 65420, 65421, 65422, 65423, 65424, 65425, 65426, 65427, 65428, 65429, 65430, 65431, 65432, 65433, 65434, 65435, 65436, 65437, 65438); $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $result = Multibyte::utf8($string); $expected = array(292, 275, 314, 316, 335, 44, 32, 372, 337, 345, 316, 271, 33); $this->assertEquals($expected, $result); $string = 'Hello, World!'; $result = Multibyte::utf8($string); $expected = array(72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33); $this->assertEquals($expected, $result); $string = 'ยจ'; $result = Multibyte::utf8($string); $expected = array(168); $this->assertEquals($expected, $result); $string = 'ยฟ'; $result = Multibyte::utf8($string); $expected = array(191); $this->assertEquals($expected, $result); $string = 'ฤini'; $result = Multibyte::utf8($string); $expected = array(269, 105, 110, 105); $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $result = Multibyte::utf8($string); $expected = array(109, 111, 263, 105); $this->assertEquals($expected, $result); $string = 'drลพavni'; $result = Multibyte::utf8($string); $expected = array(100, 114, 382, 97, 118, 110, 105); $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $result = Multibyte::utf8($string); $expected = array(25226, 30334, 24230, 35774, 20026, 39318, 39029); $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $result = Multibyte::utf8($string); $expected = array(19968, 20108, 19977, 21608, 27704, 40845); $this->assertEquals($expected, $result); $string = 'ิ€ิ‚ิ„ิ†ิˆิŠิŒิŽิิ’'; $result = Multibyte::utf8($string); $expected = array(1280, 1282, 1284, 1286, 1288, 1290, 1292, 1294, 1296, 1298); $this->assertEquals($expected, $result); $string = 'ิิƒิ…ิ‡ิ‰ิ‹ิิิิ’'; $result = Multibyte::utf8($string); $expected = array(1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1296, 1298); $this->assertEquals($expected, $result); $string = 'ิฑิฒิณิดิติถิทิธินิบิปิผิฝิพิฟี€ีี‚ีƒี„ี…ี†ี‡ีˆี‰ีŠี‹ีŒีีŽีีี‘ี’ี“ี”ี•ี–ึ‡'; $result = Multibyte::utf8($string); $expected = array(1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1415); $this->assertEquals($expected, $result); $string = 'ีกีขีฃีคีฅีฆีงีจีฉีชีซีฌีญีฎีฏีฐีฑีฒีณีดีตีถีทีธีนีบีปีผีฝีพีฟึ€ึึ‚ึƒึ„ึ…ึ†ึ‡'; $result = Multibyte::utf8($string); $expected = array(1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415); $this->assertEquals($expected, $result); $string = 'แ‚ แ‚กแ‚ขแ‚ฃแ‚คแ‚ฅแ‚ฆแ‚งแ‚จแ‚ฉแ‚ชแ‚ซแ‚ฌแ‚ญแ‚ฎแ‚ฏแ‚ฐแ‚ฑแ‚ฒแ‚ณแ‚ดแ‚ตแ‚ถแ‚ทแ‚ธแ‚นแ‚บแ‚ปแ‚ผแ‚ฝแ‚พแ‚ฟแƒ€แƒแƒ‚แƒƒแƒ„แƒ…'; $result = Multibyte::utf8($string); $expected = array(4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293); $this->assertEquals($expected, $result); $string = 'แธ€แธ‚แธ„แธ†แธˆแธŠแธŒแธŽแธแธ’แธ”แธ–แธ˜แธšแธœแธžแธ แธขแธคแธฆแธจแธชแธฌแธฎแธฐแธฒแธดแธถแธธแธบแธผแธพแน€แน‚แน„แน†แนˆแนŠแนŒแนŽแนแน’แน”แน–แน˜แนšแนœแนžแน แนขแนคแนฆแนจแนชแนฌแนฎแนฐแนฒแนดแนถแนธแนบแนผแนพแบ€แบ‚แบ„แบ†แบˆแบŠแบŒแบŽแบแบ’แบ”แบ–แบ—แบ˜แบ™แบšแบ แบขแบคแบฆแบจแบชแบฌแบฎแบฐแบฒแบดแบถแบธแบบแบผแบพแป€แป‚แป„แป†แปˆแปŠแปŒแปŽแปแป’แป”แป–แป˜แปšแปœแปžแป แปขแปคแปฆแปจแปชแปฌแปฎแปฐแปฒแปดแปถแปธ'; $result = Multibyte::utf8($string); $expected = array(7680, 7682, 7684, 7686, 7688, 7690, 7692, 7694, 7696, 7698, 7700, 7702, 7704, 7706, 7708, 7710, 7712, 7714, 7716, 7718, 7720, 7722, 7724, 7726, 7728, 7730, 7732, 7734, 7736, 7738, 7740, 7742, 7744, 7746, 7748, 7750, 7752, 7754, 7756, 7758, 7760, 7762, 7764, 7766, 7768, 7770, 7772, 7774, 7776, 7778, 7780, 7782, 7784, 7786, 7788, 7790, 7792, 7794, 7796, 7798, 7800, 7802, 7804, 7806, 7808, 7810, 7812, 7814, 7816, 7818, 7820, 7822, 7824, 7826, 7828, 7830, 7831, 7832, 7833, 7834, 7840, 7842, 7844, 7846, 7848, 7850, 7852, 7854, 7856, 7858, 7860, 7862, 7864, 7866, 7868, 7870, 7872, 7874, 7876, 7878, 7880, 7882, 7884, 7886, 7888, 7890, 7892, 7894, 7896, 7898, 7900, 7902, 7904, 7906, 7908, 7910, 7912, 7914, 7916, 7918, 7920, 7922, 7924, 7926, 7928); $this->assertEquals($expected, $result); $string = 'แธแธƒแธ…แธ‡แธ‰แธ‹แธแธแธ‘แธ“แธ•แธ—แธ™แธ›แธแธŸแธกแธฃแธฅแธงแธฉแธซแธญแธฏแธฑแธณแธตแธทแธนแธปแธฝแธฟแนแนƒแน…แน‡แน‰แน‹แนแนแน‘แน“แน•แน—แน™แน›แนแนŸแนกแนฃแนฅแนงแนฉแนซแนญแนฏแนฑแนณแนตแนทแนนแนปแนฝแนฟแบแบƒแบ…แบ‡แบ‰แบ‹แบแบแบ‘แบ“แบ•แบ–แบ—แบ˜แบ™แบšแบกแบฃแบฅแบงแบฉแบซแบญแบฏแบฑแบณแบตแบทแบนแบปแบฝแบฟแปแปƒแป…แป‡แป‰แป‹แปแปแป‘แป“แป•แป—แป™แป›แปแปŸแปกแปฃแปฅแปงแปฉแปซแปญแปฏแปฑแปณแปตแปทแปน'; $result = Multibyte::utf8($string); $expected = array(7681, 7683, 7685, 7687, 7689, 7691, 7693, 7695, 7697, 7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717, 7719, 7721, 7723, 7725, 7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745, 7747, 7749, 7751, 7753, 7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773, 7775, 7777, 7779, 7781, 7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801, 7803, 7805, 7807, 7809, 7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829, 7830, 7831, 7832, 7833, 7834, 7841, 7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861, 7863, 7865, 7867, 7869, 7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889, 7891, 7893, 7895, 7897, 7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917, 7919, 7921, 7923, 7925, 7927, 7929); $this->assertEquals($expected, $result); $string = 'โ„ฆโ„ชโ„ซโ„ฒ'; $result = Multibyte::utf8($string); $expected = array(8486, 8490, 8491, 8498); $this->assertEquals($expected, $result); $string = 'ฯ‰kรฅโ…Ž'; $result = Multibyte::utf8($string); $expected = array(969, 107, 229, 8526); $this->assertEquals($expected, $result); $string = 'โ… โ…กโ…ขโ…ฃโ…คโ…ฅโ…ฆโ…งโ…จโ…ฉโ…ชโ…ซโ…ฌโ…ญโ…ฎโ…ฏโ†ƒ'; $result = Multibyte::utf8($string); $expected = array(8544, 8545, 8546, 8547, 8548, 8549, 8550, 8551, 8552, 8553, 8554, 8555, 8556, 8557, 8558, 8559, 8579); $this->assertEquals($expected, $result); $string = 'โ…ฐโ…ฑโ…ฒโ…ณโ…ดโ…ตโ…ถโ…ทโ…ธโ…นโ…บโ…ปโ…ผโ…ฝโ…พโ…ฟโ†„'; $result = Multibyte::utf8($string); $expected = array(8560, 8561, 8562, 8563, 8564, 8565, 8566, 8567, 8568, 8569, 8570, 8571, 8572, 8573, 8574, 8575, 8580); $this->assertEquals($expected, $result); $string = 'โ’ถโ’ทโ’ธโ’นโ’บโ’ปโ’ผโ’ฝโ’พโ’ฟโ“€โ“โ“‚โ“ƒโ“„โ“…โ“†โ“‡โ“ˆโ“‰โ“Šโ“‹โ“Œโ“โ“Žโ“'; $result = Multibyte::utf8($string); $expected = array(9398, 9399, 9400, 9401, 9402, 9403, 9404, 9405, 9406, 9407, 9408, 9409, 9410, 9411, 9412, 9413, 9414, 9415, 9416, 9417, 9418, 9419, 9420, 9421, 9422, 9423); $this->assertEquals($expected, $result); $string = 'โ“โ“‘โ“’โ““โ“”โ“•โ“–โ“—โ“˜โ“™โ“šโ“›โ“œโ“โ“žโ“Ÿโ“ โ“กโ“ขโ“ฃโ“คโ“ฅโ“ฆโ“งโ“จโ“ฉ'; $result = Multibyte::utf8($string); $expected = array(9424, 9425, 9426, 9427, 9428, 9429, 9430, 9431, 9432, 9433, 9434, 9435, 9436, 9437, 9438, 9439, 9440, 9441, 9442, 9443, 9444, 9445, 9446, 9447, 9448, 9449); $this->assertEquals($expected, $result); $string = 'โฐ€โฐโฐ‚โฐƒโฐ„โฐ…โฐ†โฐ‡โฐˆโฐ‰โฐŠโฐ‹โฐŒโฐโฐŽโฐโฐโฐ‘โฐ’โฐ“โฐ”โฐ•โฐ–โฐ—โฐ˜โฐ™โฐšโฐ›โฐœโฐโฐžโฐŸโฐ โฐกโฐขโฐฃโฐคโฐฅโฐฆโฐงโฐจโฐฉโฐชโฐซโฐฌโฐญโฐฎ'; $result = Multibyte::utf8($string); $expected = array(11264, 11265, 11266, 11267, 11268, 11269, 11270, 11271, 11272, 11273, 11274, 11275, 11276, 11277, 11278, 11279, 11280, 11281, 11282, 11283, 11284, 11285, 11286, 11287, 11288, 11289, 11290, 11291, 11292, 11293, 11294, 11295, 11296, 11297, 11298, 11299, 11300, 11301, 11302, 11303, 11304, 11305, 11306, 11307, 11308, 11309, 11310); $this->assertEquals($expected, $result); $string = 'โฐฐโฐฑโฐฒโฐณโฐดโฐตโฐถโฐทโฐธโฐนโฐบโฐปโฐผโฐฝโฐพโฐฟโฑ€โฑโฑ‚โฑƒโฑ„โฑ…โฑ†โฑ‡โฑˆโฑ‰โฑŠโฑ‹โฑŒโฑโฑŽโฑโฑโฑ‘โฑ’โฑ“โฑ”โฑ•โฑ–โฑ—โฑ˜โฑ™โฑšโฑ›โฑœโฑโฑž'; $result = Multibyte::utf8($string); $expected = array(11312, 11313, 11314, 11315, 11316, 11317, 11318, 11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, 11327, 11328, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338, 11339, 11340, 11341, 11342, 11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350, 11351, 11352, 11353, 11354, 11355, 11356, 11357, 11358); $this->assertEquals($expected, $result); $string = 'โฒ€โฒ‚โฒ„โฒ†โฒˆโฒŠโฒŒโฒŽโฒโฒ’โฒ”โฒ–โฒ˜โฒšโฒœโฒžโฒ โฒขโฒคโฒฆโฒจโฒชโฒฌโฒฎโฒฐโฒฒโฒดโฒถโฒธโฒบโฒผโฒพโณ€โณ‚โณ„โณ†โณˆโณŠโณŒโณŽโณโณ’โณ”โณ–โณ˜โณšโณœโณžโณ โณข'; $result = Multibyte::utf8($string); $expected = array(11392, 11394, 11396, 11398, 11400, 11402, 11404, 11406, 11408, 11410, 11412, 11414, 11416, 11418, 11420, 11422, 11424, 11426, 11428, 11430, 11432, 11434, 11436, 11438, 11440, 11442, 11444, 11446, 11448, 11450, 11452, 11454, 11456, 11458, 11460, 11462, 11464, 11466, 11468, 11470, 11472, 11474, 11476, 11478, 11480, 11482, 11484, 11486, 11488, 11490); $this->assertEquals($expected, $result); $string = 'โฒโฒƒโฒ…โฒ‡โฒ‰โฒ‹โฒโฒโฒ‘โฒ“โฒ•โฒ—โฒ™โฒ›โฒโฒŸโฒกโฒฃโฒฅโฒงโฒฉโฒซโฒญโฒฏโฒฑโฒณโฒตโฒทโฒนโฒปโฒฝโฒฟโณโณƒโณ…โณ‡โณ‰โณ‹โณโณโณ‘โณ“โณ•โณ—โณ™โณ›โณโณŸโณกโณฃ'; $result = Multibyte::utf8($string); $expected = array(11393, 11395, 11397, 11399, 11401, 11403, 11405, 11407, 11409, 11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425, 11427, 11429, 11431, 11433, 11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449, 11451, 11453, 11455, 11457, 11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473, 11475, 11477, 11479, 11481, 11483, 11485, 11487, 11489, 11491); $this->assertEquals($expected, $result); $string = '๏ฌ€๏ฌ๏ฌ‚๏ฌƒ๏ฌ„๏ฌ…๏ฌ†๏ฌ“๏ฌ”๏ฌ•๏ฌ–๏ฌ—'; $result = Multibyte::utf8($string); $expected = array(64256, 64257, 64258, 64259, 64260, 64261, 64262, 64275, 64276, 64277, 64278, 64279); $this->assertEquals($expected, $result); } /** * testAscii method * * @return void */ public function testAscii() { $input = array(33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126); $result = Multibyte::ascii($input); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $this->assertEquals($expected, $result); $input = array(161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200); $result = Multibyte::ascii($input); $expected = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $this->assertEquals($expected, $result); $input = array(201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300); $result = Multibyte::ascii($input); $expected = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $this->assertEquals($expected, $result); $input = array(301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400); $expected = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500); $expected = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700); $expected = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051); $expected = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100); $expected = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(1401, 1402, 1403, 1404, 1405, 1406, 1407); $expected = 'ีนีบีปีผีฝีพีฟ'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1609, 1610, 1611, 1612, 1613, 1614, 1615); $expected = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(10032, 10033, 10034, 10035, 10036, 10037, 10038, 10039, 10040, 10041, 10042, 10043, 10044, 10045, 10046, 10047, 10048, 10049, 10050, 10051, 10052, 10053, 10054, 10055, 10056, 10057, 10058, 10059, 10060, 10061, 10062, 10063, 10064, 10065, 10066, 10067, 10068, 10069, 10070, 10071, 10072, 10073, 10074, 10075, 10076, 10077, 10078); $expected = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(11904, 11905, 11906, 11907, 11908, 11909, 11910, 11911, 11912, 11913, 11914, 11915, 11916, 11917, 11918, 11919, 11920, 11921, 11922, 11923, 11924, 11925, 11926, 11927, 11928, 11929, 11931, 11932, 11933, 11934, 11935, 11936, 11937, 11938, 11939, 11940, 11941, 11942, 11943, 11944, 11945, 11946, 11947, 11948, 11949, 11950, 11951, 11952, 11953, 11954, 11955, 11956, 11957, 11958, 11959, 11960, 11961, 11962, 11963, 11964, 11965, 11966, 11967, 11968, 11969, 11970, 11971, 11972, 11973, 11974, 11975, 11976, 11977, 11978, 11979, 11980, 11981, 11982, 11983, 11984, 11985, 11986, 11987, 11988, 11989, 11990, 11991, 11992, 11993, 11994, 11995, 11996, 11997, 11998, 11999, 12000); $expected = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(12101, 12102, 12103, 12104, 12105, 12106, 12107, 12108, 12109, 12110, 12111, 12112, 12113, 12114, 12115, 12116, 12117, 12118, 12119, 12120, 12121, 12122, 12123, 12124, 12125, 12126, 12127, 12128, 12129, 12130, 12131, 12132, 12133, 12134, 12135, 12136, 12137, 12138, 12139, 12140, 12141, 12142, 12143, 12144, 12145, 12146, 12147, 12148, 12149, 12150, 12151, 12152, 12153, 12154, 12155, 12156, 12157, 12158, 12159); $expected = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(45601, 45602, 45603, 45604, 45605, 45606, 45607, 45608, 45609, 45610, 45611, 45612, 45613, 45614, 45615, 45616, 45617, 45618, 45619, 45620, 45621, 45622, 45623, 45624, 45625, 45626, 45627, 45628, 45629, 45630, 45631, 45632, 45633, 45634, 45635, 45636, 45637, 45638, 45639, 45640, 45641, 45642, 45643, 45644, 45645, 45646, 45647, 45648, 45649, 45650, 45651, 45652, 45653, 45654, 45655, 45656, 45657, 45658, 45659, 45660, 45661, 45662, 45663, 45664, 45665, 45666, 45667, 45668, 45669, 45670, 45671, 45672, 45673, 45674, 45675, 45676, 45677, 45678, 45679, 45680, 45681, 45682, 45683, 45684, 45685, 45686, 45687, 45688, 45689, 45690, 45691, 45692, 45693, 45694, 45695, 45696, 45697, 45698, 45699, 45700); $expected = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(65136, 65137, 65138, 65139, 65140, 65141, 65142, 65143, 65144, 65145, 65146, 65147, 65148, 65149, 65150, 65151, 65152, 65153, 65154, 65155, 65156, 65157, 65158, 65159, 65160, 65161, 65162, 65163, 65164, 65165, 65166, 65167, 65168, 65169, 65170, 65171, 65172, 65173, 65174, 65175, 65176, 65177, 65178, 65179, 65180, 65181, 65182, 65183, 65184, 65185, 65186, 65187, 65188, 65189, 65190, 65191, 65192, 65193, 65194, 65195, 65196, 65197, 65198, 65199, 65200); $expected = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(65201, 65202, 65203, 65204, 65205, 65206, 65207, 65208, 65209, 65210, 65211, 65212, 65213, 65214, 65215, 65216, 65217, 65218, 65219, 65220, 65221, 65222, 65223, 65224, 65225, 65226, 65227, 65228, 65229, 65230, 65231, 65232, 65233, 65234, 65235, 65236, 65237, 65238, 65239, 65240, 65241, 65242, 65243, 65244, 65245, 65246, 65247, 65248, 65249, 65250, 65251, 65252, 65253, 65254, 65255, 65256, 65257, 65258, 65259, 65260, 65261, 65262, 65263, 65264, 65265, 65266, 65267, 65268, 65269, 65270, 65271, 65272, 65273, 65274, 65275, 65276); $expected = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(65345, 65346, 65347, 65348, 65349, 65350, 65351, 65352, 65353, 65354, 65355, 65356, 65357, 65358, 65359, 65360, 65361, 65362, 65363, 65364, 65365, 65366, 65367, 65368, 65369, 65370); $expected = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(65377, 65378, 65379, 65380, 65381, 65382, 65383, 65384, 65385, 65386, 65387, 65388, 65389, 65390, 65391, 65392, 65393, 65394, 65395, 65396, 65397, 65398, 65399, 65400); $expected = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(65401, 65402, 65403, 65404, 65405, 65406, 65407, 65408, 65409, 65410, 65411, 65412, 65413, 65414, 65415, 65416, 65417, 65418, 65419, 65420, 65421, 65422, 65423, 65424, 65425, 65426, 65427, 65428, 65429, 65430, 65431, 65432, 65433, 65434, 65435, 65436, 65437, 65438); $expected = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(292, 275, 314, 316, 335, 44, 32, 372, 337, 345, 316, 271, 33); $expected = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33); $expected = 'Hello, World!'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(168); $expected = 'ยจ'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(191); $expected = 'ยฟ'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(269, 105, 110, 105); $expected = 'ฤini'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(109, 111, 263, 105); $expected = 'moฤ‡i'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(100, 114, 382, 97, 118, 110, 105); $expected = 'drลพavni'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(25226, 30334, 24230, 35774, 20026, 39318, 39029); $expected = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(19968, 20108, 19977, 21608, 27704, 40845); $expected = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(1280, 1282, 1284, 1286, 1288, 1290, 1292, 1294, 1296, 1298); $expected = 'ิ€ิ‚ิ„ิ†ิˆิŠิŒิŽิิ’'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(1281, 1283, 1285, 1287, 1289, 1291, 1293, 1295, 1296, 1298); $expected = 'ิิƒิ…ิ‡ิ‰ิ‹ิิิิ’'; $result = Multibyte::ascii($input); $this->assertEquals($expected, $result); $input = array(1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1415); $result = Multibyte::ascii($input); $expected = 'ิฑิฒิณิดิติถิทิธินิบิปิผิฝิพิฟี€ีี‚ีƒี„ี…ี†ี‡ีˆี‰ีŠี‹ีŒีีŽีีี‘ี’ี“ี”ี•ี–ึ‡'; $this->assertEquals($expected, $result); $input = array(1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415); $result = Multibyte::ascii($input); $expected = 'ีกีขีฃีคีฅีฆีงีจีฉีชีซีฌีญีฎีฏีฐีฑีฒีณีดีตีถีทีธีนีบีปีผีฝีพีฟึ€ึึ‚ึƒึ„ึ…ึ†ึ‡'; $this->assertEquals($expected, $result); $input = array(4256, 4257, 4258, 4259, 4260, 4261, 4262, 4263, 4264, 4265, 4266, 4267, 4268, 4269, 4270, 4271, 4272, 4273, 4274, 4275, 4276, 4277, 4278, 4279, 4280, 4281, 4282, 4283, 4284, 4285, 4286, 4287, 4288, 4289, 4290, 4291, 4292, 4293); $result = Multibyte::ascii($input); $expected = 'แ‚ แ‚กแ‚ขแ‚ฃแ‚คแ‚ฅแ‚ฆแ‚งแ‚จแ‚ฉแ‚ชแ‚ซแ‚ฌแ‚ญแ‚ฎแ‚ฏแ‚ฐแ‚ฑแ‚ฒแ‚ณแ‚ดแ‚ตแ‚ถแ‚ทแ‚ธแ‚นแ‚บแ‚ปแ‚ผแ‚ฝแ‚พแ‚ฟแƒ€แƒแƒ‚แƒƒแƒ„แƒ…'; $this->assertEquals($expected, $result); $input = array(7680, 7682, 7684, 7686, 7688, 7690, 7692, 7694, 7696, 7698, 7700, 7702, 7704, 7706, 7708, 7710, 7712, 7714, 7716, 7718, 7720, 7722, 7724, 7726, 7728, 7730, 7732, 7734, 7736, 7738, 7740, 7742, 7744, 7746, 7748, 7750, 7752, 7754, 7756, 7758, 7760, 7762, 7764, 7766, 7768, 7770, 7772, 7774, 7776, 7778, 7780, 7782, 7784, 7786, 7788, 7790, 7792, 7794, 7796, 7798, 7800, 7802, 7804, 7806, 7808, 7810, 7812, 7814, 7816, 7818, 7820, 7822, 7824, 7826, 7828, 7830, 7831, 7832, 7833, 7834, 7840, 7842, 7844, 7846, 7848, 7850, 7852, 7854, 7856, 7858, 7860, 7862, 7864, 7866, 7868, 7870, 7872, 7874, 7876, 7878, 7880, 7882, 7884, 7886, 7888, 7890, 7892, 7894, 7896, 7898, 7900, 7902, 7904, 7906, 7908, 7910, 7912, 7914, 7916, 7918, 7920, 7922, 7924, 7926, 7928); $result = Multibyte::ascii($input); $expected = 'แธ€แธ‚แธ„แธ†แธˆแธŠแธŒแธŽแธแธ’แธ”แธ–แธ˜แธšแธœแธžแธ แธขแธคแธฆแธจแธชแธฌแธฎแธฐแธฒแธดแธถแธธแธบแธผแธพแน€แน‚แน„แน†แนˆแนŠแนŒแนŽแนแน’แน”แน–แน˜แนšแนœแนžแน แนขแนคแนฆแนจแนชแนฌแนฎแนฐแนฒแนดแนถแนธแนบแนผแนพแบ€แบ‚แบ„แบ†แบˆแบŠแบŒแบŽแบแบ’แบ”แบ–แบ—แบ˜แบ™แบšแบ แบขแบคแบฆแบจแบชแบฌแบฎแบฐแบฒแบดแบถแบธแบบแบผแบพแป€แป‚แป„แป†แปˆแปŠแปŒแปŽแปแป’แป”แป–แป˜แปšแปœแปžแป แปขแปคแปฆแปจแปชแปฌแปฎแปฐแปฒแปดแปถแปธ'; $this->assertEquals($expected, $result); $input = array(7681, 7683, 7685, 7687, 7689, 7691, 7693, 7695, 7697, 7699, 7701, 7703, 7705, 7707, 7709, 7711, 7713, 7715, 7717, 7719, 7721, 7723, 7725, 7727, 7729, 7731, 7733, 7735, 7737, 7739, 7741, 7743, 7745, 7747, 7749, 7751, 7753, 7755, 7757, 7759, 7761, 7763, 7765, 7767, 7769, 7771, 7773, 7775, 7777, 7779, 7781, 7783, 7785, 7787, 7789, 7791, 7793, 7795, 7797, 7799, 7801, 7803, 7805, 7807, 7809, 7811, 7813, 7815, 7817, 7819, 7821, 7823, 7825, 7827, 7829, 7830, 7831, 7832, 7833, 7834, 7841, 7843, 7845, 7847, 7849, 7851, 7853, 7855, 7857, 7859, 7861, 7863, 7865, 7867, 7869, 7871, 7873, 7875, 7877, 7879, 7881, 7883, 7885, 7887, 7889, 7891, 7893, 7895, 7897, 7899, 7901, 7903, 7905, 7907, 7909, 7911, 7913, 7915, 7917, 7919, 7921, 7923, 7925, 7927, 7929); $result = Multibyte::ascii($input); $expected = 'แธแธƒแธ…แธ‡แธ‰แธ‹แธแธแธ‘แธ“แธ•แธ—แธ™แธ›แธแธŸแธกแธฃแธฅแธงแธฉแธซแธญแธฏแธฑแธณแธตแธทแธนแธปแธฝแธฟแนแนƒแน…แน‡แน‰แน‹แนแนแน‘แน“แน•แน—แน™แน›แนแนŸแนกแนฃแนฅแนงแนฉแนซแนญแนฏแนฑแนณแนตแนทแนนแนปแนฝแนฟแบแบƒแบ…แบ‡แบ‰แบ‹แบแบแบ‘แบ“แบ•แบ–แบ—แบ˜แบ™แบšแบกแบฃแบฅแบงแบฉแบซแบญแบฏแบฑแบณแบตแบทแบนแบปแบฝแบฟแปแปƒแป…แป‡แป‰แป‹แปแปแป‘แป“แป•แป—แป™แป›แปแปŸแปกแปฃแปฅแปงแปฉแปซแปญแปฏแปฑแปณแปตแปทแปน'; $this->assertEquals($expected, $result); $input = array(8486, 8490, 8491, 8498); $result = Multibyte::ascii($input); $expected = 'โ„ฆโ„ชโ„ซโ„ฒ'; $this->assertEquals($expected, $result); $input = array(969, 107, 229, 8526); $result = Multibyte::ascii($input); $expected = 'ฯ‰kรฅโ…Ž'; $this->assertEquals($expected, $result); $input = array(8544, 8545, 8546, 8547, 8548, 8549, 8550, 8551, 8552, 8553, 8554, 8555, 8556, 8557, 8558, 8559, 8579); $result = Multibyte::ascii($input); $expected = 'โ… โ…กโ…ขโ…ฃโ…คโ…ฅโ…ฆโ…งโ…จโ…ฉโ…ชโ…ซโ…ฌโ…ญโ…ฎโ…ฏโ†ƒ'; $this->assertEquals($expected, $result); $input = array(8560, 8561, 8562, 8563, 8564, 8565, 8566, 8567, 8568, 8569, 8570, 8571, 8572, 8573, 8574, 8575, 8580); $result = Multibyte::ascii($input); $expected = 'โ…ฐโ…ฑโ…ฒโ…ณโ…ดโ…ตโ…ถโ…ทโ…ธโ…นโ…บโ…ปโ…ผโ…ฝโ…พโ…ฟโ†„'; $this->assertEquals($expected, $result); $input = array(9398, 9399, 9400, 9401, 9402, 9403, 9404, 9405, 9406, 9407, 9408, 9409, 9410, 9411, 9412, 9413, 9414, 9415, 9416, 9417, 9418, 9419, 9420, 9421, 9422, 9423); $result = Multibyte::ascii($input); $expected = 'โ’ถโ’ทโ’ธโ’นโ’บโ’ปโ’ผโ’ฝโ’พโ’ฟโ“€โ“โ“‚โ“ƒโ“„โ“…โ“†โ“‡โ“ˆโ“‰โ“Šโ“‹โ“Œโ“โ“Žโ“'; $this->assertEquals($expected, $result); $input = array(9424, 9425, 9426, 9427, 9428, 9429, 9430, 9431, 9432, 9433, 9434, 9435, 9436, 9437, 9438, 9439, 9440, 9441, 9442, 9443, 9444, 9445, 9446, 9447, 9448, 9449); $result = Multibyte::ascii($input); $expected = 'โ“โ“‘โ“’โ““โ“”โ“•โ“–โ“—โ“˜โ“™โ“šโ“›โ“œโ“โ“žโ“Ÿโ“ โ“กโ“ขโ“ฃโ“คโ“ฅโ“ฆโ“งโ“จโ“ฉ'; $this->assertEquals($expected, $result); $input = array(11264, 11265, 11266, 11267, 11268, 11269, 11270, 11271, 11272, 11273, 11274, 11275, 11276, 11277, 11278, 11279, 11280, 11281, 11282, 11283, 11284, 11285, 11286, 11287, 11288, 11289, 11290, 11291, 11292, 11293, 11294, 11295, 11296, 11297, 11298, 11299, 11300, 11301, 11302, 11303, 11304, 11305, 11306, 11307, 11308, 11309, 11310); $result = Multibyte::ascii($input); $expected = 'โฐ€โฐโฐ‚โฐƒโฐ„โฐ…โฐ†โฐ‡โฐˆโฐ‰โฐŠโฐ‹โฐŒโฐโฐŽโฐโฐโฐ‘โฐ’โฐ“โฐ”โฐ•โฐ–โฐ—โฐ˜โฐ™โฐšโฐ›โฐœโฐโฐžโฐŸโฐ โฐกโฐขโฐฃโฐคโฐฅโฐฆโฐงโฐจโฐฉโฐชโฐซโฐฌโฐญโฐฎ'; $this->assertEquals($expected, $result); $input = array(11312, 11313, 11314, 11315, 11316, 11317, 11318, 11319, 11320, 11321, 11322, 11323, 11324, 11325, 11326, 11327, 11328, 11329, 11330, 11331, 11332, 11333, 11334, 11335, 11336, 11337, 11338, 11339, 11340, 11341, 11342, 11343, 11344, 11345, 11346, 11347, 11348, 11349, 11350, 11351, 11352, 11353, 11354, 11355, 11356, 11357, 11358); $result = Multibyte::ascii($input); $expected = 'โฐฐโฐฑโฐฒโฐณโฐดโฐตโฐถโฐทโฐธโฐนโฐบโฐปโฐผโฐฝโฐพโฐฟโฑ€โฑโฑ‚โฑƒโฑ„โฑ…โฑ†โฑ‡โฑˆโฑ‰โฑŠโฑ‹โฑŒโฑโฑŽโฑโฑโฑ‘โฑ’โฑ“โฑ”โฑ•โฑ–โฑ—โฑ˜โฑ™โฑšโฑ›โฑœโฑโฑž'; $this->assertEquals($expected, $result); $input = array(11392, 11394, 11396, 11398, 11400, 11402, 11404, 11406, 11408, 11410, 11412, 11414, 11416, 11418, 11420, 11422, 11424, 11426, 11428, 11430, 11432, 11434, 11436, 11438, 11440, 11442, 11444, 11446, 11448, 11450, 11452, 11454, 11456, 11458, 11460, 11462, 11464, 11466, 11468, 11470, 11472, 11474, 11476, 11478, 11480, 11482, 11484, 11486, 11488, 11490); $result = Multibyte::ascii($input); $expected = 'โฒ€โฒ‚โฒ„โฒ†โฒˆโฒŠโฒŒโฒŽโฒโฒ’โฒ”โฒ–โฒ˜โฒšโฒœโฒžโฒ โฒขโฒคโฒฆโฒจโฒชโฒฌโฒฎโฒฐโฒฒโฒดโฒถโฒธโฒบโฒผโฒพโณ€โณ‚โณ„โณ†โณˆโณŠโณŒโณŽโณโณ’โณ”โณ–โณ˜โณšโณœโณžโณ โณข'; $this->assertEquals($expected, $result); $input = array(11393, 11395, 11397, 11399, 11401, 11403, 11405, 11407, 11409, 11411, 11413, 11415, 11417, 11419, 11421, 11423, 11425, 11427, 11429, 11431, 11433, 11435, 11437, 11439, 11441, 11443, 11445, 11447, 11449, 11451, 11453, 11455, 11457, 11459, 11461, 11463, 11465, 11467, 11469, 11471, 11473, 11475, 11477, 11479, 11481, 11483, 11485, 11487, 11489, 11491); $result = Multibyte::ascii($input); $expected = 'โฒโฒƒโฒ…โฒ‡โฒ‰โฒ‹โฒโฒโฒ‘โฒ“โฒ•โฒ—โฒ™โฒ›โฒโฒŸโฒกโฒฃโฒฅโฒงโฒฉโฒซโฒญโฒฏโฒฑโฒณโฒตโฒทโฒนโฒปโฒฝโฒฟโณโณƒโณ…โณ‡โณ‰โณ‹โณโณโณ‘โณ“โณ•โณ—โณ™โณ›โณโณŸโณกโณฃ'; $this->assertEquals($expected, $result); $input = array(64256, 64257, 64258, 64259, 64260, 64261, 64262, 64275, 64276, 64277, 64278, 64279); $result = Multibyte::ascii($input); $expected = '๏ฌ€๏ฌ๏ฌ‚๏ฌƒ๏ฌ„๏ฌ…๏ฌ†๏ฌ“๏ฌ”๏ฌ•๏ฌ–๏ฌ—'; $this->assertEquals($expected, $result); } /** * testUsingMbStripos method * * @return void */ public function testUsingMbStripos() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'f'; $result = mb_stripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQFRSTUVWXYZ0123456789'; $find = 'f'; $result = mb_stripos($string, $find, 6); $expected = 17; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'รฅ'; $result = mb_stripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรž'; $find = 'รฅ'; $result = mb_stripos($string, $find, 6); $expected = 24; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤ‹'; $result = mb_stripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลฤŠลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤ‹'; $result = mb_stripos($string, $find, 6); $expected = 32; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'f'; $result = mb_stripos($string, $find); $expected = 37; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ฮœ'; $result = mb_stripos($string, $find); $expected = 20; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'ร‰'; $result = mb_stripos($string, $find, 6); $expected = 32; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = mb_stripos($string, $find); $expected = 24; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = mb_stripos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = mb_stripos($string, $find, 40); $expected = 40; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ฦฆ'; $result = mb_stripos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ั—'; $result = mb_stripos($string, $find); $expected = 7; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = mb_stripos($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = mb_stripos($string, $find, 5); $expected = 36; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = mb_stripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = mb_stripos($string, $find); $expected = 15; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = mb_stripos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = mb_stripos($string, $find); $expected = 31; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = mb_stripos($string, $find); $expected = 26; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = mb_stripos($string, $find); $expected = 46; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = mb_stripos($string, $find); $expected = 45; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_stripos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ผซ'; $result = mb_stripos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = mb_stripos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = mb_stripos($string, $find); $expected = 17; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_stripos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล'; $result = mb_stripos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'O'; $result = mb_stripos($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_stripos($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_stripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'N'; $result = mb_stripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_stripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ†'; $result = mb_stripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = mb_stripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลฝ'; $result = mb_stripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = mb_stripos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = mb_stripos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'Dลฝ'; $result = mb_stripos($string, $find); $expected = false; $this->assertEquals($expected, $result); } /** * testMultibyteStripos method * * @return void */ public function testMultibyteStripos() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'f'; $result = Multibyte::stripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQFRSTUVWXYZ0123456789'; $find = 'f'; $result = Multibyte::stripos($string, $find, 6); $expected = 17; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'รฅ'; $result = Multibyte::stripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรž'; $find = 'รฅ'; $result = Multibyte::stripos($string, $find, 6); $expected = 24; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤ‹'; $result = Multibyte::stripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลฤŠลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤ‹'; $result = Multibyte::stripos($string, $find, 6); $expected = 32; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'f'; $result = Multibyte::stripos($string, $find); $expected = 37; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ฮœ'; $result = Multibyte::stripos($string, $find); $expected = 20; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'ร‰'; $result = Multibyte::stripos($string, $find, 6); $expected = 32; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = Multibyte::stripos($string, $find); $expected = 24; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = Multibyte::stripos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = Multibyte::stripos($string, $find, 40); $expected = 40; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ฦฆ'; $result = Multibyte::stripos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ั—'; $result = Multibyte::stripos($string, $find); $expected = 7; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = Multibyte::stripos($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = Multibyte::stripos($string, $find, 5); $expected = 36; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = Multibyte::stripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = Multibyte::stripos($string, $find); $expected = 15; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = Multibyte::stripos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = Multibyte::stripos($string, $find); $expected = 31; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = Multibyte::stripos($string, $find); $expected = 26; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = Multibyte::stripos($string, $find); $expected = 46; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = Multibyte::stripos($string, $find); $expected = 45; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::stripos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ผซ'; $result = Multibyte::stripos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = Multibyte::stripos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = Multibyte::stripos($string, $find); $expected = 17; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::stripos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล'; $result = Multibyte::stripos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'O'; $result = Multibyte::stripos($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::stripos($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::stripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'N'; $result = Multibyte::stripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::stripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ†'; $result = Multibyte::stripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = Multibyte::stripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลฝ'; $result = Multibyte::stripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = Multibyte::stripos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = Multibyte::stripos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'Dลฝ'; $result = Multibyte::stripos($string, $find); $expected = false; $this->assertEquals($expected, $result); } /** * testUsingMbStristr method * * @return void */ public function testUsingMbStristr() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'f'; $result = mb_stristr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ0123456789'; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'f'; $result = mb_stristr($string, $find, true); $expected = 'ABCDE'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'รฅ'; $result = mb_stristr($string, $find); $expected = 'ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'รฅ'; $result = mb_stristr($string, $find, true); $expected = 'ร€รร‚รƒร„'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤ‹'; $result = mb_stristr($string, $find); $expected = 'ฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤ‹'; $result = mb_stristr($string, $find, true); $expected = 'ฤ€ฤ‚ฤ„ฤ†ฤˆ'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'f'; $result = mb_stristr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'f'; $result = mb_stristr($string, $find, true); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDE'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ฮœ'; $result = mb_stristr($string, $find); $expected = 'ยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ฮœ'; $result = mb_stristr($string, $find, true); $expected = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยด'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รพ'; $result = mb_stristr($string, $find); $expected = 'รžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รพ'; $result = mb_stristr($string, $find, true); $expected = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœร'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = mb_stristr($string, $find); $expected = 'ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = mb_stristr($string, $find, true); $expected = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„'; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = mb_stristr($string, $find); $expected = 'ฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $this->assertEquals($expected, $result); $find = 'ฦธ'; $result = mb_stristr($string, $find, true); $expected = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦท'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ฦฆ'; $result = mb_stristr($string, $find); $expected = 'ส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ฦฆ'; $result = mb_stristr($string, $find, true); $expected = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟ'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ั—'; $result = mb_stristr($string, $find); $expected = 'ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ั—'; $result = mb_stristr($string, $find, true); $expected = 'ะ€ะะ‚ะƒะ„ะ…ะ†'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = mb_stristr($string, $find); $expected = 'ะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = mb_stristr($string, $find, true); $expected = 'ะœะะžะŸ'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = mb_stristr($string, $find); $expected = 'ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = mb_stristr($string, $find, true); $expected = 'ูู‚ูƒู„ู…'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = mb_stristr($string, $find); $expected = 'โœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = mb_stristr($string, $find, true); $expected = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพ'; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = mb_stristr($string, $find); $expected = 'โบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = mb_stristr($string, $find, true); $expected = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = mb_stristr($string, $find); $expected = 'โฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = mb_stristr($string, $find, true); $expected = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃ'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = mb_stristr($string, $find); $expected = '๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = mb_stristr($string, $find, true); $expected = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = mb_stristr($string, $find); $expected = '๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = mb_stristr($string, $find, true); $expected = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = mb_stristr($string, $find); $expected = '๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = mb_stristr($string, $find, true); $expected = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ผซ'; $result = mb_stristr($string, $find); $expected = '๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ผซ'; $result = mb_stristr($string, $find, true); $expected = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = mb_stristr($string, $find); $expected = '๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = mb_stristr($string, $find, true); $expected = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = mb_stristr($string, $find); $expected = '๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = mb_stristr($string, $find, true); $expected = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล'; $result = mb_stristr($string, $find); $expected = 'ล‘ล™ฤผฤ!'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล'; $result = mb_stristr($string, $find, true); $expected = 'ฤคฤ“ฤบฤผล, ลด'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ฤบฤผ'; $result = mb_stristr($string, $find, true); $expected = 'ฤคฤ“'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'O'; $result = mb_stristr($string, $find); $expected = 'o, World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'O'; $result = mb_stristr($string, $find, true); $expected = 'Hell'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = mb_stristr($string, $find); $expected = 'World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = mb_stristr($string, $find, true); $expected = 'Hello, '; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = mb_stristr($string, $find); $expected = 'llo, World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = mb_stristr($string, $find, true); $expected = 'He'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = mb_stristr($string, $find); $expected = 'rld!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = mb_stristr($string, $find, true); $expected = 'Hello, Wo'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'N'; $result = mb_stristr($string, $find); $expected = 'ni'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'N'; $result = mb_stristr($string, $find, true); $expected = 'ฤi'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ†'; $result = mb_stristr($string, $find); $expected = 'ฤ‡i'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ†'; $result = mb_stristr($string, $find, true); $expected = 'mo'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลฝ'; $result = mb_stristr($string, $find); $expected = 'ลพavni'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลฝ'; $result = mb_stristr($string, $find, true); $expected = 'dr'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = mb_stristr($string, $find); $expected = '่ฎพไธบ้ฆ–้กต'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = mb_stristr($string, $find, true); $expected = 'ๆŠŠ็™พๅบฆ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = mb_stristr($string, $find); $expected = 'ๅ‘จๆฐธ้พ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = mb_stristr($string, $find, true); $expected = 'ไธ€ไบŒไธ‰'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ไบŒๅ‘จ'; $result = mb_stristr($string, $find); $expected = false; $this->assertEquals($expected, $result); } /** * testMultibyteStristr method * * @return void */ public function testMultibyteStristr() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'f'; $result = Multibyte::stristr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ0123456789'; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'f'; $result = Multibyte::stristr($string, $find, true); $expected = 'ABCDE'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'รฅ'; $result = Multibyte::stristr($string, $find); $expected = 'ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'รฅ'; $result = Multibyte::stristr($string, $find, true); $expected = 'ร€รร‚รƒร„'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤ‹'; $result = Multibyte::stristr($string, $find); $expected = 'ฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤ‹'; $result = Multibyte::stristr($string, $find, true); $expected = 'ฤ€ฤ‚ฤ„ฤ†ฤˆ'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'f'; $result = Multibyte::stristr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'f'; $result = Multibyte::stristr($string, $find, true); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDE'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ฮœ'; $result = Multibyte::stristr($string, $find); $expected = 'ยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ฮœ'; $result = Multibyte::stristr($string, $find, true); $expected = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยด'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รพ'; $result = Multibyte::stristr($string, $find); $expected = 'รžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รพ'; $result = Multibyte::stristr($string, $find, true); $expected = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœร'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = Multibyte::stristr($string, $find); $expected = 'ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = Multibyte::stristr($string, $find, true); $expected = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„'; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = Multibyte::stristr($string, $find); $expected = 'ฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $this->assertEquals($expected, $result); $find = 'ฦธ'; $result = Multibyte::stristr($string, $find, true); $expected = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦท'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ฦฆ'; $result = Multibyte::stristr($string, $find); $expected = 'ส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ฦฆ'; $result = Multibyte::stristr($string, $find, true); $expected = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟ'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ั—'; $result = Multibyte::stristr($string, $find); $expected = 'ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ั—'; $result = Multibyte::stristr($string, $find, true); $expected = 'ะ€ะะ‚ะƒะ„ะ…ะ†'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = Multibyte::stristr($string, $find); $expected = 'ะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = Multibyte::stristr($string, $find, true); $expected = 'ะœะะžะŸ'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = Multibyte::stristr($string, $find); $expected = 'ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = Multibyte::stristr($string, $find, true); $expected = 'ูู‚ูƒู„ู…'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = Multibyte::stristr($string, $find); $expected = 'โœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = Multibyte::stristr($string, $find, true); $expected = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพ'; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = Multibyte::stristr($string, $find); $expected = 'โบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = Multibyte::stristr($string, $find, true); $expected = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = Multibyte::stristr($string, $find); $expected = 'โฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = Multibyte::stristr($string, $find, true); $expected = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃ'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = Multibyte::stristr($string, $find); $expected = '๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = Multibyte::stristr($string, $find, true); $expected = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = Multibyte::stristr($string, $find); $expected = '๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = Multibyte::stristr($string, $find, true); $expected = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = Multibyte::stristr($string, $find); $expected = '๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = Multibyte::stristr($string, $find, true); $expected = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ผซ'; $result = Multibyte::stristr($string, $find); $expected = '๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ผซ'; $result = Multibyte::stristr($string, $find, true); $expected = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = Multibyte::stristr($string, $find); $expected = '๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = Multibyte::stristr($string, $find, true); $expected = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = Multibyte::stristr($string, $find); $expected = '๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = Multibyte::stristr($string, $find, true); $expected = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล'; $result = Multibyte::stristr($string, $find); $expected = 'ล‘ล™ฤผฤ!'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล'; $result = Multibyte::stristr($string, $find, true); $expected = 'ฤคฤ“ฤบฤผล, ลด'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ฤบฤผ'; $result = Multibyte::stristr($string, $find, true); $expected = 'ฤคฤ“'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'O'; $result = Multibyte::stristr($string, $find); $expected = 'o, World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'O'; $result = Multibyte::stristr($string, $find, true); $expected = 'Hell'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = Multibyte::stristr($string, $find); $expected = 'World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = Multibyte::stristr($string, $find, true); $expected = 'Hello, '; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = Multibyte::stristr($string, $find); $expected = 'llo, World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = Multibyte::stristr($string, $find, true); $expected = 'He'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = Multibyte::stristr($string, $find); $expected = 'rld!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = Multibyte::stristr($string, $find, true); $expected = 'Hello, Wo'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'N'; $result = Multibyte::stristr($string, $find); $expected = 'ni'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'N'; $result = Multibyte::stristr($string, $find, true); $expected = 'ฤi'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ†'; $result = Multibyte::stristr($string, $find); $expected = 'ฤ‡i'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ†'; $result = Multibyte::stristr($string, $find, true); $expected = 'mo'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลฝ'; $result = Multibyte::stristr($string, $find); $expected = 'ลพavni'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลฝ'; $result = Multibyte::stristr($string, $find, true); $expected = 'dr'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = Multibyte::stristr($string, $find); $expected = '่ฎพไธบ้ฆ–้กต'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = Multibyte::stristr($string, $find, true); $expected = 'ๆŠŠ็™พๅบฆ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = Multibyte::stristr($string, $find); $expected = 'ๅ‘จๆฐธ้พ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = Multibyte::stristr($string, $find, true); $expected = 'ไธ€ไบŒไธ‰'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ไบŒๅ‘จ'; $result = Multibyte::stristr($string, $find); $expected = false; $this->assertEquals($expected, $result); } /** * testUsingMbStrlen method * * @return void */ public function testUsingMbStrlen() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $result = mb_strlen($string); $expected = 36; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $result = mb_strlen($string); $expected = 30; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $result = mb_strlen($string); $expected = 61; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $result = mb_strlen($string); $expected = 94; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $result = mb_strlen($string); $expected = 40; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $result = mb_strlen($string); $expected = 100; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $result = mb_strlen($string); $expected = 100; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $result = mb_strlen($string); $expected = 100; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $result = mb_strlen($string); $expected = 100; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $result = mb_strlen($string); $expected = 28; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $result = mb_strlen($string); $expected = 49; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $result = mb_strlen($string); $expected = 15; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $result = mb_strlen($string); $expected = 47; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $result = mb_strlen($string); $expected = 96; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $result = mb_strlen($string); $expected = 59; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $result = mb_strlen($string); $expected = 100; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $result = mb_strlen($string); $expected = 65; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $result = mb_strlen($string); $expected = 76; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $result = mb_strlen($string); $expected = 26; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $result = mb_strlen($string); $expected = 24; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $result = mb_strlen($string); $expected = 38; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $result = mb_strlen($string); $expected = 13; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $result = mb_strlen($string); $expected = 13; $this->assertEquals($expected, $result); $string = 'ฤini'; $result = mb_strlen($string); $expected = 4; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $result = mb_strlen($string); $expected = 4; $this->assertEquals($expected, $result); $string = 'drลพavni'; $result = mb_strlen($string); $expected = 7; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $result = mb_strlen($string); $expected = 7; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $result = mb_strlen($string); $expected = 6; $this->assertEquals($expected, $result); } /** * testMultibyteStrlen method * * @return void */ public function testMultibyteStrlen() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $result = Multibyte::strlen($string); $expected = 36; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $result = Multibyte::strlen($string); $expected = 30; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $result = Multibyte::strlen($string); $expected = 61; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $result = Multibyte::strlen($string); $expected = 94; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $result = Multibyte::strlen($string); $expected = 40; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $result = Multibyte::strlen($string); $expected = 100; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $result = Multibyte::strlen($string); $expected = 100; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $result = Multibyte::strlen($string); $expected = 100; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $result = Multibyte::strlen($string); $expected = 100; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $result = Multibyte::strlen($string); $expected = 28; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $result = Multibyte::strlen($string); $expected = 49; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $result = Multibyte::strlen($string); $expected = 15; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $result = Multibyte::strlen($string); $expected = 47; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $result = Multibyte::strlen($string); $expected = 96; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $result = Multibyte::strlen($string); $expected = 59; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $result = Multibyte::strlen($string); $expected = 100; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $result = Multibyte::strlen($string); $expected = 65; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $result = Multibyte::strlen($string); $expected = 76; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $result = Multibyte::strlen($string); $expected = 26; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $result = Multibyte::strlen($string); $expected = 24; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $result = Multibyte::strlen($string); $expected = 38; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $result = Multibyte::strlen($string); $expected = 13; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $result = Multibyte::strlen($string); $expected = 13; $this->assertEquals($expected, $result); $string = 'ฤini'; $result = Multibyte::strlen($string); $expected = 4; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $result = Multibyte::strlen($string); $expected = 4; $this->assertEquals($expected, $result); $string = 'drลพavni'; $result = Multibyte::strlen($string); $expected = 7; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $result = Multibyte::strlen($string); $expected = 7; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $result = Multibyte::strlen($string); $expected = 6; $this->assertEquals($expected, $result); } /** * testUsingMbStrpos method * * @return void */ public function testUsingMbStrpos() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = mb_strpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQFRSTUVWXYZ0123456789'; $find = 'F'; $result = mb_strpos($string, $find, 6); $expected = 17; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = mb_strpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรž'; $find = 'ร…'; $result = mb_strpos($string, $find, 6); $expected = 24; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_strpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลฤŠลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_strpos($string, $find, 6); $expected = 32; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = mb_strpos($string, $find); $expected = 37; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = mb_strpos($string, $find); $expected = 20; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รฉ'; $result = mb_strpos($string, $find); $expected = 32; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = mb_strpos($string, $find); $expected = 24; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = mb_strpos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦน'; $result = mb_strpos($string, $find); $expected = 40; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = mb_strpos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = mb_strpos($string, $find); $expected = 7; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = mb_strpos($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ั€'; $result = mb_strpos($string, $find, 5); $expected = 36; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = mb_strpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = mb_strpos($string, $find); $expected = 15; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = mb_strpos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = mb_strpos($string, $find); $expected = 31; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = mb_strpos($string, $find); $expected = 26; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = mb_strpos($string, $find); $expected = 46; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = mb_strpos($string, $find); $expected = 45; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_strpos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_strpos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = mb_strpos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = mb_strpos($string, $find); $expected = 17; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_strpos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_strpos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘ล™'; $result = mb_strpos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_strpos($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_strpos($string, $find, 5); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_strpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_strpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_strpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_strpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = mb_strpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = mb_strpos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = mb_strpos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ไธ€ๅ‘จ'; $result = mb_strpos($string, $find); $expected = false; $this->assertEquals($expected, $result); } /** * testMultibyteStrpos method * * @return void */ public function testMultibyteStrpos() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = Multibyte::strpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQFRSTUVWXYZ0123456789'; $find = 'F'; $result = Multibyte::strpos($string, $find, 6); $expected = 17; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = Multibyte::strpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรž'; $find = 'ร…'; $result = Multibyte::strpos($string, $find, 6); $expected = 24; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::strpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลฤŠลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::strpos($string, $find, 6); $expected = 32; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = Multibyte::strpos($string, $find); $expected = 37; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = Multibyte::strpos($string, $find); $expected = 20; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รฉ'; $result = Multibyte::strpos($string, $find); $expected = 32; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = Multibyte::strpos($string, $find); $expected = 24; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = Multibyte::strpos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦน'; $result = Multibyte::strpos($string, $find); $expected = 40; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = Multibyte::strpos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = Multibyte::strpos($string, $find); $expected = 7; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = Multibyte::strpos($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ั€'; $result = Multibyte::strpos($string, $find, 5); $expected = 36; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = Multibyte::strpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = Multibyte::strpos($string, $find); $expected = 15; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = Multibyte::strpos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = Multibyte::strpos($string, $find); $expected = 31; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = Multibyte::strpos($string, $find); $expected = 26; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = Multibyte::strpos($string, $find); $expected = 46; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = Multibyte::strpos($string, $find); $expected = 45; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::strpos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::strpos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = Multibyte::strpos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = Multibyte::strpos($string, $find); $expected = 17; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::strpos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::strpos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘ล™'; $result = Multibyte::strpos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::strpos($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::strpos($string, $find, 5); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::strpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::strpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::strpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::strpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = Multibyte::strpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = Multibyte::strpos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = Multibyte::strpos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ไธ€ๅ‘จ'; $result = Multibyte::strpos($string, $find); $expected = false; $this->assertEquals($expected, $result); } /** * testUsingMbStrrchr method * * @return void */ public function testUsingMbStrrchr() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = mb_strrchr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ0123456789'; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = mb_strrchr($string, $find, true); $expected = 'ABCDE'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = mb_strrchr($string, $find); $expected = 'ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = mb_strrchr($string, $find, true); $expected = 'ร€รร‚รƒร„'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_strrchr($string, $find); $expected = 'ฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_strrchr($string, $find, true); $expected = 'ฤ€ฤ‚ฤ„ฤ†ฤˆ'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = mb_strrchr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = mb_strrchr($string, $find, true); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDE'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = mb_strrchr($string, $find); $expected = 'ยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = mb_strrchr($string, $find, true); $expected = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยด'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รž'; $result = mb_strrchr($string, $find); $expected = 'รžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รž'; $result = mb_strrchr($string, $find, true); $expected = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœร'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = mb_strrchr($string, $find); $expected = 'ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = mb_strrchr($string, $find, true); $expected = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„'; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = mb_strrchr($string, $find); $expected = 'ฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $this->assertEquals($expected, $result); $find = 'ฦธ'; $result = mb_strrchr($string, $find, true); $expected = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦท'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = mb_strrchr($string, $find); $expected = 'ส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = mb_strrchr($string, $find, true); $expected = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟ'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = mb_strrchr($string, $find); $expected = 'ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = mb_strrchr($string, $find, true); $expected = 'ะ€ะะ‚ะƒะ„ะ…ะ†'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = mb_strrchr($string, $find); $expected = 'ะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = mb_strrchr($string, $find, true); $expected = 'ะœะะžะŸ'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = mb_strrchr($string, $find); $expected = 'ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = mb_strrchr($string, $find, true); $expected = 'ูู‚ูƒู„ู…'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = mb_strrchr($string, $find); $expected = 'โœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = mb_strrchr($string, $find, true); $expected = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพ'; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = mb_strrchr($string, $find); $expected = 'โบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = mb_strrchr($string, $find, true); $expected = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = mb_strrchr($string, $find); $expected = 'โฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = mb_strrchr($string, $find, true); $expected = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃ'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = mb_strrchr($string, $find); $expected = '๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = mb_strrchr($string, $find, true); $expected = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = mb_strrchr($string, $find); $expected = '๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = mb_strrchr($string, $find, true); $expected = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = mb_strrchr($string, $find); $expected = '๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = mb_strrchr($string, $find, true); $expected = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_strrchr($string, $find); $expected = '๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_strrchr($string, $find, true); $expected = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = mb_strrchr($string, $find); $expected = '๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = mb_strrchr($string, $find, true); $expected = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = mb_strrchr($string, $find); $expected = '๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = mb_strrchr($string, $find, true); $expected = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_strrchr($string, $find); $expected = 'ล‘ล™ฤผฤ!'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_strrchr($string, $find, true); $expected = 'ฤคฤ“ฤบฤผล, ลด'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_strrchr($string, $find); $expected = 'orld!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_strrchr($string, $find, true); $expected = 'Hello, W'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = mb_strrchr($string, $find); $expected = 'World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = mb_strrchr($string, $find, true); $expected = 'Hello, '; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = mb_strrchr($string, $find); $expected = 'llo, World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = mb_strrchr($string, $find, true); $expected = 'He'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = mb_strrchr($string, $find); $expected = 'rld!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = mb_strrchr($string, $find, true); $expected = 'Hello, Wo'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_strrchr($string, $find); $expected = 'ni'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_strrchr($string, $find, true); $expected = 'ฤi'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_strrchr($string, $find); $expected = 'ฤ‡i'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_strrchr($string, $find, true); $expected = 'mo'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = mb_strrchr($string, $find); $expected = 'ลพavni'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = mb_strrchr($string, $find, true); $expected = 'dr'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = mb_strrchr($string, $find); $expected = '่ฎพไธบ้ฆ–้กต'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = mb_strrchr($string, $find, true); $expected = 'ๆŠŠ็™พๅบฆ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = mb_strrchr($string, $find); $expected = 'ๅ‘จๆฐธ้พ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = mb_strrchr($string, $find, true); $expected = 'ไธ€ไบŒไธ‰'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ้พ'; $result = mb_strrchr($string, $find, true); $expected = false; $this->assertEquals($expected, $result); } /** * testMultibyteStrrchr method * * @return void */ public function testMultibyteStrrchr() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = Multibyte::strrchr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ0123456789'; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ABCDE'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = Multibyte::strrchr($string, $find); $expected = 'ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ร€รร‚รƒร„'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::strrchr($string, $find); $expected = 'ฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ฤ€ฤ‚ฤ„ฤ†ฤˆ'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = Multibyte::strrchr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = Multibyte::strrchr($string, $find, true); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDE'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = Multibyte::strrchr($string, $find); $expected = 'ยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยด'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รž'; $result = Multibyte::strrchr($string, $find); $expected = 'รžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รž'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœร'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = Multibyte::strrchr($string, $find); $expected = 'ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„'; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = Multibyte::strrchr($string, $find); $expected = 'ฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $this->assertEquals($expected, $result); $find = 'ฦธ'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦท'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = Multibyte::strrchr($string, $find); $expected = 'ส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟ'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = Multibyte::strrchr($string, $find); $expected = 'ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ะ€ะะ‚ะƒะ„ะ…ะ†'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = Multibyte::strrchr($string, $find); $expected = 'ะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = Multibyte::strrchr($string, $find, true); $expected = 'ะœะะžะŸ'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = Multibyte::strrchr($string, $find); $expected = 'ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ูู‚ูƒู„ู…'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = Multibyte::strrchr($string, $find); $expected = 'โœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = Multibyte::strrchr($string, $find, true); $expected = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพ'; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = Multibyte::strrchr($string, $find); $expected = 'โบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = Multibyte::strrchr($string, $find, true); $expected = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = Multibyte::strrchr($string, $find); $expected = 'โฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = Multibyte::strrchr($string, $find, true); $expected = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃ'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = Multibyte::strrchr($string, $find); $expected = '๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = Multibyte::strrchr($string, $find, true); $expected = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = Multibyte::strrchr($string, $find); $expected = '๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = Multibyte::strrchr($string, $find, true); $expected = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = Multibyte::strrchr($string, $find); $expected = '๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = Multibyte::strrchr($string, $find, true); $expected = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::strrchr($string, $find); $expected = '๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::strrchr($string, $find, true); $expected = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = Multibyte::strrchr($string, $find); $expected = '๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = Multibyte::strrchr($string, $find, true); $expected = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = Multibyte::strrchr($string, $find); $expected = '๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = Multibyte::strrchr($string, $find, true); $expected = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::strrchr($string, $find); $expected = 'ล‘ล™ฤผฤ!'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ฤคฤ“ฤบฤผล, ลด'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::strrchr($string, $find); $expected = 'orld!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::strrchr($string, $find, true); $expected = 'Hello, W'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = Multibyte::strrchr($string, $find); $expected = 'World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = Multibyte::strrchr($string, $find, true); $expected = 'Hello, '; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = Multibyte::strrchr($string, $find); $expected = 'llo, World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = Multibyte::strrchr($string, $find, true); $expected = 'He'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = Multibyte::strrchr($string, $find); $expected = 'rld!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = Multibyte::strrchr($string, $find, true); $expected = 'Hello, Wo'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::strrchr($string, $find); $expected = 'ni'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ฤi'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::strrchr($string, $find); $expected = 'ฤ‡i'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::strrchr($string, $find, true); $expected = 'mo'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = Multibyte::strrchr($string, $find); $expected = 'ลพavni'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = Multibyte::strrchr($string, $find, true); $expected = 'dr'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = Multibyte::strrchr($string, $find); $expected = '่ฎพไธบ้ฆ–้กต'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ๆŠŠ็™พๅบฆ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = Multibyte::strrchr($string, $find); $expected = 'ๅ‘จๆฐธ้พ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = Multibyte::strrchr($string, $find, true); $expected = 'ไธ€ไบŒไธ‰'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ้พ'; $result = Multibyte::strrchr($string, $find, true); $expected = false; $this->assertEquals($expected, $result); } /** * testUsingMbStrrichr method * * @return void */ public function testUsingMbStrrichr() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = mb_strrichr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ0123456789'; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = mb_strrichr($string, $find, true); $expected = 'ABCDE'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = mb_strrichr($string, $find); $expected = 'ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = mb_strrichr($string, $find, true); $expected = 'ร€รร‚รƒร„'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_strrichr($string, $find); $expected = 'ฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_strrichr($string, $find, true); $expected = 'ฤ€ฤ‚ฤ„ฤ†ฤˆ'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = mb_strrichr($string, $find); $expected = 'fghijklmnopqrstuvwxyz{|}~'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = mb_strrichr($string, $find, true); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcde'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = mb_strrichr($string, $find); $expected = 'ยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = mb_strrichr($string, $find, true); $expected = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยด'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รž'; $result = mb_strrichr($string, $find); $expected = 'รพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รž'; $result = mb_strrichr($string, $find, true); $expected = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝ'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = mb_strrichr($string, $find); $expected = 'ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = mb_strrichr($string, $find, true); $expected = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…'; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = mb_strrichr($string, $find); $expected = 'ฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $this->assertEquals($expected, $result); $find = 'ฦธ'; $result = mb_strrichr($string, $find, true); $expected = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธ'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = mb_strrichr($string, $find); $expected = 'ส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = mb_strrichr($string, $find, true); $expected = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟ'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = mb_strrichr($string, $find); $expected = 'ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = mb_strrichr($string, $find, true); $expected = 'ะ€ะะ‚ะƒะ„ะ…ะ†'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = mb_strrichr($string, $find); $expected = 'ั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟ'; $find = 'ะ '; $result = mb_strrichr($string, $find, true); $expected = 'ะœะะžะŸ'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = mb_strrichr($string, $find); $expected = 'ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = mb_strrichr($string, $find, true); $expected = 'ูู‚ูƒู„ู…'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = mb_strrichr($string, $find); $expected = 'โœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = mb_strrichr($string, $find, true); $expected = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพ'; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = mb_strrichr($string, $find); $expected = 'โบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = mb_strrichr($string, $find, true); $expected = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = mb_strrichr($string, $find); $expected = 'โฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = mb_strrichr($string, $find, true); $expected = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃ'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = mb_strrichr($string, $find); $expected = '๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = mb_strrichr($string, $find, true); $expected = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = mb_strrichr($string, $find); $expected = '๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = mb_strrichr($string, $find, true); $expected = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = mb_strrichr($string, $find); $expected = '๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = mb_strrichr($string, $find, true); $expected = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_strrichr($string, $find); $expected = '๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_strrichr($string, $find, true); $expected = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = mb_strrichr($string, $find); $expected = '๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = mb_strrichr($string, $find, true); $expected = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = mb_strrichr($string, $find); $expected = '๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = mb_strrichr($string, $find, true); $expected = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_strrichr($string, $find); $expected = 'ล‘ล™ฤผฤ!'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_strrichr($string, $find, true); $expected = 'ฤคฤ“ฤบฤผล, ลด'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_strrichr($string, $find); $expected = 'orld!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_strrichr($string, $find, true); $expected = 'Hello, W'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = mb_strrichr($string, $find); $expected = 'World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = mb_strrichr($string, $find, true); $expected = 'Hello, '; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = mb_strrichr($string, $find); $expected = 'llo, World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = mb_strrichr($string, $find, true); $expected = 'He'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = mb_strrichr($string, $find); $expected = 'rld!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = mb_strrichr($string, $find, true); $expected = 'Hello, Wo'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_strrichr($string, $find); $expected = 'ni'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_strrichr($string, $find, true); $expected = 'ฤi'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_strrichr($string, $find); $expected = 'ฤ‡i'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_strrichr($string, $find, true); $expected = 'mo'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = mb_strrichr($string, $find); $expected = 'ลพavni'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = mb_strrichr($string, $find, true); $expected = 'dr'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = mb_strrichr($string, $find); $expected = '่ฎพไธบ้ฆ–้กต'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = mb_strrichr($string, $find, true); $expected = 'ๆŠŠ็™พๅบฆ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = mb_strrichr($string, $find); $expected = 'ๅ‘จๆฐธ้พ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = mb_strrichr($string, $find, true); $expected = 'ไธ€ไบŒไธ‰'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '็™พ่ฎพ'; $result = mb_strrichr($string, $find, true); $expected = false; $this->assertEquals($expected, $result); } /** * testMultibyteStrrichr method * * @return void */ public function testMultibyteStrrichr() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = Multibyte::strrichr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ0123456789'; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ABCDE'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = Multibyte::strrichr($string, $find); $expected = 'ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ร€รร‚รƒร„'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::strrichr($string, $find); $expected = 'ฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ฤ€ฤ‚ฤ„ฤ†ฤˆ'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = Multibyte::strrichr($string, $find); $expected = 'fghijklmnopqrstuvwxyz{|}~'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = Multibyte::strrichr($string, $find, true); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcde'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = Multibyte::strrichr($string, $find); $expected = 'ยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยด'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รž'; $result = Multibyte::strrichr($string, $find); $expected = 'รพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รž'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝ'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = Multibyte::strrichr($string, $find); $expected = 'ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…'; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = Multibyte::strrichr($string, $find); $expected = 'ฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $this->assertEquals($expected, $result); $find = 'ฦธ'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธ'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = Multibyte::strrichr($string, $find); $expected = 'ส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟ'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = Multibyte::strrichr($string, $find); $expected = 'ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ะ€ะะ‚ะƒะ„ะ…ะ†'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = Multibyte::strrichr($string, $find); $expected = 'ั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟ'; $find = 'ะ '; $result = Multibyte::strrichr($string, $find, true); $expected = 'ะœะะžะŸ'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = Multibyte::strrichr($string, $find); $expected = 'ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ูู‚ูƒู„ู…'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = Multibyte::strrichr($string, $find); $expected = 'โœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = Multibyte::strrichr($string, $find, true); $expected = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพ'; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = Multibyte::strrichr($string, $find); $expected = 'โบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = Multibyte::strrichr($string, $find, true); $expected = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = Multibyte::strrichr($string, $find); $expected = 'โฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = Multibyte::strrichr($string, $find, true); $expected = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃ'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = Multibyte::strrichr($string, $find); $expected = '๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = Multibyte::strrichr($string, $find, true); $expected = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = Multibyte::strrichr($string, $find); $expected = '๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = Multibyte::strrichr($string, $find, true); $expected = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = Multibyte::strrichr($string, $find); $expected = '๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = Multibyte::strrichr($string, $find, true); $expected = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::strrichr($string, $find); $expected = '๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::strrichr($string, $find, true); $expected = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = Multibyte::strrichr($string, $find); $expected = '๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = Multibyte::strrichr($string, $find, true); $expected = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = Multibyte::strrichr($string, $find); $expected = '๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = Multibyte::strrichr($string, $find, true); $expected = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::strrichr($string, $find); $expected = 'ล‘ล™ฤผฤ!'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ฤคฤ“ฤบฤผล, ลด'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::strrichr($string, $find); $expected = 'orld!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::strrichr($string, $find, true); $expected = 'Hello, W'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = Multibyte::strrichr($string, $find); $expected = 'World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = Multibyte::strrichr($string, $find, true); $expected = 'Hello, '; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = Multibyte::strrichr($string, $find); $expected = 'llo, World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = Multibyte::strrichr($string, $find, true); $expected = 'He'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = Multibyte::strrichr($string, $find); $expected = 'rld!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = Multibyte::strrichr($string, $find, true); $expected = 'Hello, Wo'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::strrichr($string, $find); $expected = 'ni'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ฤi'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::strrichr($string, $find); $expected = 'ฤ‡i'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::strrichr($string, $find, true); $expected = 'mo'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = Multibyte::strrichr($string, $find); $expected = 'ลพavni'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = Multibyte::strrichr($string, $find, true); $expected = 'dr'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = Multibyte::strrichr($string, $find); $expected = '่ฎพไธบ้ฆ–้กต'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ๆŠŠ็™พๅบฆ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = Multibyte::strrichr($string, $find); $expected = 'ๅ‘จๆฐธ้พ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = Multibyte::strrichr($string, $find, true); $expected = 'ไธ€ไบŒไธ‰'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '็™พ่ฎพ'; $result = Multibyte::strrichr($string, $find, true); $expected = false; $this->assertEquals($expected, $result); } /** * testUsingMbStrripos method * * @return void */ public function testUsingMbStrripos() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = mb_strripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQFRSTUVWXYZ0123456789'; $find = 'F'; $result = mb_strripos($string, $find, 6); $expected = 17; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = mb_strripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรž'; $find = 'ร…'; $result = mb_strripos($string, $find, 6); $expected = 24; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรž'; $find = 'ร“ร”'; $result = mb_strripos($string, $find); $expected = 19; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_strripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลฤŠลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_strripos($string, $find, 6); $expected = 32; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = mb_strripos($string, $find); $expected = 69; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = mb_strripos($string, $find); $expected = 20; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รฉ'; $result = mb_strripos($string, $find); $expected = 32; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = mb_strripos($string, $find); $expected = 25; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = mb_strripos($string, $find); $expected = 40; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦน'; $result = mb_strripos($string, $find); $expected = 40; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = mb_strripos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = mb_strripos($string, $find); $expected = 7; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = mb_strripos($string, $find); $expected = 36; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ั€'; $result = mb_strripos($string, $find, 5); $expected = 36; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = mb_strripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = mb_strripos($string, $find); $expected = 15; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = mb_strripos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = mb_strripos($string, $find); $expected = 31; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = mb_strripos($string, $find); $expected = 26; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = mb_strripos($string, $find); $expected = 46; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = mb_strripos($string, $find); $expected = 45; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_strripos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_strripos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ๏ฝ'; $result = mb_strripos($string, $find); $expected = 15; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = mb_strripos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = mb_strripos($string, $find); $expected = 17; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_strripos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_strripos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_strripos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_strripos($string, $find, 5); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_strripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_strripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_strripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_strripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = mb_strripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = mb_strripos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = mb_strripos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'dลพ'; $result = mb_strripos($string, $find); $this->assertFalse($result); } /** * testMultibyteStrripos method * * @return void */ public function testMultibyteStrripos() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = Multibyte::strripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQFRSTUVWXYZ0123456789'; $find = 'F'; $result = Multibyte::strripos($string, $find, 6); $expected = 17; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = Multibyte::strripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรž'; $find = 'ร…'; $result = Multibyte::strripos($string, $find, 6); $expected = 24; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรž'; $find = 'ร“ร”'; $result = Multibyte::strripos($string, $find); $expected = 19; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::strripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลฤŠลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::strripos($string, $find, 6); $expected = 32; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = Multibyte::strripos($string, $find); $expected = 69; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = Multibyte::strripos($string, $find); $expected = 20; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รฉ'; $result = Multibyte::strripos($string, $find); $expected = 32; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = Multibyte::strripos($string, $find); $expected = 25; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = Multibyte::strripos($string, $find); $expected = 40; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦน'; $result = Multibyte::strripos($string, $find); $expected = 40; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = Multibyte::strripos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = Multibyte::strripos($string, $find); $expected = 7; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = Multibyte::strripos($string, $find); $expected = 36; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ั€'; $result = Multibyte::strripos($string, $find, 5); $expected = 36; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = Multibyte::strripos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = Multibyte::strripos($string, $find); $expected = 15; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = Multibyte::strripos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = Multibyte::strripos($string, $find); $expected = 31; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = Multibyte::strripos($string, $find); $expected = 26; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = Multibyte::strripos($string, $find); $expected = 46; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = Multibyte::strripos($string, $find); $expected = 45; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::strripos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::strripos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ๏ฝ'; $result = Multibyte::strripos($string, $find); $expected = 15; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = Multibyte::strripos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = Multibyte::strripos($string, $find); $expected = 17; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::strripos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::strripos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::strripos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::strripos($string, $find, 5); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::strripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::strripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::strripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::strripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = Multibyte::strripos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = Multibyte::strripos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = Multibyte::strripos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'dลพ'; $result = Multibyte::strripos($string, $find); $expected = 0; $this->assertEquals($expected, $result); } /** * testUsingMbStrrpos method * * @return void */ public function testUsingMbStrrpos() { $this->skipIf(extension_loaded('mbstring') && version_compare(PHP_VERSION, '5.2.0', '<'), 'PHP version does not support $offset parameter in mb_strrpos().'); $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = mb_strrpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQFRSTUVWXYZ0123456789'; $find = 'F'; $result = mb_strrpos($string, $find, 6); $expected = 17; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = mb_strrpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรž'; $find = 'ร™รš'; $result = mb_strrpos($string, $find); $expected = 25; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรž'; $find = 'ร…'; $result = mb_strrpos($string, $find, 6); $expected = 24; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_strrpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลฤŠลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_strrpos($string, $find, 6); $expected = 32; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = mb_strrpos($string, $find); $expected = 37; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = mb_strrpos($string, $find); $expected = 20; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รฉ'; $result = mb_strrpos($string, $find); $expected = 32; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = mb_strrpos($string, $find); $expected = 24; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = mb_strrpos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦน'; $result = mb_strrpos($string, $find); $expected = 40; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = mb_strrpos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = mb_strrpos($string, $find); $expected = 7; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = mb_strrpos($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ั€'; $result = mb_strrpos($string, $find, 5); $expected = 36; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = mb_strrpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = mb_strrpos($string, $find); $expected = 15; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = mb_strrpos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = mb_strrpos($string, $find); $expected = 31; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = mb_strrpos($string, $find); $expected = 26; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = mb_strrpos($string, $find); $expected = 46; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = mb_strrpos($string, $find); $expected = 45; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_strrpos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_strrpos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ๏ฝ'; $result = mb_strrpos($string, $find); $expected = 15; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = mb_strrpos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = mb_strrpos($string, $find); $expected = 17; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_strrpos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_strrpos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_strrpos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_strrpos($string, $find, 5); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_strrpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_strrpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_strrpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_strrpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = mb_strrpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = mb_strrpos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = mb_strrpos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'H'; $result = mb_strrpos($string, $find); $expected = false; $this->assertEquals($expected, $result); } /** * testMultibyteStrrpos method * * @return void */ public function testMultibyteStrrpos() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = Multibyte::strrpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQFRSTUVWXYZ0123456789'; $find = 'F'; $result = Multibyte::strrpos($string, $find, 6); $expected = 17; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = Multibyte::strrpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรž'; $find = 'ร…'; $result = Multibyte::strrpos($string, $find, 6); $expected = 24; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรž'; $find = 'ร™รš'; $result = Multibyte::strrpos($string, $find); $expected = 25; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::strrpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลฤŠลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::strrpos($string, $find, 6); $expected = 32; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = Multibyte::strrpos($string, $find); $expected = 37; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = Multibyte::strrpos($string, $find); $expected = 20; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รฉ'; $result = Multibyte::strrpos($string, $find); $expected = 32; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = Multibyte::strrpos($string, $find); $expected = 24; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = Multibyte::strrpos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦน'; $result = Multibyte::strrpos($string, $find); $expected = 40; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = Multibyte::strrpos($string, $find); $expected = 39; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = Multibyte::strrpos($string, $find); $expected = 7; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = Multibyte::strrpos($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ั€'; $result = Multibyte::strrpos($string, $find, 5); $expected = 36; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = Multibyte::strrpos($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = Multibyte::strrpos($string, $find); $expected = 15; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = Multibyte::strrpos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = Multibyte::strrpos($string, $find); $expected = 31; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = Multibyte::strrpos($string, $find); $expected = 26; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = Multibyte::strrpos($string, $find); $expected = 46; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = Multibyte::strrpos($string, $find); $expected = 45; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::strrpos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::strrpos($string, $find); $expected = 10; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ๏ฝ'; $result = Multibyte::strrpos($string, $find); $expected = 15; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = Multibyte::strrpos($string, $find); $expected = 16; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = Multibyte::strrpos($string, $find); $expected = 17; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::strrpos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::strrpos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::strrpos($string, $find); $expected = 8; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::strrpos($string, $find, 5); $expected = 8; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::strrpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::strrpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::strrpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::strrpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = Multibyte::strrpos($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = Multibyte::strrpos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = Multibyte::strrpos($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'H'; $result = Multibyte::strrpos($string, $find); $expected = false; $this->assertEquals($expected, $result); } /** * testUsingMbStrstr method * * @return void */ public function testUsingMbStrstr() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = mb_strstr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ0123456789'; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = mb_strstr($string, $find, true); $expected = 'ABCDE'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = mb_strstr($string, $find); $expected = 'ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = mb_strstr($string, $find, true); $expected = 'ร€รร‚รƒร„'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_strstr($string, $find); $expected = 'ฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_strstr($string, $find, true); $expected = 'ฤ€ฤ‚ฤ„ฤ†ฤˆ'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = mb_strstr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = mb_strstr($string, $find, true); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDE'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = mb_strstr($string, $find); $expected = 'ยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = mb_strstr($string, $find, true); $expected = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยด'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รž'; $result = mb_strstr($string, $find); $expected = 'รžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รž'; $result = mb_strstr($string, $find, true); $expected = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœร'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = mb_strstr($string, $find); $expected = 'ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = mb_strstr($string, $find, true); $expected = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„'; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = mb_strstr($string, $find); $expected = 'ฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $this->assertEquals($expected, $result); $find = 'ฦธ'; $result = mb_strstr($string, $find, true); $expected = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦท'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = mb_strstr($string, $find); $expected = 'ส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = mb_strstr($string, $find, true); $expected = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟ'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = mb_strstr($string, $find); $expected = 'ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = mb_strstr($string, $find, true); $expected = 'ะ€ะะ‚ะƒะ„ะ…ะ†'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = mb_strstr($string, $find); $expected = 'ะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = mb_strstr($string, $find, true); $expected = 'ะœะะžะŸ'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = mb_strstr($string, $find); $expected = 'ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = mb_strstr($string, $find, true); $expected = 'ูู‚ูƒู„ู…'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = mb_strstr($string, $find); $expected = 'โœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = mb_strstr($string, $find, true); $expected = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพ'; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = mb_strstr($string, $find); $expected = 'โบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = mb_strstr($string, $find, true); $expected = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = mb_strstr($string, $find); $expected = 'โฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = mb_strstr($string, $find, true); $expected = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃ'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = mb_strstr($string, $find); $expected = '๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = mb_strstr($string, $find, true); $expected = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = mb_strstr($string, $find); $expected = '๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = mb_strstr($string, $find, true); $expected = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = mb_strstr($string, $find); $expected = '๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = mb_strstr($string, $find, true); $expected = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_strstr($string, $find); $expected = '๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_strstr($string, $find, true); $expected = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ผซ'; $result = mb_strstr($string, $find); $expected = false; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = mb_strstr($string, $find); $expected = '๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = mb_strstr($string, $find, true); $expected = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = mb_strstr($string, $find); $expected = '๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = mb_strstr($string, $find, true); $expected = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_strstr($string, $find); $expected = 'ล‘ล™ฤผฤ!'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_strstr($string, $find, true); $expected = 'ฤคฤ“ฤบฤผล, ลด'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ฤบฤผ'; $result = mb_strstr($string, $find, true); $expected = 'ฤคฤ“'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_strstr($string, $find); $expected = 'o, World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_strstr($string, $find, true); $expected = 'Hell'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = mb_strstr($string, $find); $expected = 'World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = mb_strstr($string, $find, true); $expected = 'Hello, '; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = mb_strstr($string, $find); $expected = 'llo, World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = mb_strstr($string, $find, true); $expected = 'He'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = mb_strstr($string, $find); $expected = 'rld!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = mb_strstr($string, $find, true); $expected = 'Hello, Wo'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_strstr($string, $find); $expected = 'ni'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_strstr($string, $find, true); $expected = 'ฤi'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_strstr($string, $find); $expected = 'ฤ‡i'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_strstr($string, $find, true); $expected = 'mo'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = mb_strstr($string, $find); $expected = 'ลพavni'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = mb_strstr($string, $find, true); $expected = 'dr'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = mb_strstr($string, $find); $expected = '่ฎพไธบ้ฆ–้กต'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = mb_strstr($string, $find, true); $expected = 'ๆŠŠ็™พๅบฆ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = mb_strstr($string, $find); $expected = 'ๅ‘จๆฐธ้พ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = mb_strstr($string, $find, true); $expected = 'ไธ€ไบŒไธ‰'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ไบŒๅ‘จ'; $result = mb_strstr($string, $find); $expected = false; $this->assertEquals($expected, $result); } /** * testMultibyteStrstr method * * @return void */ public function testMultibyteStrstr() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = Multibyte::strstr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ0123456789'; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = Multibyte::strstr($string, $find, true); $expected = 'ABCDE'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = Multibyte::strstr($string, $find); $expected = 'ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $find = 'ร…'; $result = Multibyte::strstr($string, $find, true); $expected = 'ร€รร‚รƒร„'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::strstr($string, $find); $expected = 'ฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::strstr($string, $find, true); $expected = 'ฤ€ฤ‚ฤ„ฤ†ฤˆ'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = Multibyte::strstr($string, $find); $expected = 'FGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $find = 'F'; $result = Multibyte::strstr($string, $find, true); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDE'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = Multibyte::strstr($string, $find); $expected = 'ยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $find = 'ยต'; $result = Multibyte::strstr($string, $find, true); $expected = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยด'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รž'; $result = Multibyte::strstr($string, $find); $expected = 'รžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $find = 'รž'; $result = Multibyte::strstr($string, $find, true); $expected = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœร'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = Multibyte::strstr($string, $find); $expected = 'ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ล…'; $result = Multibyte::strstr($string, $find, true); $expected = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„'; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = Multibyte::strstr($string, $find); $expected = 'ฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $this->assertEquals($expected, $result); $find = 'ฦธ'; $result = Multibyte::strstr($string, $find, true); $expected = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦท'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = Multibyte::strstr($string, $find); $expected = 'ส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $find = 'ส€'; $result = Multibyte::strstr($string, $find, true); $expected = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟ'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = Multibyte::strstr($string, $find); $expected = 'ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = Multibyte::strstr($string, $find, true); $expected = 'ะ€ะะ‚ะƒะ„ะ…ะ†'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = Multibyte::strstr($string, $find); $expected = 'ะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = Multibyte::strstr($string, $find, true); $expected = 'ะœะะžะŸ'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = Multibyte::strstr($string, $find); $expected = 'ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $find = 'ู†'; $result = Multibyte::strstr($string, $find, true); $expected = 'ูู‚ูƒู„ู…'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = Multibyte::strstr($string, $find); $expected = 'โœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = Multibyte::strstr($string, $find, true); $expected = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพ'; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = Multibyte::strstr($string, $find); $expected = 'โบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = Multibyte::strstr($string, $find, true); $expected = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = Multibyte::strstr($string, $find); $expected = 'โฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = Multibyte::strstr($string, $find, true); $expected = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃ'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = Multibyte::strstr($string, $find); $expected = '๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆป'; $result = Multibyte::strstr($string, $find, true); $expected = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = Multibyte::strstr($string, $find); $expected = '๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž'; $result = Multibyte::strstr($string, $find, true); $expected = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = Multibyte::strstr($string, $find); $expected = '๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $find = '๏ปž'; $result = Multibyte::strstr($string, $find, true); $expected = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::strstr($string, $find); $expected = '๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::strstr($string, $find, true); $expected = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ผซ'; $result = Multibyte::strstr($string, $find); $expected = false; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = Multibyte::strstr($string, $find); $expected = '๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = Multibyte::strstr($string, $find, true); $expected = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = Multibyte::strstr($string, $find); $expected = '๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = Multibyte::strstr($string, $find, true); $expected = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::strstr($string, $find); $expected = 'ล‘ล™ฤผฤ!'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::strstr($string, $find, true); $expected = 'ฤคฤ“ฤบฤผล, ลด'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ฤบฤผ'; $result = Multibyte::strstr($string, $find, true); $expected = 'ฤคฤ“'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::strstr($string, $find); $expected = 'o, World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::strstr($string, $find, true); $expected = 'Hell'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = Multibyte::strstr($string, $find); $expected = 'World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'Wo'; $result = Multibyte::strstr($string, $find, true); $expected = 'Hello, '; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = Multibyte::strstr($string, $find); $expected = 'llo, World!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'll'; $result = Multibyte::strstr($string, $find, true); $expected = 'He'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = Multibyte::strstr($string, $find); $expected = 'rld!'; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rld'; $result = Multibyte::strstr($string, $find, true); $expected = 'Hello, Wo'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::strstr($string, $find); $expected = 'ni'; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::strstr($string, $find, true); $expected = 'ฤi'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::strstr($string, $find); $expected = 'ฤ‡i'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::strstr($string, $find, true); $expected = 'mo'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = Multibyte::strstr($string, $find); $expected = 'ลพavni'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = Multibyte::strstr($string, $find, true); $expected = 'dr'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = Multibyte::strstr($string, $find); $expected = '่ฎพไธบ้ฆ–้กต'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = Multibyte::strstr($string, $find, true); $expected = 'ๆŠŠ็™พๅบฆ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = Multibyte::strstr($string, $find); $expected = 'ๅ‘จๆฐธ้พ'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = Multibyte::strstr($string, $find, true); $expected = 'ไธ€ไบŒไธ‰'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ไบŒๅ‘จ'; $result = Multibyte::strstr($string, $find); $expected = false; $this->assertEquals($expected, $result); } /** * testUsingMbStrtolower method * * @return void */ public function testUsingMbStrtolower() { $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~'; $result = mb_strtolower($string); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@'; $result = mb_strtolower($string); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@'; $this->assertEquals($expected, $result); $string = 'ร€'; $result = mb_strtolower($string); $expected = 'ร '; $this->assertEquals($expected, $result); $string = 'ร'; $result = mb_strtolower($string); $expected = 'รก'; $this->assertEquals($expected, $result); $string = 'ร‚'; $result = mb_strtolower($string); $expected = 'รข'; $this->assertEquals($expected, $result); $string = 'รƒ'; $result = mb_strtolower($string); $expected = 'รฃ'; $this->assertEquals($expected, $result); $string = 'ร„'; $result = mb_strtolower($string); $expected = 'รค'; $this->assertEquals($expected, $result); $string = 'ร…'; $result = mb_strtolower($string); $expected = 'รฅ'; $this->assertEquals($expected, $result); $string = 'ร†'; $result = mb_strtolower($string); $expected = 'รฆ'; $this->assertEquals($expected, $result); $string = 'ร‡'; $result = mb_strtolower($string); $expected = 'รง'; $this->assertEquals($expected, $result); $string = 'รˆ'; $result = mb_strtolower($string); $expected = 'รจ'; $this->assertEquals($expected, $result); $string = 'ร‰'; $result = mb_strtolower($string); $expected = 'รฉ'; $this->assertEquals($expected, $result); $string = 'รŠ'; $result = mb_strtolower($string); $expected = 'รช'; $this->assertEquals($expected, $result); $string = 'ร‹'; $result = mb_strtolower($string); $expected = 'รซ'; $this->assertEquals($expected, $result); $string = 'รŒ'; $result = mb_strtolower($string); $expected = 'รฌ'; $this->assertEquals($expected, $result); $string = 'ร'; $result = mb_strtolower($string); $expected = 'รญ'; $this->assertEquals($expected, $result); $string = 'รŽ'; $result = mb_strtolower($string); $expected = 'รฎ'; $this->assertEquals($expected, $result); $string = 'ร'; $result = mb_strtolower($string); $expected = 'รฏ'; $this->assertEquals($expected, $result); $string = 'ร'; $result = mb_strtolower($string); $expected = 'รฐ'; $this->assertEquals($expected, $result); $string = 'ร‘'; $result = mb_strtolower($string); $expected = 'รฑ'; $this->assertEquals($expected, $result); $string = 'ร’'; $result = mb_strtolower($string); $expected = 'รฒ'; $this->assertEquals($expected, $result); $string = 'ร“'; $result = mb_strtolower($string); $expected = 'รณ'; $this->assertEquals($expected, $result); $string = 'ร”'; $result = mb_strtolower($string); $expected = 'รด'; $this->assertEquals($expected, $result); $string = 'ร•'; $result = mb_strtolower($string); $expected = 'รต'; $this->assertEquals($expected, $result); $string = 'ร–'; $result = mb_strtolower($string); $expected = 'รถ'; $this->assertEquals($expected, $result); $string = 'ร˜'; $result = mb_strtolower($string); $expected = 'รธ'; $this->assertEquals($expected, $result); $string = 'ร™'; $result = mb_strtolower($string); $expected = 'รน'; $this->assertEquals($expected, $result); $string = 'รš'; $result = mb_strtolower($string); $expected = 'รบ'; $this->assertEquals($expected, $result); $string = 'ร›'; $result = mb_strtolower($string); $expected = 'รป'; $this->assertEquals($expected, $result); $string = 'รœ'; $result = mb_strtolower($string); $expected = 'รผ'; $this->assertEquals($expected, $result); $string = 'ร'; $result = mb_strtolower($string); $expected = 'รฝ'; $this->assertEquals($expected, $result); $string = 'รž'; $result = mb_strtolower($string); $expected = 'รพ'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $result = mb_strtolower($string); $expected = 'ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพ'; $this->assertEquals($expected, $result); $string = 'ฤ€'; $result = mb_strtolower($string); $expected = 'ฤ'; $this->assertEquals($expected, $result); $string = 'ฤ‚'; $result = mb_strtolower($string); $expected = 'ฤƒ'; $this->assertEquals($expected, $result); $string = 'ฤ„'; $result = mb_strtolower($string); $expected = 'ฤ…'; $this->assertEquals($expected, $result); $string = 'ฤ†'; $result = mb_strtolower($string); $expected = 'ฤ‡'; $this->assertEquals($expected, $result); $string = 'ฤˆ'; $result = mb_strtolower($string); $expected = 'ฤ‰'; $this->assertEquals($expected, $result); $string = 'ฤŠ'; $result = mb_strtolower($string); $expected = 'ฤ‹'; $this->assertEquals($expected, $result); $string = 'ฤŒ'; $result = mb_strtolower($string); $expected = 'ฤ'; $this->assertEquals($expected, $result); $string = 'ฤŽ'; $result = mb_strtolower($string); $expected = 'ฤ'; $this->assertEquals($expected, $result); $string = 'ฤ'; $result = mb_strtolower($string); $expected = 'ฤ‘'; $this->assertEquals($expected, $result); $string = 'ฤ’'; $result = mb_strtolower($string); $expected = 'ฤ“'; $this->assertEquals($expected, $result); $string = 'ฤ”'; $result = mb_strtolower($string); $expected = 'ฤ•'; $this->assertEquals($expected, $result); $string = 'ฤ–'; $result = mb_strtolower($string); $expected = 'ฤ—'; $this->assertEquals($expected, $result); $string = 'ฤ˜'; $result = mb_strtolower($string); $expected = 'ฤ™'; $this->assertEquals($expected, $result); $string = 'ฤš'; $result = mb_strtolower($string); $expected = 'ฤ›'; $this->assertEquals($expected, $result); $string = 'ฤœ'; $result = mb_strtolower($string); $expected = 'ฤ'; $this->assertEquals($expected, $result); $string = 'ฤž'; $result = mb_strtolower($string); $expected = 'ฤŸ'; $this->assertEquals($expected, $result); $string = 'ฤ '; $result = mb_strtolower($string); $expected = 'ฤก'; $this->assertEquals($expected, $result); $string = 'ฤข'; $result = mb_strtolower($string); $expected = 'ฤฃ'; $this->assertEquals($expected, $result); $string = 'ฤค'; $result = mb_strtolower($string); $expected = 'ฤฅ'; $this->assertEquals($expected, $result); $string = 'ฤฆ'; $result = mb_strtolower($string); $expected = 'ฤง'; $this->assertEquals($expected, $result); $string = 'ฤจ'; $result = mb_strtolower($string); $expected = 'ฤฉ'; $this->assertEquals($expected, $result); $string = 'ฤช'; $result = mb_strtolower($string); $expected = 'ฤซ'; $this->assertEquals($expected, $result); $string = 'ฤฌ'; $result = mb_strtolower($string); $expected = 'ฤญ'; $this->assertEquals($expected, $result); $string = 'ฤฎ'; $result = mb_strtolower($string); $expected = 'ฤฏ'; $this->assertEquals($expected, $result); $string = 'ฤฒ'; $result = mb_strtolower($string); $expected = 'ฤณ'; $this->assertEquals($expected, $result); $string = 'ฤด'; $result = mb_strtolower($string); $expected = 'ฤต'; $this->assertEquals($expected, $result); $string = 'ฤถ'; $result = mb_strtolower($string); $expected = 'ฤท'; $this->assertEquals($expected, $result); $string = 'ฤน'; $result = mb_strtolower($string); $expected = 'ฤบ'; $this->assertEquals($expected, $result); $string = 'ฤป'; $result = mb_strtolower($string); $expected = 'ฤผ'; $this->assertEquals($expected, $result); $string = 'ฤฝ'; $result = mb_strtolower($string); $expected = 'ฤพ'; $this->assertEquals($expected, $result); $string = 'ฤฟ'; $result = mb_strtolower($string); $expected = 'ล€'; $this->assertEquals($expected, $result); $string = 'ล'; $result = mb_strtolower($string); $expected = 'ล‚'; $this->assertEquals($expected, $result); $string = 'ลƒ'; $result = mb_strtolower($string); $expected = 'ล„'; $this->assertEquals($expected, $result); $string = 'ล…'; $result = mb_strtolower($string); $expected = 'ล†'; $this->assertEquals($expected, $result); $string = 'ล‡'; $result = mb_strtolower($string); $expected = 'ลˆ'; $this->assertEquals($expected, $result); $string = 'ลŠ'; $result = mb_strtolower($string); $expected = 'ล‹'; $this->assertEquals($expected, $result); $string = 'ลŒ'; $result = mb_strtolower($string); $expected = 'ล'; $this->assertEquals($expected, $result); $string = 'ลŽ'; $result = mb_strtolower($string); $expected = 'ล'; $this->assertEquals($expected, $result); $string = 'ล'; $result = mb_strtolower($string); $expected = 'ล‘'; $this->assertEquals($expected, $result); $string = 'ล’'; $result = mb_strtolower($string); $expected = 'ล“'; $this->assertEquals($expected, $result); $string = 'ล”'; $result = mb_strtolower($string); $expected = 'ล•'; $this->assertEquals($expected, $result); $string = 'ล–'; $result = mb_strtolower($string); $expected = 'ล—'; $this->assertEquals($expected, $result); $string = 'ล˜'; $result = mb_strtolower($string); $expected = 'ล™'; $this->assertEquals($expected, $result); $string = 'ลš'; $result = mb_strtolower($string); $expected = 'ล›'; $this->assertEquals($expected, $result); $string = 'ลœ'; $result = mb_strtolower($string); $expected = 'ล'; $this->assertEquals($expected, $result); $string = 'ลž'; $result = mb_strtolower($string); $expected = 'ลŸ'; $this->assertEquals($expected, $result); $string = 'ล '; $result = mb_strtolower($string); $expected = 'ลก'; $this->assertEquals($expected, $result); $string = 'ลข'; $result = mb_strtolower($string); $expected = 'ลฃ'; $this->assertEquals($expected, $result); $string = 'ลค'; $result = mb_strtolower($string); $expected = 'ลฅ'; $this->assertEquals($expected, $result); $string = 'ลฆ'; $result = mb_strtolower($string); $expected = 'ลง'; $this->assertEquals($expected, $result); $string = 'ลจ'; $result = mb_strtolower($string); $expected = 'ลฉ'; $this->assertEquals($expected, $result); $string = 'ลช'; $result = mb_strtolower($string); $expected = 'ลซ'; $this->assertEquals($expected, $result); $string = 'ลฌ'; $result = mb_strtolower($string); $expected = 'ลญ'; $this->assertEquals($expected, $result); $string = 'ลฎ'; $result = mb_strtolower($string); $expected = 'ลฏ'; $this->assertEquals($expected, $result); $string = 'ลฐ'; $result = mb_strtolower($string); $expected = 'ลฑ'; $this->assertEquals($expected, $result); $string = 'ลฒ'; $result = mb_strtolower($string); $expected = 'ลณ'; $this->assertEquals($expected, $result); $string = 'ลด'; $result = mb_strtolower($string); $expected = 'ลต'; $this->assertEquals($expected, $result); $string = 'ลถ'; $result = mb_strtolower($string); $expected = 'ลท'; $this->assertEquals($expected, $result); $string = 'ลน'; $result = mb_strtolower($string); $expected = 'ลบ'; $this->assertEquals($expected, $result); $string = 'ลป'; $result = mb_strtolower($string); $expected = 'ลผ'; $this->assertEquals($expected, $result); $string = 'ลฝ'; $result = mb_strtolower($string); $expected = 'ลพ'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $result = mb_strtolower($string); $expected = 'ฤฤƒฤ…ฤ‡ฤ‰ฤ‹ฤฤฤ‘ฤ“ฤ•ฤ—ฤ™ฤ›ฤฤŸฤกฤฃฤฅฤงฤฉฤซฤญฤฏฤณฤตฤทฤบฤผฤพล€ล‚ล„ล†ลˆล‹ลลล‘ล“ล•ล—ล™ล›ลลŸลกลฃลฅลงลฉลซลญลฏลฑลณลตลทลบลผลพ'; $this->assertEquals($expected, $result); $string = 'ฤคฤ’ฤนฤปลŽ, ลดลล˜ฤปฤŽ!'; $result = mb_strtolower($string); $expected = 'ฤฅฤ“ฤบฤผล, ลตล‘ล™ฤผฤ!'; $this->assertEquals($expected, $result); $string = 'ฤฅฤ“ฤบฤผล, ลตล‘ล™ฤผฤ!'; $result = mb_strtolower($string); $expected = 'ฤฅฤ“ฤบฤผล, ลตล‘ล™ฤผฤ!'; $this->assertEquals($expected, $result); $string = 'แผˆฮ™'; $result = mb_strtolower($string); $expected = 'แผ€ฮน'; $this->assertEquals($expected, $result); $string = '๏ฌ€๏ฌ๏ฌ‚๏ฌƒ๏ฌ„๏ฌ…๏ฌ†๏ฌ“๏ฌ”๏ฌ•๏ฌ–๏ฌ—'; $result = mb_strtolower($string); $expected = '๏ฌ€๏ฌ๏ฌ‚๏ฌƒ๏ฌ„๏ฌ…๏ฌ†๏ฌ“๏ฌ”๏ฌ•๏ฌ–๏ฌ—'; $this->assertEquals($expected, $result); } /** * testMultibyteStrtolower method * * @return void */ public function testMultibyteStrtolower() { $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~'; $result = Multibyte::strtolower($string); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@'; $result = Multibyte::strtolower($string); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@'; $this->assertEquals($expected, $result); $string = 'ร€'; $result = Multibyte::strtolower($string); $expected = 'ร '; $this->assertEquals($expected, $result); $string = 'ร'; $result = Multibyte::strtolower($string); $expected = 'รก'; $this->assertEquals($expected, $result); $string = 'ร‚'; $result = Multibyte::strtolower($string); $expected = 'รข'; $this->assertEquals($expected, $result); $string = 'รƒ'; $result = Multibyte::strtolower($string); $expected = 'รฃ'; $this->assertEquals($expected, $result); $string = 'ร„'; $result = Multibyte::strtolower($string); $expected = 'รค'; $this->assertEquals($expected, $result); $string = 'ร…'; $result = Multibyte::strtolower($string); $expected = 'รฅ'; $this->assertEquals($expected, $result); $string = 'ร†'; $result = Multibyte::strtolower($string); $expected = 'รฆ'; $this->assertEquals($expected, $result); $string = 'ร‡'; $result = Multibyte::strtolower($string); $expected = 'รง'; $this->assertEquals($expected, $result); $string = 'รˆ'; $result = Multibyte::strtolower($string); $expected = 'รจ'; $this->assertEquals($expected, $result); $string = 'ร‰'; $result = Multibyte::strtolower($string); $expected = 'รฉ'; $this->assertEquals($expected, $result); $string = 'รŠ'; $result = Multibyte::strtolower($string); $expected = 'รช'; $this->assertEquals($expected, $result); $string = 'ร‹'; $result = Multibyte::strtolower($string); $expected = 'รซ'; $this->assertEquals($expected, $result); $string = 'รŒ'; $result = Multibyte::strtolower($string); $expected = 'รฌ'; $this->assertEquals($expected, $result); $string = 'ร'; $result = Multibyte::strtolower($string); $expected = 'รญ'; $this->assertEquals($expected, $result); $string = 'รŽ'; $result = Multibyte::strtolower($string); $expected = 'รฎ'; $this->assertEquals($expected, $result); $string = 'ร'; $result = Multibyte::strtolower($string); $expected = 'รฏ'; $this->assertEquals($expected, $result); $string = 'ร'; $result = Multibyte::strtolower($string); $expected = 'รฐ'; $this->assertEquals($expected, $result); $string = 'ร‘'; $result = Multibyte::strtolower($string); $expected = 'รฑ'; $this->assertEquals($expected, $result); $string = 'ร’'; $result = Multibyte::strtolower($string); $expected = 'รฒ'; $this->assertEquals($expected, $result); $string = 'ร“'; $result = Multibyte::strtolower($string); $expected = 'รณ'; $this->assertEquals($expected, $result); $string = 'ร”'; $result = Multibyte::strtolower($string); $expected = 'รด'; $this->assertEquals($expected, $result); $string = 'ร•'; $result = Multibyte::strtolower($string); $expected = 'รต'; $this->assertEquals($expected, $result); $string = 'ร–'; $result = Multibyte::strtolower($string); $expected = 'รถ'; $this->assertEquals($expected, $result); $string = 'ร˜'; $result = Multibyte::strtolower($string); $expected = 'รธ'; $this->assertEquals($expected, $result); $string = 'ร™'; $result = Multibyte::strtolower($string); $expected = 'รน'; $this->assertEquals($expected, $result); $string = 'รš'; $result = Multibyte::strtolower($string); $expected = 'รบ'; $this->assertEquals($expected, $result); $string = 'ร›'; $result = Multibyte::strtolower($string); $expected = 'รป'; $this->assertEquals($expected, $result); $string = 'รœ'; $result = Multibyte::strtolower($string); $expected = 'รผ'; $this->assertEquals($expected, $result); $string = 'ร'; $result = Multibyte::strtolower($string); $expected = 'รฝ'; $this->assertEquals($expected, $result); $string = 'รž'; $result = Multibyte::strtolower($string); $expected = 'รพ'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $result = Multibyte::strtolower($string); $expected = 'ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพ'; $this->assertEquals($expected, $result); $string = 'ฤ€'; $result = Multibyte::strtolower($string); $expected = 'ฤ'; $this->assertEquals($expected, $result); $string = 'ฤ‚'; $result = Multibyte::strtolower($string); $expected = 'ฤƒ'; $this->assertEquals($expected, $result); $string = 'ฤ„'; $result = Multibyte::strtolower($string); $expected = 'ฤ…'; $this->assertEquals($expected, $result); $string = 'ฤ†'; $result = Multibyte::strtolower($string); $expected = 'ฤ‡'; $this->assertEquals($expected, $result); $string = 'ฤˆ'; $result = Multibyte::strtolower($string); $expected = 'ฤ‰'; $this->assertEquals($expected, $result); $string = 'ฤŠ'; $result = Multibyte::strtolower($string); $expected = 'ฤ‹'; $this->assertEquals($expected, $result); $string = 'ฤŒ'; $result = Multibyte::strtolower($string); $expected = 'ฤ'; $this->assertEquals($expected, $result); $string = 'ฤŽ'; $result = Multibyte::strtolower($string); $expected = 'ฤ'; $this->assertEquals($expected, $result); $string = 'ฤ'; $result = Multibyte::strtolower($string); $expected = 'ฤ‘'; $this->assertEquals($expected, $result); $string = 'ฤ’'; $result = Multibyte::strtolower($string); $expected = 'ฤ“'; $this->assertEquals($expected, $result); $string = 'ฤ”'; $result = Multibyte::strtolower($string); $expected = 'ฤ•'; $this->assertEquals($expected, $result); $string = 'ฤ–'; $result = Multibyte::strtolower($string); $expected = 'ฤ—'; $this->assertEquals($expected, $result); $string = 'ฤ˜'; $result = Multibyte::strtolower($string); $expected = 'ฤ™'; $this->assertEquals($expected, $result); $string = 'ฤš'; $result = Multibyte::strtolower($string); $expected = 'ฤ›'; $this->assertEquals($expected, $result); $string = 'ฤœ'; $result = Multibyte::strtolower($string); $expected = 'ฤ'; $this->assertEquals($expected, $result); $string = 'ฤž'; $result = Multibyte::strtolower($string); $expected = 'ฤŸ'; $this->assertEquals($expected, $result); $string = 'ฤ '; $result = Multibyte::strtolower($string); $expected = 'ฤก'; $this->assertEquals($expected, $result); $string = 'ฤข'; $result = Multibyte::strtolower($string); $expected = 'ฤฃ'; $this->assertEquals($expected, $result); $string = 'ฤค'; $result = Multibyte::strtolower($string); $expected = 'ฤฅ'; $this->assertEquals($expected, $result); $string = 'ฤฆ'; $result = Multibyte::strtolower($string); $expected = 'ฤง'; $this->assertEquals($expected, $result); $string = 'ฤจ'; $result = Multibyte::strtolower($string); $expected = 'ฤฉ'; $this->assertEquals($expected, $result); $string = 'ฤช'; $result = Multibyte::strtolower($string); $expected = 'ฤซ'; $this->assertEquals($expected, $result); $string = 'ฤฌ'; $result = Multibyte::strtolower($string); $expected = 'ฤญ'; $this->assertEquals($expected, $result); $string = 'ฤฎ'; $result = Multibyte::strtolower($string); $expected = 'ฤฏ'; $this->assertEquals($expected, $result); $string = 'ฤฒ'; $result = Multibyte::strtolower($string); $expected = 'ฤณ'; $this->assertEquals($expected, $result); $string = 'ฤด'; $result = Multibyte::strtolower($string); $expected = 'ฤต'; $this->assertEquals($expected, $result); $string = 'ฤถ'; $result = Multibyte::strtolower($string); $expected = 'ฤท'; $this->assertEquals($expected, $result); $string = 'ฤน'; $result = Multibyte::strtolower($string); $expected = 'ฤบ'; $this->assertEquals($expected, $result); $string = 'ฤป'; $result = Multibyte::strtolower($string); $expected = 'ฤผ'; $this->assertEquals($expected, $result); $string = 'ฤฝ'; $result = Multibyte::strtolower($string); $expected = 'ฤพ'; $this->assertEquals($expected, $result); $string = 'ฤฟ'; $result = Multibyte::strtolower($string); $expected = 'ล€'; $this->assertEquals($expected, $result); $string = 'ล'; $result = Multibyte::strtolower($string); $expected = 'ล‚'; $this->assertEquals($expected, $result); $string = 'ลƒ'; $result = Multibyte::strtolower($string); $expected = 'ล„'; $this->assertEquals($expected, $result); $string = 'ล…'; $result = Multibyte::strtolower($string); $expected = 'ล†'; $this->assertEquals($expected, $result); $string = 'ล‡'; $result = Multibyte::strtolower($string); $expected = 'ลˆ'; $this->assertEquals($expected, $result); $string = 'ลŠ'; $result = Multibyte::strtolower($string); $expected = 'ล‹'; $this->assertEquals($expected, $result); $string = 'ลŒ'; $result = Multibyte::strtolower($string); $expected = 'ล'; $this->assertEquals($expected, $result); $string = 'ลŽ'; $result = Multibyte::strtolower($string); $expected = 'ล'; $this->assertEquals($expected, $result); $string = 'ล'; $result = Multibyte::strtolower($string); $expected = 'ล‘'; $this->assertEquals($expected, $result); $string = 'ล’'; $result = Multibyte::strtolower($string); $expected = 'ล“'; $this->assertEquals($expected, $result); $string = 'ล”'; $result = Multibyte::strtolower($string); $expected = 'ล•'; $this->assertEquals($expected, $result); $string = 'ล–'; $result = Multibyte::strtolower($string); $expected = 'ล—'; $this->assertEquals($expected, $result); $string = 'ล˜'; $result = Multibyte::strtolower($string); $expected = 'ล™'; $this->assertEquals($expected, $result); $string = 'ลš'; $result = Multibyte::strtolower($string); $expected = 'ล›'; $this->assertEquals($expected, $result); $string = 'ลœ'; $result = Multibyte::strtolower($string); $expected = 'ล'; $this->assertEquals($expected, $result); $string = 'ลž'; $result = Multibyte::strtolower($string); $expected = 'ลŸ'; $this->assertEquals($expected, $result); $string = 'ล '; $result = Multibyte::strtolower($string); $expected = 'ลก'; $this->assertEquals($expected, $result); $string = 'ลข'; $result = Multibyte::strtolower($string); $expected = 'ลฃ'; $this->assertEquals($expected, $result); $string = 'ลค'; $result = Multibyte::strtolower($string); $expected = 'ลฅ'; $this->assertEquals($expected, $result); $string = 'ลฆ'; $result = Multibyte::strtolower($string); $expected = 'ลง'; $this->assertEquals($expected, $result); $string = 'ลจ'; $result = Multibyte::strtolower($string); $expected = 'ลฉ'; $this->assertEquals($expected, $result); $string = 'ลช'; $result = Multibyte::strtolower($string); $expected = 'ลซ'; $this->assertEquals($expected, $result); $string = 'ลฌ'; $result = Multibyte::strtolower($string); $expected = 'ลญ'; $this->assertEquals($expected, $result); $string = 'ลฎ'; $result = Multibyte::strtolower($string); $expected = 'ลฏ'; $this->assertEquals($expected, $result); $string = 'ลฐ'; $result = Multibyte::strtolower($string); $expected = 'ลฑ'; $this->assertEquals($expected, $result); $string = 'ลฒ'; $result = Multibyte::strtolower($string); $expected = 'ลณ'; $this->assertEquals($expected, $result); $string = 'ลด'; $result = Multibyte::strtolower($string); $expected = 'ลต'; $this->assertEquals($expected, $result); $string = 'ลถ'; $result = Multibyte::strtolower($string); $expected = 'ลท'; $this->assertEquals($expected, $result); $string = 'ลน'; $result = Multibyte::strtolower($string); $expected = 'ลบ'; $this->assertEquals($expected, $result); $string = 'ลป'; $result = Multibyte::strtolower($string); $expected = 'ลผ'; $this->assertEquals($expected, $result); $string = 'ลฝ'; $result = Multibyte::strtolower($string); $expected = 'ลพ'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $result = Multibyte::strtolower($string); $expected = 'ฤฤƒฤ…ฤ‡ฤ‰ฤ‹ฤฤฤ‘ฤ“ฤ•ฤ—ฤ™ฤ›ฤฤŸฤกฤฃฤฅฤงฤฉฤซฤญฤฏฤณฤตฤทฤบฤผฤพล€ล‚ล„ล†ลˆล‹ลลล‘ล“ล•ล—ล™ล›ลลŸลกลฃลฅลงลฉลซลญลฏลฑลณลตลทลบลผลพ'; $this->assertEquals($expected, $result); $string = 'ฤคฤ’ฤนฤปลŽ, ลดลล˜ฤปฤŽ!'; $result = Multibyte::strtolower($string); $expected = 'ฤฅฤ“ฤบฤผล, ลตล‘ล™ฤผฤ!'; $this->assertEquals($expected, $result); $string = 'ฤฅฤ“ฤบฤผล, ลตล‘ล™ฤผฤ!'; $result = Multibyte::strtolower($string); $expected = 'ฤฅฤ“ฤบฤผล, ลตล‘ล™ฤผฤ!'; $this->assertEquals($expected, $result); $string = 'แผˆฮ™'; $result = Multibyte::strtolower($string); $expected = 'แผ€ฮน'; $this->assertEquals($expected, $result); $string = 'ิ€ิ‚ิ„ิ†ิˆิŠิŒิŽิิ’'; $result = Multibyte::strtolower($string); $expected = 'ิิƒิ…ิ‡ิ‰ิ‹ิิิ‘ิ“'; $this->assertEquals($expected, $result); $string = 'ิฑิฒิณิดิติถิทิธินิบิปิผิฝิพิฟี€ีี‚ีƒี„ี…ี†ี‡ีˆี‰ีŠี‹ีŒีีŽีีี‘ี’ี“ี”ี•ี–ึ‡'; $result = Multibyte::strtolower($string); $expected = 'ีกีขีฃีคีฅีฆีงีจีฉีชีซีฌีญีฎีฏีฐีฑีฒีณีดีตีถีทีธีนีบีปีผีฝีพีฟึ€ึึ‚ึƒึ„ึ…ึ†ึ‡'; $this->assertEquals($expected, $result); $string = 'แ‚ แ‚กแ‚ขแ‚ฃแ‚คแ‚ฅแ‚ฆแ‚งแ‚จแ‚ฉแ‚ชแ‚ซแ‚ฌแ‚ญแ‚ฎแ‚ฏแ‚ฐแ‚ฑแ‚ฒแ‚ณแ‚ดแ‚ตแ‚ถแ‚ทแ‚ธแ‚นแ‚บแ‚ปแ‚ผแ‚ฝแ‚พแ‚ฟแƒ€แƒแƒ‚แƒƒแƒ„แƒ…'; $result = Multibyte::strtolower($string); $expected = 'แ‚ แ‚กแ‚ขแ‚ฃแ‚คแ‚ฅแ‚ฆแ‚งแ‚จแ‚ฉแ‚ชแ‚ซแ‚ฌแ‚ญแ‚ฎแ‚ฏแ‚ฐแ‚ฑแ‚ฒแ‚ณแ‚ดแ‚ตแ‚ถแ‚ทแ‚ธแ‚นแ‚บแ‚ปแ‚ผแ‚ฝแ‚พแ‚ฟแƒ€แƒแƒ‚แƒƒแƒ„แƒ…'; $this->assertEquals($expected, $result); $string = 'แธ€แธ‚แธ„แธ†แธˆแธŠแธŒแธŽแธแธ’แธ”แธ–แธ˜แธšแธœแธžแธ แธขแธคแธฆแธจแธชแธฌแธฎแธฐแธฒแธดแธถแธธแธบแธผแธพแน€แน‚แน„แน†แนˆแนŠแนŒแนŽแนแน’แน”แน–แน˜แนšแนœแนžแน แนขแนคแนฆแนจแนชแนฌแนฎแนฐแนฒแนดแนถแนธแนบแนผแนพแบ€แบ‚แบ„แบ†แบˆแบŠแบŒแบŽแบแบ’แบ”แบ–แบ—แบ˜แบ™แบšแบ แบขแบคแบฆแบจแบชแบฌแบฎแบฐแบฒแบดแบถแบธแบบแบผแบพแป€แป‚แป„แป†แปˆแปŠแปŒแปŽแปแป’แป”แป–แป˜แปšแปœแปžแป แปขแปคแปฆแปจแปชแปฌแปฎแปฐแปฒแปดแปถแปธ'; $result = Multibyte::strtolower($string); $expected = 'แธแธƒแธ…แธ‡แธ‰แธ‹แธแธแธ‘แธ“แธ•แธ—แธ™แธ›แธแธŸแธกแธฃแธฅแธงแธฉแธซแธญแธฏแธฑแธณแธตแธทแธนแธปแธฝแธฟแนแนƒแน…แน‡แน‰แน‹แนแนแน‘แน“แน•แน—แน™แน›แนแนŸแนกแนฃแนฅแนงแนฉแนซแนญแนฏแนฑแนณแนตแนทแนนแนปแนฝแนฟแบแบƒแบ…แบ‡แบ‰แบ‹แบแบแบ‘แบ“แบ•แบ–แบ—แบ˜แบ™แบšแบกแบฃแบฅแบงแบฉแบซแบญแบฏแบฑแบณแบตแบทแบนแบปแบฝแบฟแปแปƒแป…แป‡แป‰แป‹แปแปแป‘แป“แป•แป—แป™แป›แปแปŸแปกแปฃแปฅแปงแปฉแปซแปญแปฏแปฑแปณแปตแปทแปน'; $this->assertEquals($expected, $result); $string = 'โ„ฆโ„ชโ„ซโ„ฒ'; $result = Multibyte::strtolower($string); $expected = 'ฯ‰kรฅโ…Ž'; $this->assertEquals($expected, $result); $string = 'โ„ฆโ„ชโ„ซ'; $result = Multibyte::strtolower($string); $expected = 'ฯ‰kรฅ'; $this->assertEquals($expected, $result); $string = 'ฮฉKร…'; $result = Multibyte::strtolower($string); $expected = 'ฯ‰kรฅ'; $this->assertEquals($expected, $result); $string = 'โ… โ…กโ…ขโ…ฃโ…คโ…ฅโ…ฆโ…งโ…จโ…ฉโ…ชโ…ซโ…ฌโ…ญโ…ฎโ…ฏโ†ƒ'; $result = Multibyte::strtolower($string); $expected = 'โ…ฐโ…ฑโ…ฒโ…ณโ…ดโ…ตโ…ถโ…ทโ…ธโ…นโ…บโ…ปโ…ผโ…ฝโ…พโ…ฟโ†„'; $this->assertEquals($expected, $result); $string = 'โ’ถโ’ทโ’ธโ’นโ’บโ’ปโ’ผโ’ฝโ’พโ’ฟโ“€โ“โ“‚โ“ƒโ“„โ“…โ“†โ“‡โ“ˆโ“‰โ“Šโ“‹โ“Œโ“โ“Žโ“'; $result = Multibyte::strtolower($string); $expected = 'โ“โ“‘โ“’โ““โ“”โ“•โ“–โ“—โ“˜โ“™โ“šโ“›โ“œโ“โ“žโ“Ÿโ“ โ“กโ“ขโ“ฃโ“คโ“ฅโ“ฆโ“งโ“จโ“ฉ'; $this->assertEquals($expected, $result); $string = 'โฐ€โฐโฐ‚โฐƒโฐ„โฐ…โฐ†โฐ‡โฐˆโฐ‰โฐŠโฐ‹โฐŒโฐโฐŽโฐโฐโฐ‘โฐ’โฐ“โฐ”โฐ•โฐ–โฐ—โฐ˜โฐ™โฐšโฐ›โฐœโฐโฐžโฐŸโฐ โฐกโฐขโฐฃโฐคโฐฅโฐฆโฐงโฐจโฐฉโฐชโฐซโฐฌโฐญโฐฎ'; $result = Multibyte::strtolower($string); $expected = 'โฐฐโฐฑโฐฒโฐณโฐดโฐตโฐถโฐทโฐธโฐนโฐบโฐปโฐผโฐฝโฐพโฐฟโฑ€โฑโฑ‚โฑƒโฑ„โฑ…โฑ†โฑ‡โฑˆโฑ‰โฑŠโฑ‹โฑŒโฑโฑŽโฑโฑโฑ‘โฑ’โฑ“โฑ”โฑ•โฑ–โฑ—โฑ˜โฑ™โฑšโฑ›โฑœโฑโฑž'; $this->assertEquals($expected, $result); $string = 'โฒ€โฒ‚โฒ„โฒ†โฒˆโฒŠโฒŒโฒŽโฒโฒ’โฒ”โฒ–โฒ˜โฒšโฒœโฒžโฒ โฒขโฒคโฒฆโฒจโฒชโฒฌโฒฎโฒฐโฒฒโฒดโฒถโฒธโฒบโฒผโฒพโณ€โณ‚โณ„โณ†โณˆโณŠโณŒโณŽโณโณ’โณ”โณ–โณ˜โณšโณœโณžโณ โณข'; $result = Multibyte::strtolower($string); $expected = 'โฒโฒƒโฒ…โฒ‡โฒ‰โฒ‹โฒโฒโฒ‘โฒ“โฒ•โฒ—โฒ™โฒ›โฒโฒŸโฒกโฒฃโฒฅโฒงโฒฉโฒซโฒญโฒฏโฒฑโฒณโฒตโฒทโฒนโฒปโฒฝโฒฟโณโณƒโณ…โณ‡โณ‰โณ‹โณโณโณ‘โณ“โณ•โณ—โณ™โณ›โณโณŸโณกโณฃ'; $this->assertEquals($expected, $result); $string = '๏ฌ€๏ฌ๏ฌ‚๏ฌƒ๏ฌ„๏ฌ…๏ฌ†๏ฌ“๏ฌ”๏ฌ•๏ฌ–๏ฌ—'; $result = Multibyte::strtolower($string); $expected = '๏ฌ€๏ฌ๏ฌ‚๏ฌƒ๏ฌ„๏ฌ…๏ฌ†๏ฌ“๏ฌ”๏ฌ•๏ฌ–๏ฌ—'; $this->assertEquals($expected, $result); } /** * testUsingMbStrtoupper method * * @return void */ public function testUsingMbStrtoupper() { $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $result = mb_strtoupper($string); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@'; $result = mb_strtoupper($string); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@'; $this->assertEquals($expected, $result); $string = 'ร '; $result = mb_strtoupper($string); $expected = 'ร€'; $this->assertEquals($expected, $result); $string = 'รก'; $result = mb_strtoupper($string); $expected = 'ร'; $this->assertEquals($expected, $result); $string = 'รข'; $result = mb_strtoupper($string); $expected = 'ร‚'; $this->assertEquals($expected, $result); $string = 'รฃ'; $result = mb_strtoupper($string); $expected = 'รƒ'; $this->assertEquals($expected, $result); $string = 'รค'; $result = mb_strtoupper($string); $expected = 'ร„'; $this->assertEquals($expected, $result); $string = 'รฅ'; $result = mb_strtoupper($string); $expected = 'ร…'; $this->assertEquals($expected, $result); $string = 'รฆ'; $result = mb_strtoupper($string); $expected = 'ร†'; $this->assertEquals($expected, $result); $string = 'รง'; $result = mb_strtoupper($string); $expected = 'ร‡'; $this->assertEquals($expected, $result); $string = 'รจ'; $result = mb_strtoupper($string); $expected = 'รˆ'; $this->assertEquals($expected, $result); $string = 'รฉ'; $result = mb_strtoupper($string); $expected = 'ร‰'; $this->assertEquals($expected, $result); $string = 'รช'; $result = mb_strtoupper($string); $expected = 'รŠ'; $this->assertEquals($expected, $result); $string = 'รซ'; $result = mb_strtoupper($string); $expected = 'ร‹'; $this->assertEquals($expected, $result); $string = 'รฌ'; $result = mb_strtoupper($string); $expected = 'รŒ'; $this->assertEquals($expected, $result); $string = 'รญ'; $result = mb_strtoupper($string); $expected = 'ร'; $this->assertEquals($expected, $result); $string = 'รฎ'; $result = mb_strtoupper($string); $expected = 'รŽ'; $this->assertEquals($expected, $result); $string = 'รฏ'; $result = mb_strtoupper($string); $expected = 'ร'; $this->assertEquals($expected, $result); $string = 'รฐ'; $result = mb_strtoupper($string); $expected = 'ร'; $this->assertEquals($expected, $result); $string = 'รฑ'; $result = mb_strtoupper($string); $expected = 'ร‘'; $this->assertEquals($expected, $result); $string = 'รฒ'; $result = mb_strtoupper($string); $expected = 'ร’'; $this->assertEquals($expected, $result); $string = 'รณ'; $result = mb_strtoupper($string); $expected = 'ร“'; $this->assertEquals($expected, $result); $string = 'รด'; $result = mb_strtoupper($string); $expected = 'ร”'; $this->assertEquals($expected, $result); $string = 'รต'; $result = mb_strtoupper($string); $expected = 'ร•'; $this->assertEquals($expected, $result); $string = 'รถ'; $result = mb_strtoupper($string); $expected = 'ร–'; $this->assertEquals($expected, $result); $string = 'รธ'; $result = mb_strtoupper($string); $expected = 'ร˜'; $this->assertEquals($expected, $result); $string = 'รน'; $result = mb_strtoupper($string); $expected = 'ร™'; $this->assertEquals($expected, $result); $string = 'รบ'; $result = mb_strtoupper($string); $expected = 'รš'; $this->assertEquals($expected, $result); $string = 'รป'; $result = mb_strtoupper($string); $expected = 'ร›'; $this->assertEquals($expected, $result); $string = 'รผ'; $result = mb_strtoupper($string); $expected = 'รœ'; $this->assertEquals($expected, $result); $string = 'รฝ'; $result = mb_strtoupper($string); $expected = 'ร'; $this->assertEquals($expected, $result); $string = 'รพ'; $result = mb_strtoupper($string); $expected = 'รž'; $this->assertEquals($expected, $result); $string = 'ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพ'; $result = mb_strtoupper($string); $expected = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $this->assertEquals($expected, $result); $string = 'ฤ'; $result = mb_strtoupper($string); $expected = 'ฤ€'; $this->assertEquals($expected, $result); $string = 'ฤƒ'; $result = mb_strtoupper($string); $expected = 'ฤ‚'; $this->assertEquals($expected, $result); $string = 'ฤ…'; $result = mb_strtoupper($string); $expected = 'ฤ„'; $this->assertEquals($expected, $result); $string = 'ฤ‡'; $result = mb_strtoupper($string); $expected = 'ฤ†'; $this->assertEquals($expected, $result); $string = 'ฤ‰'; $result = mb_strtoupper($string); $expected = 'ฤˆ'; $this->assertEquals($expected, $result); $string = 'ฤ‹'; $result = mb_strtoupper($string); $expected = 'ฤŠ'; $this->assertEquals($expected, $result); $string = 'ฤ'; $result = mb_strtoupper($string); $expected = 'ฤŒ'; $this->assertEquals($expected, $result); $string = 'ฤ'; $result = mb_strtoupper($string); $expected = 'ฤŽ'; $this->assertEquals($expected, $result); $string = 'ฤ‘'; $result = mb_strtoupper($string); $expected = 'ฤ'; $this->assertEquals($expected, $result); $string = 'ฤ“'; $result = mb_strtoupper($string); $expected = 'ฤ’'; $this->assertEquals($expected, $result); $string = 'ฤ•'; $result = mb_strtoupper($string); $expected = 'ฤ”'; $this->assertEquals($expected, $result); $string = 'ฤ—'; $result = mb_strtoupper($string); $expected = 'ฤ–'; $this->assertEquals($expected, $result); $string = 'ฤ™'; $result = mb_strtoupper($string); $expected = 'ฤ˜'; $this->assertEquals($expected, $result); $string = 'ฤ›'; $result = mb_strtoupper($string); $expected = 'ฤš'; $this->assertEquals($expected, $result); $string = 'ฤ'; $result = mb_strtoupper($string); $expected = 'ฤœ'; $this->assertEquals($expected, $result); $string = 'ฤŸ'; $result = mb_strtoupper($string); $expected = 'ฤž'; $this->assertEquals($expected, $result); $string = 'ฤก'; $result = mb_strtoupper($string); $expected = 'ฤ '; $this->assertEquals($expected, $result); $string = 'ฤฃ'; $result = mb_strtoupper($string); $expected = 'ฤข'; $this->assertEquals($expected, $result); $string = 'ฤฅ'; $result = mb_strtoupper($string); $expected = 'ฤค'; $this->assertEquals($expected, $result); $string = 'ฤง'; $result = mb_strtoupper($string); $expected = 'ฤฆ'; $this->assertEquals($expected, $result); $string = 'ฤฉ'; $result = mb_strtoupper($string); $expected = 'ฤจ'; $this->assertEquals($expected, $result); $string = 'ฤซ'; $result = mb_strtoupper($string); $expected = 'ฤช'; $this->assertEquals($expected, $result); $string = 'ฤญ'; $result = mb_strtoupper($string); $expected = 'ฤฌ'; $this->assertEquals($expected, $result); $string = 'ฤฏ'; $result = mb_strtoupper($string); $expected = 'ฤฎ'; $this->assertEquals($expected, $result); $string = 'ฤณ'; $result = mb_strtoupper($string); $expected = 'ฤฒ'; $this->assertEquals($expected, $result); $string = 'ฤต'; $result = mb_strtoupper($string); $expected = 'ฤด'; $this->assertEquals($expected, $result); $string = 'ฤท'; $result = mb_strtoupper($string); $expected = 'ฤถ'; $this->assertEquals($expected, $result); $string = 'ฤบ'; $result = mb_strtoupper($string); $expected = 'ฤน'; $this->assertEquals($expected, $result); $string = 'ฤผ'; $result = mb_strtoupper($string); $expected = 'ฤป'; $this->assertEquals($expected, $result); $string = 'ฤพ'; $result = mb_strtoupper($string); $expected = 'ฤฝ'; $this->assertEquals($expected, $result); $string = 'ล€'; $result = mb_strtoupper($string); $expected = 'ฤฟ'; $this->assertEquals($expected, $result); $string = 'ล‚'; $result = mb_strtoupper($string); $expected = 'ล'; $this->assertEquals($expected, $result); $string = 'ล„'; $result = mb_strtoupper($string); $expected = 'ลƒ'; $this->assertEquals($expected, $result); $string = 'ล†'; $result = mb_strtoupper($string); $expected = 'ล…'; $this->assertEquals($expected, $result); $string = 'ลˆ'; $result = mb_strtoupper($string); $expected = 'ล‡'; $this->assertEquals($expected, $result); $string = 'ล‹'; $result = mb_strtoupper($string); $expected = 'ลŠ'; $this->assertEquals($expected, $result); $string = 'ล'; $result = mb_strtoupper($string); $expected = 'ลŒ'; $this->assertEquals($expected, $result); $string = 'ล'; $result = mb_strtoupper($string); $expected = 'ลŽ'; $this->assertEquals($expected, $result); $string = 'ล‘'; $result = mb_strtoupper($string); $expected = 'ล'; $this->assertEquals($expected, $result); $string = 'ล“'; $result = mb_strtoupper($string); $expected = 'ล’'; $this->assertEquals($expected, $result); $string = 'ล•'; $result = mb_strtoupper($string); $expected = 'ล”'; $this->assertEquals($expected, $result); $string = 'ล—'; $result = mb_strtoupper($string); $expected = 'ล–'; $this->assertEquals($expected, $result); $string = 'ล™'; $result = mb_strtoupper($string); $expected = 'ล˜'; $this->assertEquals($expected, $result); $string = 'ล›'; $result = mb_strtoupper($string); $expected = 'ลš'; $this->assertEquals($expected, $result); $string = 'ล'; $result = mb_strtoupper($string); $expected = 'ลœ'; $this->assertEquals($expected, $result); $string = 'ลŸ'; $result = mb_strtoupper($string); $expected = 'ลž'; $this->assertEquals($expected, $result); $string = 'ลก'; $result = mb_strtoupper($string); $expected = 'ล '; $this->assertEquals($expected, $result); $string = 'ลฃ'; $result = mb_strtoupper($string); $expected = 'ลข'; $this->assertEquals($expected, $result); $string = 'ลฅ'; $result = mb_strtoupper($string); $expected = 'ลค'; $this->assertEquals($expected, $result); $string = 'ลง'; $result = mb_strtoupper($string); $expected = 'ลฆ'; $this->assertEquals($expected, $result); $string = 'ลฉ'; $result = mb_strtoupper($string); $expected = 'ลจ'; $this->assertEquals($expected, $result); $string = 'ลซ'; $result = mb_strtoupper($string); $expected = 'ลช'; $this->assertEquals($expected, $result); $string = 'ลญ'; $result = mb_strtoupper($string); $expected = 'ลฌ'; $this->assertEquals($expected, $result); $string = 'ลฏ'; $result = mb_strtoupper($string); $expected = 'ลฎ'; $this->assertEquals($expected, $result); $string = 'ลฑ'; $result = mb_strtoupper($string); $expected = 'ลฐ'; $this->assertEquals($expected, $result); $string = 'ลณ'; $result = mb_strtoupper($string); $expected = 'ลฒ'; $this->assertEquals($expected, $result); $string = 'ลต'; $result = mb_strtoupper($string); $expected = 'ลด'; $this->assertEquals($expected, $result); $string = 'ลท'; $result = mb_strtoupper($string); $expected = 'ลถ'; $this->assertEquals($expected, $result); $string = 'ลบ'; $result = mb_strtoupper($string); $expected = 'ลน'; $this->assertEquals($expected, $result); $string = 'ลผ'; $result = mb_strtoupper($string); $expected = 'ลป'; $this->assertEquals($expected, $result); $string = 'ลพ'; $result = mb_strtoupper($string); $expected = 'ลฝ'; $this->assertEquals($expected, $result); $string = 'ฤฤƒฤ…ฤ‡ฤ‰ฤ‹ฤฤฤ‘ฤ“ฤ•ฤ—ฤ™ฤ›ฤฤŸฤกฤฃฤฅฤงฤฉฤซฤญฤฏฤณฤตฤทฤบฤผฤพล€ล‚ล„ล†ลˆล‹ลลล‘ล“ล•ล—ล™ล›ลลŸลกลฃลฅลงลฉลซลญลฏลฑลณลตลทลบลผลพ'; $result = mb_strtoupper($string); $expected = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $result = mb_strtoupper($string); $expected = 'ฤคฤ’ฤนฤปลŽ, ลดลล˜ฤปฤŽ!'; $this->assertEquals($expected, $result); $string = 'แผ€ฮน'; $result = mb_strtoupper($string); $expected = 'แผˆฮ™'; $this->assertEquals($expected, $result); $string = 'ิิƒิ…ิ‡ิ‰ิ‹ิิิิ’'; $result = mb_strtoupper($string); $expected = 'ิ€ิ‚ิ„ิ†ิˆิŠิŒิŽิิ’'; $this->assertEquals($expected, $result); $string = 'ีกีขีฃีคีฅีฆีงีจีฉีชีซีฌีญีฎีฏีฐีฑีฒีณีดีตีถีทีธีนีบีปีผีฝีพีฟึ€ึึ‚ึƒึ„ึ…ึ†ึ‡'; $result = mb_strtoupper($string); $expected = 'ิฑิฒิณิดิติถิทิธินิบิปิผิฝิพิฟี€ีี‚ีƒี„ี…ี†ี‡ีˆี‰ีŠี‹ีŒีีŽีีี‘ี’ี“ี”ี•ี–ึ‡'; $this->assertEquals($expected, $result); $string = 'แ‚ แ‚กแ‚ขแ‚ฃแ‚คแ‚ฅแ‚ฆแ‚งแ‚จแ‚ฉแ‚ชแ‚ซแ‚ฌแ‚ญแ‚ฎแ‚ฏแ‚ฐแ‚ฑแ‚ฒแ‚ณแ‚ดแ‚ตแ‚ถแ‚ทแ‚ธแ‚นแ‚บแ‚ปแ‚ผแ‚ฝแ‚พแ‚ฟแƒ€แƒแƒ‚แƒƒแƒ„แƒ…'; $result = mb_strtoupper($string); $expected = 'แ‚ แ‚กแ‚ขแ‚ฃแ‚คแ‚ฅแ‚ฆแ‚งแ‚จแ‚ฉแ‚ชแ‚ซแ‚ฌแ‚ญแ‚ฎแ‚ฏแ‚ฐแ‚ฑแ‚ฒแ‚ณแ‚ดแ‚ตแ‚ถแ‚ทแ‚ธแ‚นแ‚บแ‚ปแ‚ผแ‚ฝแ‚พแ‚ฟแƒ€แƒแƒ‚แƒƒแƒ„แƒ…'; $this->assertEquals($expected, $result); $string = 'แธแธƒแธ…แธ‡แธ‰แธ‹แธแธแธ‘แธ“แธ•แธ—แธ™แธ›แธแธŸแธกแธฃแธฅแธงแธฉแธซแธญแธฏแธฑแธณแธตแธทแธนแธปแธฝแธฟแนแนƒแน…แน‡แน‰แน‹แนแนแน‘แน“แน•แน—แน™แน›แนแนŸแนกแนฃแนฅแนงแนฉแนซแนญแนฏแนฑแนณแนตแนทแนนแนปแนฝแนฟแบแบƒแบ…แบ‡แบ‰แบ‹แบแบแบ‘แบ“แบ•แบ–แบ—แบ˜แบ™แบšแบกแบฃแบฅแบงแบฉแบซแบญแบฏแบฑแบณแบตแบทแบนแบปแบฝแบฟแปแปƒแป…แป‡แป‰แป‹แปแปแป‘แป“แป•แป—แป™แป›แปแปŸแปกแปฃแปฅแปงแปฉแปซแปญแปฏแปฑแปณแปตแปทแปน'; $result = mb_strtoupper($string); $expected = 'แธ€แธ‚แธ„แธ†แธˆแธŠแธŒแธŽแธแธ’แธ”แธ–แธ˜แธšแธœแธžแธ แธขแธคแธฆแธจแธชแธฌแธฎแธฐแธฒแธดแธถแธธแธบแธผแธพแน€แน‚แน„แน†แนˆแนŠแนŒแนŽแนแน’แน”แน–แน˜แนšแนœแนžแน แนขแนคแนฆแนจแนชแนฌแนฎแนฐแนฒแนดแนถแนธแนบแนผแนพแบ€แบ‚แบ„แบ†แบˆแบŠแบŒแบŽแบแบ’แบ”แบ–แบ—แบ˜แบ™แบšแบ แบขแบคแบฆแบจแบชแบฌแบฎแบฐแบฒแบดแบถแบธแบบแบผแบพแป€แป‚แป„แป†แปˆแปŠแปŒแปŽแปแป’แป”แป–แป˜แปšแปœแปžแป แปขแปคแปฆแปจแปชแปฌแปฎแปฐแปฒแปดแปถแปธ'; $this->assertEquals($expected, $result); $string = 'ฯ‰kรฅ'; $result = mb_strtoupper($string); $expected = 'ฮฉKร…'; $this->assertEquals($expected, $result); $string = '๏ฌ€๏ฌ๏ฌ‚๏ฌƒ๏ฌ„๏ฌ…๏ฌ†๏ฌ“๏ฌ”๏ฌ•๏ฌ–๏ฌ—'; $result = mb_strtoupper($string); $expected = '๏ฌ€๏ฌ๏ฌ‚๏ฌƒ๏ฌ„๏ฌ…๏ฌ†๏ฌ“๏ฌ”๏ฌ•๏ฌ–๏ฌ—'; $this->assertEquals($expected, $result); } /** * testMultibyteStrtoupper method * * @return void */ public function testMultibyteStrtoupper() { $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $result = Multibyte::strtoupper($string); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@'; $result = Multibyte::strtoupper($string); $expected = '!"#$%&\'()*+,-./0123456789:;<=>?@'; $this->assertEquals($expected, $result); $string = 'ร '; $result = Multibyte::strtoupper($string); $expected = 'ร€'; $this->assertEquals($expected, $result); $string = 'รก'; $result = Multibyte::strtoupper($string); $expected = 'ร'; $this->assertEquals($expected, $result); $string = 'รข'; $result = Multibyte::strtoupper($string); $expected = 'ร‚'; $this->assertEquals($expected, $result); $string = 'รฃ'; $result = Multibyte::strtoupper($string); $expected = 'รƒ'; $this->assertEquals($expected, $result); $string = 'รค'; $result = Multibyte::strtoupper($string); $expected = 'ร„'; $this->assertEquals($expected, $result); $string = 'รฅ'; $result = Multibyte::strtoupper($string); $expected = 'ร…'; $this->assertEquals($expected, $result); $string = 'รฆ'; $result = Multibyte::strtoupper($string); $expected = 'ร†'; $this->assertEquals($expected, $result); $string = 'รง'; $result = Multibyte::strtoupper($string); $expected = 'ร‡'; $this->assertEquals($expected, $result); $string = 'รจ'; $result = Multibyte::strtoupper($string); $expected = 'รˆ'; $this->assertEquals($expected, $result); $string = 'รฉ'; $result = Multibyte::strtoupper($string); $expected = 'ร‰'; $this->assertEquals($expected, $result); $string = 'รช'; $result = Multibyte::strtoupper($string); $expected = 'รŠ'; $this->assertEquals($expected, $result); $string = 'รซ'; $result = Multibyte::strtoupper($string); $expected = 'ร‹'; $this->assertEquals($expected, $result); $string = 'รฌ'; $result = Multibyte::strtoupper($string); $expected = 'รŒ'; $this->assertEquals($expected, $result); $string = 'รญ'; $result = Multibyte::strtoupper($string); $expected = 'ร'; $this->assertEquals($expected, $result); $string = 'รฎ'; $result = Multibyte::strtoupper($string); $expected = 'รŽ'; $this->assertEquals($expected, $result); $string = 'รฏ'; $result = Multibyte::strtoupper($string); $expected = 'ร'; $this->assertEquals($expected, $result); $string = 'รฐ'; $result = Multibyte::strtoupper($string); $expected = 'ร'; $this->assertEquals($expected, $result); $string = 'รฑ'; $result = Multibyte::strtoupper($string); $expected = 'ร‘'; $this->assertEquals($expected, $result); $string = 'รฒ'; $result = Multibyte::strtoupper($string); $expected = 'ร’'; $this->assertEquals($expected, $result); $string = 'รณ'; $result = Multibyte::strtoupper($string); $expected = 'ร“'; $this->assertEquals($expected, $result); $string = 'รด'; $result = Multibyte::strtoupper($string); $expected = 'ร”'; $this->assertEquals($expected, $result); $string = 'รต'; $result = Multibyte::strtoupper($string); $expected = 'ร•'; $this->assertEquals($expected, $result); $string = 'รถ'; $result = Multibyte::strtoupper($string); $expected = 'ร–'; $this->assertEquals($expected, $result); $string = 'รธ'; $result = Multibyte::strtoupper($string); $expected = 'ร˜'; $this->assertEquals($expected, $result); $string = 'รน'; $result = Multibyte::strtoupper($string); $expected = 'ร™'; $this->assertEquals($expected, $result); $string = 'รบ'; $result = Multibyte::strtoupper($string); $expected = 'รš'; $this->assertEquals($expected, $result); $string = 'รป'; $result = Multibyte::strtoupper($string); $expected = 'ร›'; $this->assertEquals($expected, $result); $string = 'รผ'; $result = Multibyte::strtoupper($string); $expected = 'รœ'; $this->assertEquals($expected, $result); $string = 'รฝ'; $result = Multibyte::strtoupper($string); $expected = 'ร'; $this->assertEquals($expected, $result); $string = 'รพ'; $result = Multibyte::strtoupper($string); $expected = 'รž'; $this->assertEquals($expected, $result); $string = 'ร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรธรนรบรปรผรฝรพ'; $result = Multibyte::strtoupper($string); $expected = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $this->assertEquals($expected, $result); $string = 'ฤ'; $result = Multibyte::strtoupper($string); $expected = 'ฤ€'; $this->assertEquals($expected, $result); $string = 'ฤƒ'; $result = Multibyte::strtoupper($string); $expected = 'ฤ‚'; $this->assertEquals($expected, $result); $string = 'ฤ…'; $result = Multibyte::strtoupper($string); $expected = 'ฤ„'; $this->assertEquals($expected, $result); $string = 'ฤ‡'; $result = Multibyte::strtoupper($string); $expected = 'ฤ†'; $this->assertEquals($expected, $result); $string = 'ฤ‰'; $result = Multibyte::strtoupper($string); $expected = 'ฤˆ'; $this->assertEquals($expected, $result); $string = 'ฤ‹'; $result = Multibyte::strtoupper($string); $expected = 'ฤŠ'; $this->assertEquals($expected, $result); $string = 'ฤ'; $result = Multibyte::strtoupper($string); $expected = 'ฤŒ'; $this->assertEquals($expected, $result); $string = 'ฤ'; $result = Multibyte::strtoupper($string); $expected = 'ฤŽ'; $this->assertEquals($expected, $result); $string = 'ฤ‘'; $result = Multibyte::strtoupper($string); $expected = 'ฤ'; $this->assertEquals($expected, $result); $string = 'ฤ“'; $result = Multibyte::strtoupper($string); $expected = 'ฤ’'; $this->assertEquals($expected, $result); $string = 'ฤ•'; $result = Multibyte::strtoupper($string); $expected = 'ฤ”'; $this->assertEquals($expected, $result); $string = 'ฤ—'; $result = Multibyte::strtoupper($string); $expected = 'ฤ–'; $this->assertEquals($expected, $result); $string = 'ฤ™'; $result = Multibyte::strtoupper($string); $expected = 'ฤ˜'; $this->assertEquals($expected, $result); $string = 'ฤ›'; $result = Multibyte::strtoupper($string); $expected = 'ฤš'; $this->assertEquals($expected, $result); $string = 'ฤ'; $result = Multibyte::strtoupper($string); $expected = 'ฤœ'; $this->assertEquals($expected, $result); $string = 'ฤŸ'; $result = Multibyte::strtoupper($string); $expected = 'ฤž'; $this->assertEquals($expected, $result); $string = 'ฤก'; $result = Multibyte::strtoupper($string); $expected = 'ฤ '; $this->assertEquals($expected, $result); $string = 'ฤฃ'; $result = Multibyte::strtoupper($string); $expected = 'ฤข'; $this->assertEquals($expected, $result); $string = 'ฤฅ'; $result = Multibyte::strtoupper($string); $expected = 'ฤค'; $this->assertEquals($expected, $result); $string = 'ฤง'; $result = Multibyte::strtoupper($string); $expected = 'ฤฆ'; $this->assertEquals($expected, $result); $string = 'ฤฉ'; $result = Multibyte::strtoupper($string); $expected = 'ฤจ'; $this->assertEquals($expected, $result); $string = 'ฤซ'; $result = Multibyte::strtoupper($string); $expected = 'ฤช'; $this->assertEquals($expected, $result); $string = 'ฤญ'; $result = Multibyte::strtoupper($string); $expected = 'ฤฌ'; $this->assertEquals($expected, $result); $string = 'ฤฏ'; $result = Multibyte::strtoupper($string); $expected = 'ฤฎ'; $this->assertEquals($expected, $result); $string = 'ฤณ'; $result = Multibyte::strtoupper($string); $expected = 'ฤฒ'; $this->assertEquals($expected, $result); $string = 'ฤต'; $result = Multibyte::strtoupper($string); $expected = 'ฤด'; $this->assertEquals($expected, $result); $string = 'ฤท'; $result = Multibyte::strtoupper($string); $expected = 'ฤถ'; $this->assertEquals($expected, $result); $string = 'ฤบ'; $result = Multibyte::strtoupper($string); $expected = 'ฤน'; $this->assertEquals($expected, $result); $string = 'ฤผ'; $result = Multibyte::strtoupper($string); $expected = 'ฤป'; $this->assertEquals($expected, $result); $string = 'ฤพ'; $result = Multibyte::strtoupper($string); $expected = 'ฤฝ'; $this->assertEquals($expected, $result); $string = 'ล€'; $result = Multibyte::strtoupper($string); $expected = 'ฤฟ'; $this->assertEquals($expected, $result); $string = 'ล‚'; $result = Multibyte::strtoupper($string); $expected = 'ล'; $this->assertEquals($expected, $result); $string = 'ล„'; $result = Multibyte::strtoupper($string); $expected = 'ลƒ'; $this->assertEquals($expected, $result); $string = 'ล†'; $result = Multibyte::strtoupper($string); $expected = 'ล…'; $this->assertEquals($expected, $result); $string = 'ลˆ'; $result = Multibyte::strtoupper($string); $expected = 'ล‡'; $this->assertEquals($expected, $result); $string = 'ล‹'; $result = Multibyte::strtoupper($string); $expected = 'ลŠ'; $this->assertEquals($expected, $result); $string = 'ล'; $result = Multibyte::strtoupper($string); $expected = 'ลŒ'; $this->assertEquals($expected, $result); $string = 'ล'; $result = Multibyte::strtoupper($string); $expected = 'ลŽ'; $this->assertEquals($expected, $result); $string = 'ล‘'; $result = Multibyte::strtoupper($string); $expected = 'ล'; $this->assertEquals($expected, $result); $string = 'ล“'; $result = Multibyte::strtoupper($string); $expected = 'ล’'; $this->assertEquals($expected, $result); $string = 'ล•'; $result = Multibyte::strtoupper($string); $expected = 'ล”'; $this->assertEquals($expected, $result); $string = 'ล—'; $result = Multibyte::strtoupper($string); $expected = 'ล–'; $this->assertEquals($expected, $result); $string = 'ล™'; $result = Multibyte::strtoupper($string); $expected = 'ล˜'; $this->assertEquals($expected, $result); $string = 'ล›'; $result = Multibyte::strtoupper($string); $expected = 'ลš'; $this->assertEquals($expected, $result); $string = 'ล'; $result = Multibyte::strtoupper($string); $expected = 'ลœ'; $this->assertEquals($expected, $result); $string = 'ลŸ'; $result = Multibyte::strtoupper($string); $expected = 'ลž'; $this->assertEquals($expected, $result); $string = 'ลก'; $result = Multibyte::strtoupper($string); $expected = 'ล '; $this->assertEquals($expected, $result); $string = 'ลฃ'; $result = Multibyte::strtoupper($string); $expected = 'ลข'; $this->assertEquals($expected, $result); $string = 'ลฅ'; $result = Multibyte::strtoupper($string); $expected = 'ลค'; $this->assertEquals($expected, $result); $string = 'ลง'; $result = Multibyte::strtoupper($string); $expected = 'ลฆ'; $this->assertEquals($expected, $result); $string = 'ลฉ'; $result = Multibyte::strtoupper($string); $expected = 'ลจ'; $this->assertEquals($expected, $result); $string = 'ลซ'; $result = Multibyte::strtoupper($string); $expected = 'ลช'; $this->assertEquals($expected, $result); $string = 'ลญ'; $result = Multibyte::strtoupper($string); $expected = 'ลฌ'; $this->assertEquals($expected, $result); $string = 'ลฏ'; $result = Multibyte::strtoupper($string); $expected = 'ลฎ'; $this->assertEquals($expected, $result); $string = 'ลฑ'; $result = Multibyte::strtoupper($string); $expected = 'ลฐ'; $this->assertEquals($expected, $result); $string = 'ลณ'; $result = Multibyte::strtoupper($string); $expected = 'ลฒ'; $this->assertEquals($expected, $result); $string = 'ลต'; $result = Multibyte::strtoupper($string); $expected = 'ลด'; $this->assertEquals($expected, $result); $string = 'ลท'; $result = Multibyte::strtoupper($string); $expected = 'ลถ'; $this->assertEquals($expected, $result); $string = 'ลบ'; $result = Multibyte::strtoupper($string); $expected = 'ลน'; $this->assertEquals($expected, $result); $string = 'ลผ'; $result = Multibyte::strtoupper($string); $expected = 'ลป'; $this->assertEquals($expected, $result); $string = 'ลพ'; $result = Multibyte::strtoupper($string); $expected = 'ลฝ'; $this->assertEquals($expected, $result); $string = 'ฤฤƒฤ…ฤ‡ฤ‰ฤ‹ฤฤฤ‘ฤ“ฤ•ฤ—ฤ™ฤ›ฤฤŸฤกฤฃฤฅฤงฤฉฤซฤญฤฏฤณฤตฤทฤบฤผฤพล€ล‚ล„ล†ลˆล‹ลลล‘ล“ล•ล—ล™ล›ลลŸลกลฃลฅลงลฉลซลญลฏลฑลณลตลทลบลผลพ'; $result = Multibyte::strtoupper($string); $expected = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $result = Multibyte::strtoupper($string); $expected = 'ฤคฤ’ฤนฤปลŽ, ลดลล˜ฤปฤŽ!'; $this->assertEquals($expected, $result); $string = 'แผ€ฮน'; $result = mb_strtoupper($string); $expected = 'แผˆฮ™'; $this->assertEquals($expected, $result); $string = 'แผ€ฮน'; $result = Multibyte::strtoupper($string); $expected = 'แผˆฮ™'; $this->assertEquals($expected, $result); $string = 'ิิƒิ…ิ‡ิ‰ิ‹ิิิิ’'; $result = Multibyte::strtoupper($string); $expected = 'ิ€ิ‚ิ„ิ†ิˆิŠิŒิŽิิ’'; $this->assertEquals($expected, $result); $string = 'ีกีขีฃีคีฅีฆีงีจีฉีชีซีฌีญีฎีฏีฐีฑีฒีณีดีตีถีทีธีนีบีปีผีฝีพีฟึ€ึึ‚ึƒึ„ึ…ึ†ึ‡'; $result = Multibyte::strtoupper($string); $expected = 'ิฑิฒิณิดิติถิทิธินิบิปิผิฝิพิฟี€ีี‚ีƒี„ี…ี†ี‡ีˆี‰ีŠี‹ีŒีีŽีีี‘ี’ี“ี”ี•ี–ึ‡'; $this->assertEquals($expected, $result); $string = 'แ‚ แ‚กแ‚ขแ‚ฃแ‚คแ‚ฅแ‚ฆแ‚งแ‚จแ‚ฉแ‚ชแ‚ซแ‚ฌแ‚ญแ‚ฎแ‚ฏแ‚ฐแ‚ฑแ‚ฒแ‚ณแ‚ดแ‚ตแ‚ถแ‚ทแ‚ธแ‚นแ‚บแ‚ปแ‚ผแ‚ฝแ‚พแ‚ฟแƒ€แƒแƒ‚แƒƒแƒ„แƒ…'; $result = Multibyte::strtoupper($string); $expected = 'แ‚ แ‚กแ‚ขแ‚ฃแ‚คแ‚ฅแ‚ฆแ‚งแ‚จแ‚ฉแ‚ชแ‚ซแ‚ฌแ‚ญแ‚ฎแ‚ฏแ‚ฐแ‚ฑแ‚ฒแ‚ณแ‚ดแ‚ตแ‚ถแ‚ทแ‚ธแ‚นแ‚บแ‚ปแ‚ผแ‚ฝแ‚พแ‚ฟแƒ€แƒแƒ‚แƒƒแƒ„แƒ…'; $this->assertEquals($expected, $result); $string = 'แธแธƒแธ…แธ‡แธ‰แธ‹แธแธแธ‘แธ“แธ•แธ—แธ™แธ›แธแธŸแธกแธฃแธฅแธงแธฉแธซแธญแธฏแธฑแธณแธตแธทแธนแธปแธฝแธฟแนแนƒแน…แน‡แน‰แน‹แนแนแน‘แน“แน•แน—แน™แน›แนแนŸแนกแนฃแนฅแนงแนฉแนซแนญแนฏแนฑแนณแนตแนทแนนแนปแนฝแนฟแบแบƒแบ…แบ‡แบ‰แบ‹แบแบแบ‘แบ“แบ•แบ–แบ—แบ˜แบ™แบšแบกแบฃแบฅแบงแบฉแบซแบญแบฏแบฑแบณแบตแบทแบนแบปแบฝแบฟแปแปƒแป…แป‡แป‰แป‹แปแปแป‘แป“แป•แป—แป™แป›แปแปŸแปกแปฃแปฅแปงแปฉแปซแปญแปฏแปฑแปณแปตแปทแปน'; $result = Multibyte::strtoupper($string); $expected = 'แธ€แธ‚แธ„แธ†แธˆแธŠแธŒแธŽแธแธ’แธ”แธ–แธ˜แธšแธœแธžแธ แธขแธคแธฆแธจแธชแธฌแธฎแธฐแธฒแธดแธถแธธแธบแธผแธพแน€แน‚แน„แน†แนˆแนŠแนŒแนŽแนแน’แน”แน–แน˜แนšแนœแนžแน แนขแนคแนฆแนจแนชแนฌแนฎแนฐแนฒแนดแนถแนธแนบแนผแนพแบ€แบ‚แบ„แบ†แบˆแบŠแบŒแบŽแบแบ’แบ”แบ–แบ—แบ˜แบ™แบšแบ แบขแบคแบฆแบจแบชแบฌแบฎแบฐแบฒแบดแบถแบธแบบแบผแบพแป€แป‚แป„แป†แปˆแปŠแปŒแปŽแปแป’แป”แป–แป˜แปšแปœแปžแป แปขแปคแปฆแปจแปชแปฌแปฎแปฐแปฒแปดแปถแปธ'; $this->assertEquals($expected, $result); $string = 'ฯ‰kรฅโ…Ž'; $result = Multibyte::strtoupper($string); $expected = 'ฮฉKร…โ„ฒ'; $this->assertEquals($expected, $result); $string = 'ฯ‰kรฅ'; $result = Multibyte::strtoupper($string); $expected = 'ฮฉKร…'; $this->assertEquals($expected, $result); $string = 'โ…ฐโ…ฑโ…ฒโ…ณโ…ดโ…ตโ…ถโ…ทโ…ธโ…นโ…บโ…ปโ…ผโ…ฝโ…พโ…ฟโ†„'; $result = Multibyte::strtoupper($string); $expected = 'โ… โ…กโ…ขโ…ฃโ…คโ…ฅโ…ฆโ…งโ…จโ…ฉโ…ชโ…ซโ…ฌโ…ญโ…ฎโ…ฏโ†ƒ'; $this->assertEquals($expected, $result); $string = 'โ“โ“‘โ“’โ““โ“”โ“•โ“–โ“—โ“˜โ“™โ“šโ“›โ“œโ“โ“žโ“Ÿโ“ โ“กโ“ขโ“ฃโ“คโ“ฅโ“ฆโ“งโ“จโ“ฉ'; $result = Multibyte::strtoupper($string); $expected = 'โ’ถโ’ทโ’ธโ’นโ’บโ’ปโ’ผโ’ฝโ’พโ’ฟโ“€โ“โ“‚โ“ƒโ“„โ“…โ“†โ“‡โ“ˆโ“‰โ“Šโ“‹โ“Œโ“โ“Žโ“'; $this->assertEquals($expected, $result); $string = 'โฐฐโฐฑโฐฒโฐณโฐดโฐตโฐถโฐทโฐธโฐนโฐบโฐปโฐผโฐฝโฐพโฐฟโฑ€โฑโฑ‚โฑƒโฑ„โฑ…โฑ†โฑ‡โฑˆโฑ‰โฑŠโฑ‹โฑŒโฑโฑŽโฑโฑโฑ‘โฑ’โฑ“โฑ”โฑ•โฑ–โฑ—โฑ˜โฑ™โฑšโฑ›โฑœโฑโฑž'; $result = Multibyte::strtoupper($string); $expected = 'โฐ€โฐโฐ‚โฐƒโฐ„โฐ…โฐ†โฐ‡โฐˆโฐ‰โฐŠโฐ‹โฐŒโฐโฐŽโฐโฐโฐ‘โฐ’โฐ“โฐ”โฐ•โฐ–โฐ—โฐ˜โฐ™โฐšโฐ›โฐœโฐโฐžโฐŸโฐ โฐกโฐขโฐฃโฐคโฐฅโฐฆโฐงโฐจโฐฉโฐชโฐซโฐฌโฐญโฐฎ'; $this->assertEquals($expected, $result); $string = 'โฒโฒƒโฒ…โฒ‡โฒ‰โฒ‹โฒโฒโฒ‘โฒ“โฒ•โฒ—โฒ™โฒ›โฒโฒŸโฒกโฒฃโฒฅโฒงโฒฉโฒซโฒญโฒฏโฒฑโฒณโฒตโฒทโฒนโฒปโฒฝโฒฟโณโณƒโณ…โณ‡โณ‰โณ‹โณโณโณ‘โณ“โณ•โณ—โณ™โณ›โณโณŸโณกโณฃ'; $result = Multibyte::strtoupper($string); $expected = 'โฒ€โฒ‚โฒ„โฒ†โฒˆโฒŠโฒŒโฒŽโฒโฒ’โฒ”โฒ–โฒ˜โฒšโฒœโฒžโฒ โฒขโฒคโฒฆโฒจโฒชโฒฌโฒฎโฒฐโฒฒโฒดโฒถโฒธโฒบโฒผโฒพโณ€โณ‚โณ„โณ†โณˆโณŠโณŒโณŽโณโณ’โณ”โณ–โณ˜โณšโณœโณžโณ โณข'; $this->assertEquals($expected, $result); $string = '๏ฌ€๏ฌ๏ฌ‚๏ฌƒ๏ฌ„๏ฌ…๏ฌ†๏ฌ“๏ฌ”๏ฌ•๏ฌ–๏ฌ—'; $result = Multibyte::strtoupper($string); $expected = '๏ฌ€๏ฌ๏ฌ‚๏ฌƒ๏ฌ„๏ฌ…๏ฌ†๏ฌ“๏ฌ”๏ฌ•๏ฌ–๏ฌ—'; $this->assertEquals($expected, $result); } /** * testUsingMbSubstrCount method * * @return void */ public function testUsingMbSubstrCount() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = mb_substr_count($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQFRSFTUVWXYZ0F12345F6789'; $find = 'F'; $result = mb_substr_count($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰ร…รŠร‹รŒรรŽรรร‘ร’ร“ร”ร…ร•ร–ร˜ร…ร™รšร›ร…รœรรž'; $find = 'ร…'; $result = mb_substr_count($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร€รร™รšร‚รƒร„ร…ร†ร‡รˆร™รšร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรžร™รš'; $find = 'ร™รš'; $result = mb_substr_count($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร…ร‹รŒรรŽรรร‘ร’ร“ร”ร•ร…ร–ร˜ร…ร™รšร…ร›รœร…รรžร…'; $find = 'ร…'; $result = mb_substr_count($string, $find); $expected = 7; $this->assertEquals($expected, $result); $string = 'ฤŠฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤŠฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤŠฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒฤŠลŽลล’ล”ล–ล˜ลšลœลžล ลขฤŠลคลฆลจลชลฌลฎลฐฤŠลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_substr_count($string, $find); $expected = 7; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤŠฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลฤŠลƒล…ฤŠล‡ลŠลŒลŽลล’ล”ล–ฤŠล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = mb_substr_count($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./012F34567F89:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghiFjklmnopqFrstuvwFxyz{|}~'; $find = 'F'; $result = mb_substr_count($string, $find); $expected = 6; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยตยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รยตร‚รƒยตร„ร…ร†ร‡ยตรˆ'; $find = 'ยต'; $result = mb_substr_count($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดร•ร–รตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ร•ร–ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤร•ร–ฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆร•ร–ฤงฤจฤฉฤชฤซฤฌ'; $find = 'ร•ร–'; $result = mb_substr_count($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลฤตฤถฤทฤธฤนลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกฤตฤถฤทฤธฤนลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณฤตฤถฤทฤธฤนลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ฤตฤถฤทฤธฤน'; $result = mb_substr_count($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦธฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠฦธว‹วŒววŽววว‘ว’ว“ฦธว”ว•ว–ว—ว˜ว™วšฦธว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = mb_substr_count($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦนฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦนฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦนฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚ฦนวƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦน'; $result = mb_substr_count($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžส€ษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส€ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงส€สจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบส€สปสผ'; $find = 'ส€'; $result = mb_substr_count($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะ‡ะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = mb_substr_count($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะ ะขะฃะคะฅะฆะงะจะฉะชะซะฌะ ะญะฎะฏะฐะฑะ ะฒะณะดะตะถะทะธะนะบะปะ ะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = mb_substr_count($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกั€ะขะฃะคะฅะฆะงะจะฉะชะซั€ะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ั€'; $result = mb_substr_count($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ูู†ู‚ูƒู„ู†ู…ู†ู‡ูˆู†ู‰ูŠู†ู‹ูŒููŽู'; $find = 'ู†'; $result = mb_substr_count($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœฟโœดโœตโœถโœทโœธโœฟโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โœฟโ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = mb_substr_count($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบโบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โบโปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = mb_substr_count($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝคโฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝคโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = mb_substr_count($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆบ๋ˆป๋ˆผ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋ˆบ๋ˆป๋ˆผ๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋ˆบ๋ˆป๋ˆผ๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆบ๋ˆป๋ˆผ'; $result = mb_substr_count($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = '๏บž๏บŸ๏บ ๏บก๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บž๏บŸ๏บ ๏บก๏บ†๏บ‡๏บž๏บŸ๏บ ๏บก๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž๏บŸ๏บ ๏บก'; $result = mb_substr_count($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏ปž๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ปž๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปž๏ปธ๏ปน๏ปบ๏ปž๏ปป๏ปผ'; $find = '๏ปž'; $result = mb_substr_count($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ‹๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ‹๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = mb_substr_count($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝ‹๏ฝŒ๏ฝ๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ‹๏ฝŒ๏ฝ๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹๏ฝŒ๏ฝ'; $result = mb_substr_count($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ๏ฝ๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ๏ฝ๏ฝ…'; $result = mb_substr_count($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = mb_substr_count($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = mb_substr_count($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = mb_substr_count($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ฤบฤผ'; $result = mb_substr_count($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = mb_substr_count($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rl'; $result = mb_substr_count($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = mb_substr_count($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'niฤiniฤiini'; $find = 'n'; $result = mb_substr_count($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = mb_substr_count($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'moฤ‡imoฤ‡imoฤ‡mฤ‡ioฤ‡i'; $find = 'ฤ‡i'; $result = mb_substr_count($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = mb_substr_count($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = mb_substr_count($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = mb_substr_count($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'H'; $result = mb_substr_count($string, $find); $expected = 0; $this->assertEquals($expected, $result); } /** * testMultibyteSubstrCount method * * @return void */ public function testMultibyteSubstrCount() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $find = 'F'; $result = Multibyte::substrCount($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ABCDEFGHIJKLMNOPQFRSFTUVWXYZ0F12345F6789'; $find = 'F'; $result = Multibyte::substrCount($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰ร…รŠร‹รŒรรŽรรร‘ร’ร“ร”ร…ร•ร–ร˜ร…ร™รšร›ร…รœรรž'; $find = 'ร…'; $result = Multibyte::substrCount($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร€รร™รšร‚รƒร„ร…ร†ร‡รˆร™รšร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร…ร™รšร›รœรรžร™รš'; $find = 'ร™รš'; $result = Multibyte::substrCount($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร…ร‹รŒรรŽรรร‘ร’ร“ร”ร•ร…ร–ร˜ร…ร™รšร…ร›รœร…รรžร…'; $find = 'ร…'; $result = Multibyte::substrCount($string, $find); $expected = 7; $this->assertEquals($expected, $result); $string = 'ฤŠฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤŠฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤŠฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒฤŠลŽลล’ล”ล–ล˜ลšลœลžล ลขฤŠลคลฆลจลชลฌลฎลฐฤŠลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::substrCount($string, $find); $expected = 7; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤŠฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลฤŠลƒล…ฤŠล‡ลŠลŒลŽลล’ล”ล–ฤŠล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $find = 'ฤŠ'; $result = Multibyte::substrCount($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./012F34567F89:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghiFjklmnopqFrstuvwFxyz{|}~'; $find = 'F'; $result = Multibyte::substrCount($string, $find); $expected = 6; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยตยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รยตร‚รƒยตร„ร…ร†ร‡ยตรˆ'; $find = 'ยต'; $result = Multibyte::substrCount($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดร•ร–รตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ร•ร–ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤร•ร–ฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆร•ร–ฤงฤจฤฉฤชฤซฤฌ'; $find = 'ร•ร–'; $result = Multibyte::substrCount($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลฤตฤถฤทฤธฤนลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกฤตฤถฤทฤธฤนลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณฤตฤถฤทฤธฤนลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $find = 'ฤตฤถฤทฤธฤน'; $result = Multibyte::substrCount($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦธฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠฦธว‹วŒววŽววว‘ว’ว“ฦธว”ว•ว–ว—ว˜ว™วšฦธว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦธ'; $result = Multibyte::substrCount($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦนฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦนฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦนฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚ฦนวƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $find = 'ฦน'; $result = Multibyte::substrCount($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžส€ษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส€ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงส€สจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบส€สปสผ'; $find = 'ส€'; $result = Multibyte::substrCount($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะ‡ะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $find = 'ะ‡'; $result = Multibyte::substrCount($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะ ะขะฃะคะฅะฆะงะจะฉะชะซะฌะ ะญะฎะฏะฐะฑะ ะฒะณะดะตะถะทะธะนะบะปะ ะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ะ '; $result = Multibyte::substrCount($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกั€ะขะฃะคะฅะฆะงะจะฉะชะซั€ะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $find = 'ั€'; $result = Multibyte::substrCount($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'ูู†ู‚ูƒู„ู†ู…ู†ู‡ูˆู†ู‰ูŠู†ู‹ูŒููŽู'; $find = 'ู†'; $result = Multibyte::substrCount($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœฟโœดโœตโœถโœทโœธโœฟโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โœฟโ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $find = 'โœฟ'; $result = Multibyte::substrCount($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบโบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โบโปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $find = 'โบ'; $result = Multibyte::substrCount($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝคโฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝคโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $find = 'โฝค'; $result = Multibyte::substrCount($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆบ๋ˆป๋ˆผ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋ˆบ๋ˆป๋ˆผ๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋ˆบ๋ˆป๋ˆผ๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $find = '๋ˆบ๋ˆป๋ˆผ'; $result = Multibyte::substrCount($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = '๏บž๏บŸ๏บ ๏บก๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บž๏บŸ๏บ ๏บก๏บ†๏บ‡๏บž๏บŸ๏บ ๏บก๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $find = '๏บž๏บŸ๏บ ๏บก'; $result = Multibyte::substrCount($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏ปž๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ปž๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปž๏ปธ๏ปน๏ปบ๏ปž๏ปป๏ปผ'; $find = '๏ปž'; $result = Multibyte::substrCount($string, $find); $expected = 5; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ‹๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ‹๏ฝ™๏ฝš'; $find = '๏ฝ‹'; $result = Multibyte::substrCount($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝ‹๏ฝŒ๏ฝ๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ‹๏ฝŒ๏ฝ๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ‹๏ฝŒ๏ฝ'; $result = Multibyte::substrCount($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ๏ฝ๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $find = '๏ฝ๏ฝ๏ฝ…'; $result = Multibyte::substrCount($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $find = '๏ฝฑ'; $result = Multibyte::substrCount($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $find = '๏พŠ'; $result = Multibyte::substrCount($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ล‘'; $result = Multibyte::substrCount($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'ฤบฤผ'; $result = Multibyte::substrCount($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'o'; $result = Multibyte::substrCount($string, $find); $expected = 2; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $find = 'rl'; $result = Multibyte::substrCount($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ฤini'; $find = 'n'; $result = Multibyte::substrCount($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'niฤiniฤiini'; $find = 'n'; $result = Multibyte::substrCount($string, $find); $expected = 3; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $find = 'ฤ‡'; $result = Multibyte::substrCount($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'moฤ‡imoฤ‡imoฤ‡mฤ‡ioฤ‡i'; $find = 'ฤ‡i'; $result = Multibyte::substrCount($string, $find); $expected = 4; $this->assertEquals($expected, $result); $string = 'drลพavni'; $find = 'ลพ'; $result = Multibyte::substrCount($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $find = '่ฎพ'; $result = Multibyte::substrCount($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $find = 'ๅ‘จ'; $result = Multibyte::substrCount($string, $find); $expected = 1; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $find = 'H'; $result = Multibyte::substrCount($string, $find); $expected = 0; $this->assertEquals($expected, $result); } /** * testUsingMbSubstr method * * @return void */ public function testUsingMbSubstr() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $result = mb_substr($string, 4, 7); $expected = 'EFGHIJK'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $result = mb_substr($string, 4, 7); $expected = 'ร„ร…ร†ร‡รˆร‰รŠ'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $result = mb_substr($string, 4, 7); $expected = 'ฤˆฤŠฤŒฤŽฤฤ’ฤ”'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $result = mb_substr($string, 4, 7); $expected = '%&\'()*+'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $result = mb_substr($string, 4); $expected = 'ยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $result = mb_substr($string, 4, 7); $expected = 'รรŽรรร‘ร’ร“'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $result = mb_substr($string, 4, 7); $expected = 'ฤฑฤฒฤณฤดฤตฤถฤท'; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $result = mb_substr($string, 25); $expected = 'ฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $result = mb_substr($string, 3); $expected = 'ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $result = mb_substr($string, 3); $expected = 'ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $result = mb_substr($string, 3, 16); $expected = 'ะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎ'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $result = mb_substr($string, 3, 6); $expected = 'ู„ู…ู†ู‡ูˆู‰'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $result = mb_substr($string, 6, 14); $expected = 'โœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒ'; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $result = mb_substr($string, 8, 13); $expected = 'โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $result = mb_substr($string, 12, 24); $expected = 'โฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจ'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $result = mb_substr($string, 12, 24); $expected = '๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $result = mb_substr($string, 12); $expected = '๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $result = mb_substr($string, 24, 12); $expected = '๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $result = mb_substr($string, 11, 2); $expected = '๏ฝŒ๏ฝ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $result = mb_substr($string, 7, 11); $expected = '๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $result = mb_substr($string, 13, 13); $expected = '๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $result = mb_substr($string, 3, 4); $expected = 'ฤผล, '; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $result = mb_substr($string, 3, 4); $expected = 'lo, '; $this->assertEquals($expected, $result); $string = 'ฤini'; $result = mb_substr($string, 3); $expected = 'i'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $result = mb_substr($string, 1); $expected = 'oฤ‡i'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $result = mb_substr($string, 0, 2); $expected = 'dr'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $result = mb_substr($string, 3, 3); $expected = '่ฎพไธบ้ฆ–'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $result = mb_substr($string, 0, 1); $expected = 'ไธ€'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $result = mb_substr($string, 6); $expected = false; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $result = mb_substr($string, 0); $expected = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $this->assertEquals($expected, $result); } /** * testMultibyteSubstr method * * @return void */ public function testMultibyteSubstr() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $result = Multibyte::substr($string, 4, 7); $expected = 'EFGHIJK'; $this->assertEquals($expected, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $result = Multibyte::substr($string, 4, 7); $expected = 'ร„ร…ร†ร‡รˆร‰รŠ'; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $result = Multibyte::substr($string, 4, 7); $expected = 'ฤˆฤŠฤŒฤŽฤฤ’ฤ”'; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $result = Multibyte::substr($string, 4, 7); $expected = '%&\'()*+'; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $result = Multibyte::substr($string, 4); $expected = 'ยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $result = Multibyte::substr($string, 4, 7); $expected = 'รรŽรรร‘ร’ร“'; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $result = Multibyte::substr($string, 4, 7); $expected = 'ฤฑฤฒฤณฤดฤตฤถฤท'; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $result = Multibyte::substr($string, 25); $expected = 'ฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $result = Multibyte::substr($string, 3); $expected = 'ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $result = Multibyte::substr($string, 3); $expected = 'ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $result = Multibyte::substr($string, 3, 16); $expected = 'ะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎ'; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $result = Multibyte::substr($string, 3, 6); $expected = 'ู„ู…ู†ู‡ูˆู‰'; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $result = Multibyte::substr($string, 6, 14); $expected = 'โœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒ'; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $result = Multibyte::substr($string, 8, 13); $expected = 'โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”'; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $result = Multibyte::substr($string, 12, 24); $expected = 'โฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจ'; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $result = Multibyte::substr($string, 12, 24); $expected = '๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„'; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $result = Multibyte::substr($string, 12); $expected = '๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $result = Multibyte::substr($string, 24, 12); $expected = '๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”'; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $result = Multibyte::substr($string, 11, 2); $expected = '๏ฝŒ๏ฝ'; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $result = Multibyte::substr($string, 7, 11); $expected = '๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ'; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $result = Multibyte::substr($string, 13, 13); $expected = '๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’'; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $result = Multibyte::substr($string, 3, 4); $expected = 'ฤผล, '; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $result = Multibyte::substr($string, 3, 4); $expected = 'lo, '; $this->assertEquals($expected, $result); $string = 'ฤini'; $result = Multibyte::substr($string, 3); $expected = 'i'; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $result = Multibyte::substr($string, 1); $expected = 'oฤ‡i'; $this->assertEquals($expected, $result); $string = 'drลพavni'; $result = Multibyte::substr($string, 0, 2); $expected = 'dr'; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $result = Multibyte::substr($string, 3, 3); $expected = '่ฎพไธบ้ฆ–'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $result = Multibyte::substr($string, 0, 1); $expected = 'ไธ€'; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $result = Multibyte::substr($string, 6); $expected = false; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $result = Multibyte::substr($string, 0); $expected = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $this->assertEquals($expected, $result); } /** * testMultibyteSubstr method * * @return void */ public function testMultibyteMimeEncode() { $string = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $result = Multibyte::mimeEncode($string); $this->assertEquals($string, $result); $string = 'ร€รร‚รƒร„ร…ร†ร‡รˆร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร˜ร™รšร›รœรรž'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?w4DDgcOCw4PDhMOFw4bDh8OIw4nDisOLw4zDjcOOw4/DkMORw5LDk8OUw5U=?=' . "\r\n" . ' =?UTF-8?B?w5bDmMOZw5rDm8Ocw53Dng==?='; $this->assertEquals($expected, $result); $result = Multibyte::mimeEncode($string, null, "\n"); $expected = '=?UTF-8?B?w4DDgcOCw4PDhMOFw4bDh8OIw4nDisOLw4zDjcOOw4/DkMORw5LDk8OUw5U=?=' . "\n" . ' =?UTF-8?B?w5bDmMOZw5rDm8Ocw53Dng==?='; $this->assertEquals($expected, $result); $string = 'ฤ€ฤ‚ฤ„ฤ†ฤˆฤŠฤŒฤŽฤฤ’ฤ”ฤ–ฤ˜ฤšฤœฤžฤ ฤขฤคฤฆฤจฤชฤฌฤฎฤฒฤดฤถฤนฤปฤฝฤฟลลƒล…ล‡ลŠลŒลŽลล’ล”ล–ล˜ลšลœลžล ลขลคลฆลจลชลฌลฎลฐลฒลดลถลนลปลฝ'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?xIDEgsSExIbEiMSKxIzEjsSQxJLElMSWxJjEmsScxJ7EoMSixKTEpsSoxKo=?=' . "\r\n" . ' =?UTF-8?B?xKzErsSyxLTEtsS5xLvEvcS/xYHFg8WFxYfFisWMxY7FkMWSxZTFlsWYxZo=?=' . "\r\n" . ' =?UTF-8?B?xZzFnsWgxaLFpMWmxajFqsWsxa7FsMWyxbTFtsW5xbvFvQ==?='; $this->assertEquals($expected, $result); $string = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?ISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xN?=' . "\r\n" . ' =?UTF-8?B?Tk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6?=' . "\r\n" . ' =?UTF-8?B?e3x9fg==?='; $this->assertEquals($expected, $result); $string = 'ยกยขยฃยคยฅยฆยงยจยฉยชยซยฌยญยฎยฏยฐยฑยฒยณยดยตยถยทยธยนยบยปยผยฝยพยฟร€รร‚รƒร„ร…ร†ร‡รˆ'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?wqHCosKjwqTCpcKmwqfCqMKpwqrCq8Kswq3CrsKvwrDCscKywrPCtMK1wrY=?=' . "\r\n" . ' =?UTF-8?B?wrfCuMK5wrrCu8K8wr3CvsK/w4DDgcOCw4PDhMOFw4bDh8OI?='; $this->assertEquals($expected, $result); $string = 'ร‰รŠร‹รŒรรŽรรร‘ร’ร“ร”ร•ร–ร—ร˜ร™รšร›รœรรžรŸร รกรขรฃรครฅรฆรงรจรฉรชรซรฌรญรฎรฏรฐรฑรฒรณรดรตรถรทรธรนรบรปรผรฝรพรฟฤ€ฤฤ‚ฤƒฤ„ฤ…ฤ†ฤ‡ฤˆฤ‰ฤŠฤ‹ฤŒฤฤŽฤฤฤ‘ฤ’ฤ“ฤ”ฤ•ฤ–ฤ—ฤ˜ฤ™ฤšฤ›ฤœฤฤžฤŸฤ ฤกฤขฤฃฤคฤฅฤฆฤงฤจฤฉฤชฤซฤฌ'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?w4nDisOLw4zDjcOOw4/DkMORw5LDk8OUw5XDlsOXw5jDmcOaw5vDnMOdw54=?=' . "\r\n" . ' =?UTF-8?B?w5/DoMOhw6LDo8Okw6XDpsOnw6jDqcOqw6vDrMOtw67Dr8Oww7HDssOzw7Q=?=' . "\r\n" . ' =?UTF-8?B?w7XDtsO3w7jDucO6w7vDvMO9w77Dv8SAxIHEgsSDxITEhcSGxIfEiMSJxIo=?=' . "\r\n" . ' =?UTF-8?B?xIvEjMSNxI7Ej8SQxJHEksSTxJTElcSWxJfEmMSZxJrEm8ScxJ3EnsSfxKA=?=' . "\r\n" . ' =?UTF-8?B?xKHEosSjxKTEpcSmxKfEqMSpxKrEq8Ss?='; $this->assertEquals($expected, $result); $string = 'ฤญฤฎฤฏฤฐฤฑฤฒฤณฤดฤตฤถฤทฤธฤนฤบฤปฤผฤฝฤพฤฟล€ลล‚ลƒล„ล…ล†ล‡ลˆล‰ลŠล‹ลŒลลŽลลล‘ล’ล“ล”ล•ล–ล—ล˜ล™ลšล›ลœลลžลŸล ลกลขลฃลคลฅลฆลงลจลฉลชลซลฌลญลฎลฏลฐลฑลฒลณลดลตลถลทลธลนลบลปลผลฝลพลฟฦ€ฦฦ‚ฦƒฦ„ฦ…ฦ†ฦ‡ฦˆฦ‰ฦŠฦ‹ฦŒฦฦŽฦฦ'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?xK3ErsSvxLDEscSyxLPEtMS1xLbEt8S4xLnEusS7xLzEvcS+xL/FgMWBxYI=?=' . "\r\n" . ' =?UTF-8?B?xYPFhMWFxYbFh8WIxYnFisWLxYzFjcWOxY/FkMWRxZLFk8WUxZXFlsWXxZg=?=' . "\r\n" . ' =?UTF-8?B?xZnFmsWbxZzFncWexZ/FoMWhxaLFo8WkxaXFpsWnxajFqcWqxavFrMWtxa4=?=' . "\r\n" . ' =?UTF-8?B?xa/FsMWxxbLFs8W0xbXFtsW3xbjFucW6xbvFvMW9xb7Fv8aAxoHGgsaDxoQ=?=' . "\r\n" . ' =?UTF-8?B?xoXGhsaHxojGicaKxovGjMaNxo7Gj8aQ?='; $this->assertEquals($expected, $result); $string = 'ฦ‘ฦ’ฦ“ฦ”ฦ•ฦ–ฦ—ฦ˜ฦ™ฦšฦ›ฦœฦฦžฦŸฦ ฦกฦขฦฃฦคฦฅฦฆฦงฦจฦฉฦชฦซฦฌฦญฦฎฦฏฦฐฦฑฦฒฦณฦดฦตฦถฦทฦธฦนฦบฦปฦผฦฝฦพฦฟว€วว‚วƒว„ว…ว†ว‡วˆว‰วŠว‹วŒววŽววว‘ว’ว“ว”ว•ว–ว—ว˜ว™วšว›วœววžวŸว วกวขวฃวควฅวฆวงวจวฉวชวซวฌวญวฎวฏวฐวฑวฒวณวด'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?xpHGksaTxpTGlcaWxpfGmMaZxprGm8acxp3GnsafxqDGocaixqPGpMalxqY=?=' . "\r\n" . ' =?UTF-8?B?xqfGqMapxqrGq8asxq3GrsavxrDGscayxrPGtMa1xrbGt8a4xrnGusa7xrw=?=' . "\r\n" . ' =?UTF-8?B?xr3Gvsa/x4DHgceCx4PHhMeFx4bHh8eIx4nHiseLx4zHjceOx4/HkMeRx5I=?=' . "\r\n" . ' =?UTF-8?B?x5PHlMeVx5bHl8eYx5nHmsebx5zHnceex5/HoMehx6LHo8ekx6XHpsenx6g=?=' . "\r\n" . ' =?UTF-8?B?x6nHqserx6zHrceux6/HsMexx7LHs8e0?='; $this->assertEquals($expected, $result); $string = 'ษ™ษšษ›ษœษษžษŸษ ษกษขษฃษคษฅษฆษงษจษฉษชษซษฌษญษฎษฏษฐษฑษฒษณษดษตษถษทษธษนษบษปษผษฝษพษฟส€สส‚สƒส„ส…ส†ส‡สˆส‰สŠส‹สŒสสŽสสส‘ส’ส“ส”ส•ส–ส—ส˜ส™สšส›สœสสžสŸส สกสขสฃสคสฅสฆสงสจสฉสชสซสฌสญสฎสฏสฐสฑสฒสณสดสตสถสทสธสนสบสปสผ'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?yZnJmsmbyZzJncmeyZ/JoMmhyaLJo8mkyaXJpsmnyajJqcmqyavJrMmtya4=?=' . "\r\n" . ' =?UTF-8?B?ya/JsMmxybLJs8m0ybXJtsm3ybjJucm6ybvJvMm9yb7Jv8qAyoHKgsqDyoQ=?=' . "\r\n" . ' =?UTF-8?B?yoXKhsqHyojKicqKyovKjMqNyo7Kj8qQypHKksqTypTKlcqWypfKmMqZypo=?=' . "\r\n" . ' =?UTF-8?B?ypvKnMqdyp7Kn8qgyqHKosqjyqTKpcqmyqfKqMqpyqrKq8qsyq3KrsqvyrA=?=' . "\r\n" . ' =?UTF-8?B?yrHKssqzyrTKtcq2yrfKuMq5yrrKu8q8?='; $this->assertEquals($expected, $result); $string = 'ะ€ะะ‚ะƒะ„ะ…ะ†ะ‡ะˆะ‰ะŠะ‹ะŒะะŽะะะ‘ะ’ะ“ะ”ะ•ะ–ะ—ะ˜ะ™ะšะ›'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?0IDQgdCC0IPQhNCF0IbQh9CI0InQitCL0IzQjdCO0I/QkNCR0JLQk9CU0JU=?=' . "\r\n" . ' =?UTF-8?B?0JbQl9CY0JnQmtCb?='; $this->assertEquals($expected, $result); $string = 'ะœะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?0JzQndCe0J/QoNCh0KLQo9Ck0KXQptCn0KjQqdCq0KvQrNCt0K7Qr9Cw0LE=?=' . "\r\n" . ' =?UTF-8?B?0LLQs9C00LXQttC30LjQudC60LvQvNC90L7Qv9GA0YHRgtGD0YTRhdGG0Yc=?=' . "\r\n" . ' =?UTF-8?B?0YjRidGK0YvRjA==?='; $this->assertEquals($expected, $result); $string = 'ูู‚ูƒู„ู…ู†ู‡ูˆู‰ูŠู‹ูŒููŽู'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?2YHZgtmD2YTZhdmG2YfZiNmJ2YrZi9mM2Y3ZjtmP?='; $this->assertEquals($expected, $result); $string = 'โœฐโœฑโœฒโœณโœดโœตโœถโœทโœธโœนโœบโœปโœผโœฝโœพโœฟโ€โโ‚โƒโ„โ…โ†โ‡โˆโ‰โŠโ‹โŒโโŽโโโ‘โ’โ“โ”โ•โ–โ—โ˜โ™โšโ›โœโโž'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?4pyw4pyx4pyy4pyz4py04py14py24py34py44py54py64py74py84py94py+?=' . "\r\n" . ' =?UTF-8?B?4py/4p2A4p2B4p2C4p2D4p2E4p2F4p2G4p2H4p2I4p2J4p2K4p2L4p2M4p2N?=' . "\r\n" . ' =?UTF-8?B?4p2O4p2P4p2Q4p2R4p2S4p2T4p2U4p2V4p2W4p2X4p2Y4p2Z4p2a4p2b4p2c?=' . "\r\n" . ' =?UTF-8?B?4p2d4p2e?='; $this->assertEquals($expected, $result); $string = 'โบ€โบโบ‚โบƒโบ„โบ…โบ†โบ‡โบˆโบ‰โบŠโบ‹โบŒโบโบŽโบโบโบ‘โบ’โบ“โบ”โบ•โบ–โบ—โบ˜โบ™โบ›โบœโบโบžโบŸโบ โบกโบขโบฃโบคโบฅโบฆโบงโบจโบฉโบชโบซโบฌโบญโบฎโบฏโบฐโบฑโบฒโบณโบดโบตโบถโบทโบธโบนโบบโบปโบผโบฝโบพโบฟโป€โปโป‚โปƒโป„โป…โป†โป‡โปˆโป‰โปŠโป‹โปŒโปโปŽโปโปโป‘โป’โป“โป”โป•โป–โป—โป˜โป™โปšโป›โปœโปโปžโปŸโป '; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?4rqA4rqB4rqC4rqD4rqE4rqF4rqG4rqH4rqI4rqJ4rqK4rqL4rqM4rqN4rqO?=' . "\r\n" . ' =?UTF-8?B?4rqP4rqQ4rqR4rqS4rqT4rqU4rqV4rqW4rqX4rqY4rqZ4rqb4rqc4rqd4rqe?=' . "\r\n" . ' =?UTF-8?B?4rqf4rqg4rqh4rqi4rqj4rqk4rql4rqm4rqn4rqo4rqp4rqq4rqr4rqs4rqt?=' . "\r\n" . ' =?UTF-8?B?4rqu4rqv4rqw4rqx4rqy4rqz4rq04rq14rq24rq34rq44rq54rq64rq74rq8?=' . "\r\n" . ' =?UTF-8?B?4rq94rq+4rq/4ruA4ruB4ruC4ruD4ruE4ruF4ruG4ruH4ruI4ruJ4ruK4ruL?=' . "\r\n" . ' =?UTF-8?B?4ruM4ruN4ruO4ruP4ruQ4ruR4ruS4ruT4ruU4ruV4ruW4ruX4ruY4ruZ4rua?=' . "\r\n" . ' =?UTF-8?B?4rub4ruc4rud4rue4ruf4rug?='; $this->assertEquals($expected, $result); $string = 'โฝ…โฝ†โฝ‡โฝˆโฝ‰โฝŠโฝ‹โฝŒโฝโฝŽโฝโฝโฝ‘โฝ’โฝ“โฝ”โฝ•โฝ–โฝ—โฝ˜โฝ™โฝšโฝ›โฝœโฝโฝžโฝŸโฝ โฝกโฝขโฝฃโฝคโฝฅโฝฆโฝงโฝจโฝฉโฝชโฝซโฝฌโฝญโฝฎโฝฏโฝฐโฝฑโฝฒโฝณโฝดโฝตโฝถโฝทโฝธโฝนโฝบโฝปโฝผโฝฝโฝพโฝฟ'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?4r2F4r2G4r2H4r2I4r2J4r2K4r2L4r2M4r2N4r2O4r2P4r2Q4r2R4r2S4r2T?=' . "\r\n" . ' =?UTF-8?B?4r2U4r2V4r2W4r2X4r2Y4r2Z4r2a4r2b4r2c4r2d4r2e4r2f4r2g4r2h4r2i?=' . "\r\n" . ' =?UTF-8?B?4r2j4r2k4r2l4r2m4r2n4r2o4r2p4r2q4r2r4r2s4r2t4r2u4r2v4r2w4r2x?=' . "\r\n" . ' =?UTF-8?B?4r2y4r2z4r204r214r224r234r244r254r264r274r284r294r2+4r2/?='; $this->assertEquals($expected, $result); $string = '๋ˆก๋ˆข๋ˆฃ๋ˆค๋ˆฅ๋ˆฆ๋ˆง๋ˆจ๋ˆฉ๋ˆช๋ˆซ๋ˆฌ๋ˆญ๋ˆฎ๋ˆฏ๋ˆฐ๋ˆฑ๋ˆฒ๋ˆณ๋ˆด๋ˆต๋ˆถ๋ˆท๋ˆธ๋ˆน๋ˆบ๋ˆป๋ˆผ๋ˆฝ๋ˆพ๋ˆฟ๋‰€๋‰๋‰‚๋‰ƒ๋‰„๋‰…๋‰†๋‰‡๋‰ˆ๋‰‰๋‰Š๋‰‹๋‰Œ๋‰๋‰Ž๋‰๋‰๋‰‘๋‰’๋‰“๋‰”๋‰•๋‰–๋‰—๋‰˜๋‰™๋‰š๋‰›๋‰œ๋‰๋‰ž๋‰Ÿ๋‰ ๋‰ก๋‰ข๋‰ฃ๋‰ค๋‰ฅ๋‰ฆ๋‰ง๋‰จ๋‰ฉ๋‰ช๋‰ซ๋‰ฌ๋‰ญ๋‰ฎ๋‰ฏ๋‰ฐ๋‰ฑ๋‰ฒ๋‰ณ๋‰ด๋‰ต๋‰ถ๋‰ท๋‰ธ๋‰น๋‰บ๋‰ป๋‰ผ๋‰ฝ๋‰พ๋‰ฟ๋Š€๋Ё๋Š‚๋Šƒ๋Š„'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?64ih64ii64ij64ik64il64im64in64io64ip64iq64ir64is64it64iu64iv?=' . "\r\n" . ' =?UTF-8?B?64iw64ix64iy64iz64i064i164i264i364i464i564i664i764i864i964i+?=' . "\r\n" . ' =?UTF-8?B?64i/64mA64mB64mC64mD64mE64mF64mG64mH64mI64mJ64mK64mL64mM64mN?=' . "\r\n" . ' =?UTF-8?B?64mO64mP64mQ64mR64mS64mT64mU64mV64mW64mX64mY64mZ64ma64mb64mc?=' . "\r\n" . ' =?UTF-8?B?64md64me64mf64mg64mh64mi64mj64mk64ml64mm64mn64mo64mp64mq64mr?=' . "\r\n" . ' =?UTF-8?B?64ms64mt64mu64mv64mw64mx64my64mz64m064m164m264m364m464m564m6?=' . "\r\n" . ' =?UTF-8?B?64m764m864m964m+64m/64qA64qB64qC64qD64qE?='; $this->assertEquals($expected, $result); $string = '๏นฐ๏นฑ๏นฒ๏นณ๏นด๏นต๏นถ๏นท๏นธ๏นน๏นบ๏นป๏นผ๏นฝ๏นพ๏นฟ๏บ€๏บ๏บ‚๏บƒ๏บ„๏บ…๏บ†๏บ‡๏บˆ๏บ‰๏บŠ๏บ‹๏บŒ๏บ๏บŽ๏บ๏บ๏บ‘๏บ’๏บ“๏บ”๏บ•๏บ–๏บ—๏บ˜๏บ™๏บš๏บ›๏บœ๏บ๏บž๏บŸ๏บ ๏บก๏บข๏บฃ๏บค๏บฅ๏บฆ๏บง๏บจ๏บฉ๏บช๏บซ๏บฌ๏บญ๏บฎ๏บฏ๏บฐ'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?77mw77mx77my77mz77m077m177m277m377m477m577m677m777m877m977m+?=' . "\r\n" . ' =?UTF-8?B?77m/77qA77qB77qC77qD77qE77qF77qG77qH77qI77qJ77qK77qL77qM77qN?=' . "\r\n" . ' =?UTF-8?B?77qO77qP77qQ77qR77qS77qT77qU77qV77qW77qX77qY77qZ77qa77qb77qc?=' . "\r\n" . ' =?UTF-8?B?77qd77qe77qf77qg77qh77qi77qj77qk77ql77qm77qn77qo77qp77qq77qr?=' . "\r\n" . ' =?UTF-8?B?77qs77qt77qu77qv77qw?='; $this->assertEquals($expected, $result); $string = '๏บฑ๏บฒ๏บณ๏บด๏บต๏บถ๏บท๏บธ๏บน๏บบ๏บป๏บผ๏บฝ๏บพ๏บฟ๏ป€๏ป๏ป‚๏ปƒ๏ป„๏ป…๏ป†๏ป‡๏ปˆ๏ป‰๏ปŠ๏ป‹๏ปŒ๏ป๏ปŽ๏ป๏ป๏ป‘๏ป’๏ป“๏ป”๏ป•๏ป–๏ป—๏ป˜๏ป™๏ปš๏ป›๏ปœ๏ป๏ปž๏ปŸ๏ป ๏ปก๏ปข๏ปฃ๏ปค๏ปฅ๏ปฆ๏ปง๏ปจ๏ปฉ๏ปช๏ปซ๏ปฌ๏ปญ๏ปฎ๏ปฏ๏ปฐ๏ปฑ๏ปฒ๏ปณ๏ปด๏ปต๏ปถ๏ปท๏ปธ๏ปน๏ปบ๏ปป๏ปผ'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?77qx77qy77qz77q077q177q277q377q477q577q677q777q877q977q+77q/?=' . "\r\n" . ' =?UTF-8?B?77uA77uB77uC77uD77uE77uF77uG77uH77uI77uJ77uK77uL77uM77uN77uO?=' . "\r\n" . ' =?UTF-8?B?77uP77uQ77uR77uS77uT77uU77uV77uW77uX77uY77uZ77ua77ub77uc77ud?=' . "\r\n" . ' =?UTF-8?B?77ue77uf77ug77uh77ui77uj77uk77ul77um77un77uo77up77uq77ur77us?=' . "\r\n" . ' =?UTF-8?B?77ut77uu77uv77uw77ux77uy77uz77u077u177u277u377u477u577u677u7?=' . "\r\n" . ' =?UTF-8?B?77u8?='; $this->assertEquals($expected, $result); $string = '๏ฝ๏ฝ‚๏ฝƒ๏ฝ„๏ฝ…๏ฝ†๏ฝ‡๏ฝˆ๏ฝ‰๏ฝŠ๏ฝ‹๏ฝŒ๏ฝ๏ฝŽ๏ฝ๏ฝ๏ฝ‘๏ฝ’๏ฝ“๏ฝ”๏ฝ•๏ฝ–๏ฝ—๏ฝ˜๏ฝ™๏ฝš'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?772B772C772D772E772F772G772H772I772J772K772L772M772N772O772P?=' . "\r\n" . ' =?UTF-8?B?772Q772R772S772T772U772V772W772X772Y772Z772a?='; $this->assertEquals($expected, $result); $string = '๏ฝก๏ฝข๏ฝฃ๏ฝค๏ฝฅ๏ฝฆ๏ฝง๏ฝจ๏ฝฉ๏ฝช๏ฝซ๏ฝฌ๏ฝญ๏ฝฎ๏ฝฏ๏ฝฐ๏ฝฑ๏ฝฒ๏ฝณ๏ฝด๏ฝต๏ฝถ๏ฝท๏ฝธ'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?772h772i772j772k772l772m772n772o772p772q772r772s772t772u772v?=' . "\r\n" . ' =?UTF-8?B?772w772x772y772z77207721772277237724?='; $this->assertEquals($expected, $result); $string = '๏ฝน๏ฝบ๏ฝป๏ฝผ๏ฝฝ๏ฝพ๏ฝฟ๏พ€๏พ๏พ‚๏พƒ๏พ„๏พ…๏พ†๏พ‡๏พˆ๏พ‰๏พŠ๏พ‹๏พŒ๏พ๏พŽ๏พ๏พ๏พ‘๏พ’๏พ“๏พ”๏พ•๏พ–๏พ—๏พ˜๏พ™๏พš๏พ›๏พœ๏พ๏พž'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?77257726772777287729772+772/776A776B776C776D776E776F776G776H?=' . "\r\n" . ' =?UTF-8?B?776I776J776K776L776M776N776O776P776Q776R776S776T776U776V776W?=' . "\r\n" . ' =?UTF-8?B?776X776Y776Z776a776b776c776d776e?='; $this->assertEquals($expected, $result); $string = 'ฤคฤ“ฤบฤผล, ลดล‘ล™ฤผฤ!'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?xKTEk8S6xLzFjywgxbTFkcWZxLzEjyE=?='; $this->assertEquals($expected, $result); $string = 'Hello, World!'; $result = Multibyte::mimeEncode($string); $this->assertEquals($string, $result); $string = 'ฤini'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?xI1pbmk=?='; $this->assertEquals($expected, $result); $string = 'moฤ‡i'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?bW/Eh2k=?='; $this->assertEquals($expected, $result); $string = 'drลพavni'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?ZHLFvmF2bmk=?='; $this->assertEquals($expected, $result); $string = 'ๆŠŠ็™พๅบฆ่ฎพไธบ้ฆ–้กต'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?5oqK55m+5bqm6K6+5Li66aaW6aG1?='; $this->assertEquals($expected, $result); $string = 'ไธ€ไบŒไธ‰ๅ‘จๆฐธ้พ'; $result = Multibyte::mimeEncode($string); $expected = '=?UTF-8?B?5LiA5LqM5LiJ5ZGo5rC46b6N?='; $this->assertEquals($expected, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Log/000077500000000000000000000000001265552240500170665ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Log/CakeLogTest.php000066400000000000000000000477711265552240500217640ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Log * @since CakePHP(tm) v 1.2.0.5432 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('CakeLog', 'Log'); App::uses('FileLog', 'Log/Engine'); /** * CakeLogTest class * * @package Cake.Test.Case.Log */ class CakeLogTest extends CakeTestCase { /** * Start test callback, clears all streams enabled. * * @return void */ public function setUp() { parent::setUp(); $streams = CakeLog::configured(); foreach ($streams as $stream) { CakeLog::drop($stream); } } /** * test importing loggers from app/libs and plugins. * * @return void */ public function testImportingLoggers() { App::build(array( 'Lib' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Lib' . DS), 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); $result = CakeLog::config('libtest', array( 'engine' => 'TestAppLog' )); $this->assertTrue($result); $this->assertEquals(CakeLog::configured(), array('libtest')); $result = CakeLog::config('plugintest', array( 'engine' => 'TestPlugin.TestPluginLog' )); $this->assertTrue($result); $this->assertEquals(CakeLog::configured(), array('libtest', 'plugintest')); CakeLog::write(LOG_INFO, 'TestPluginLog is not a BaseLog descendant'); App::build(); CakePlugin::unload(); } /** * test all the errors from failed logger imports * * @expectedException CakeLogException * @return void */ public function testImportingLoggerFailure() { CakeLog::config('fail', array()); } /** * test config() with valid key name * * @return void */ public function testValidKeyName() { CakeLog::config('valid', array('engine' => 'File')); $stream = CakeLog::stream('valid'); $this->assertInstanceOf('FileLog', $stream); CakeLog::drop('valid'); } /** * test config() with valid key name including the deprecated Log suffix * * @return void */ public function testValidKeyNameLogSuffix() { CakeLog::config('valid', array('engine' => 'FileLog')); $stream = CakeLog::stream('valid'); $this->assertInstanceOf('FileLog', $stream); CakeLog::drop('valid'); } /** * test config() with invalid key name * * @expectedException CakeLogException * @return void */ public function testInvalidKeyName() { CakeLog::config('1nv', array('engine' => 'File')); } /** * test that loggers have to implement the correct interface. * * @expectedException CakeLogException * @return void */ public function testNotImplementingInterface() { CakeLog::config('fail', array('engine' => 'stdClass')); } /** * Test that CakeLog does not auto create logs when no streams are there to listen. * * @return void */ public function testNoStreamListenting() { if (file_exists(LOGS . 'error.log')) { unlink(LOGS . 'error.log'); } $res = CakeLog::write(LOG_WARNING, 'Test warning'); $this->assertFalse($res); $this->assertFalse(file_exists(LOGS . 'error.log')); $result = CakeLog::configured(); $this->assertEquals(array(), $result); } /** * test configuring log streams * * @return void */ public function testConfig() { CakeLog::config('file', array( 'engine' => 'File', 'path' => LOGS )); $result = CakeLog::configured(); $this->assertEquals(array('file'), $result); if (file_exists(LOGS . 'error.log')) { unlink(LOGS . 'error.log'); } CakeLog::write(LOG_WARNING, 'Test warning'); $this->assertTrue(file_exists(LOGS . 'error.log')); $result = file_get_contents(LOGS . 'error.log'); $this->assertRegExp('/^2[0-9]{3}-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+ Warning: Test warning/', $result); unlink(LOGS . 'error.log'); } /** * explicit tests for drop() * * @return void */ public function testDrop() { CakeLog::config('file', array( 'engine' => 'File', 'path' => LOGS )); $result = CakeLog::configured(); $this->assertEquals(array('file'), $result); CakeLog::drop('file'); $result = CakeLog::configured(); $this->assertSame(array(), $result); } /** * testLogFileWriting method * * @return void */ public function testLogFileWriting() { CakeLog::config('file', array( 'engine' => 'File', 'path' => LOGS )); if (file_exists(LOGS . 'error.log')) { unlink(LOGS . 'error.log'); } $result = CakeLog::write(LOG_WARNING, 'Test warning'); $this->assertTrue($result); $this->assertTrue(file_exists(LOGS . 'error.log')); unlink(LOGS . 'error.log'); CakeLog::write(LOG_WARNING, 'Test warning 1'); CakeLog::write(LOG_WARNING, 'Test warning 2'); $result = file_get_contents(LOGS . 'error.log'); $this->assertRegExp('/^2[0-9]{3}-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+ Warning: Test warning 1/', $result); $this->assertRegExp('/2[0-9]{3}-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+ Warning: Test warning 2$/', $result); unlink(LOGS . 'error.log'); } /** * test selective logging by level/type * * @return void */ public function testSelectiveLoggingByLevel() { if (file_exists(LOGS . 'spam.log')) { unlink(LOGS . 'spam.log'); } if (file_exists(LOGS . 'eggs.log')) { unlink(LOGS . 'eggs.log'); } CakeLog::config('spam', array( 'engine' => 'File', 'types' => 'debug', 'file' => 'spam', )); CakeLog::config('eggs', array( 'engine' => 'File', 'types' => array('eggs', 'debug', 'error', 'warning'), 'file' => 'eggs', )); $testMessage = 'selective logging'; CakeLog::write(LOG_WARNING, $testMessage); $this->assertTrue(file_exists(LOGS . 'eggs.log')); $this->assertFalse(file_exists(LOGS . 'spam.log')); CakeLog::write(LOG_DEBUG, $testMessage); $this->assertTrue(file_exists(LOGS . 'spam.log')); $contents = file_get_contents(LOGS . 'spam.log'); $this->assertContains('Debug: ' . $testMessage, $contents); $contents = file_get_contents(LOGS . 'eggs.log'); $this->assertContains('Debug: ' . $testMessage, $contents); if (file_exists(LOGS . 'spam.log')) { unlink(LOGS . 'spam.log'); } if (file_exists(LOGS . 'eggs.log')) { unlink(LOGS . 'eggs.log'); } } /** * test enable * * @expectedException CakeLogException * @return void */ public function testStreamEnable() { CakeLog::config('spam', array( 'engine' => 'File', 'file' => 'spam', )); $this->assertTrue(CakeLog::enabled('spam')); CakeLog::drop('spam'); CakeLog::enable('bogus_stream'); } /** * test disable * * @expectedException CakeLogException * @return void */ public function testStreamDisable() { CakeLog::config('spam', array( 'engine' => 'File', 'file' => 'spam', )); $this->assertTrue(CakeLog::enabled('spam')); CakeLog::disable('spam'); $this->assertFalse(CakeLog::enabled('spam')); CakeLog::drop('spam'); CakeLog::enable('bogus_stream'); } /** * test enabled() invalid stream * * @expectedException CakeLogException * @return void */ public function testStreamEnabledInvalid() { CakeLog::enabled('bogus_stream'); } /** * test disable invalid stream * * @expectedException CakeLogException * @return void */ public function testStreamDisableInvalid() { CakeLog::disable('bogus_stream'); } /** * resets log config * * @return void */ protected function _resetLogConfig() { CakeLog::config('debug', array( 'engine' => 'File', 'types' => array('notice', 'info', 'debug'), 'file' => 'debug', )); CakeLog::config('error', array( 'engine' => 'File', 'types' => array('warning', 'error', 'critical', 'alert', 'emergency'), 'file' => 'error', )); } /** * delete logs * * @return void */ protected function _deleteLogs() { if (file_exists(LOGS . 'shops.log')) { unlink(LOGS . 'shops.log'); } if (file_exists(LOGS . 'error.log')) { unlink(LOGS . 'error.log'); } if (file_exists(LOGS . 'debug.log')) { unlink(LOGS . 'debug.log'); } if (file_exists(LOGS . 'bogus.log')) { unlink(LOGS . 'bogus.log'); } if (file_exists(LOGS . 'spam.log')) { unlink(LOGS . 'spam.log'); } if (file_exists(LOGS . 'eggs.log')) { unlink(LOGS . 'eggs.log'); } } /** * test backward compatible scoped logging * * @return void */ public function testScopedLoggingBC() { $this->_resetLogConfig(); CakeLog::config('shops', array( 'engine' => 'File', 'types' => array('info', 'notice', 'warning'), 'scopes' => array('transactions', 'orders'), 'file' => 'shops', )); $this->_deleteLogs(); CakeLog::write('info', 'info message'); $this->assertFalse(file_exists(LOGS . 'error.log')); $this->assertTrue(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); CakeLog::write('transactions', 'transaction message'); $this->assertTrue(file_exists(LOGS . 'shops.log')); $this->assertFalse(file_exists(LOGS . 'transactions.log')); $this->assertFalse(file_exists(LOGS . 'error.log')); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); CakeLog::write('error', 'error message'); $this->assertTrue(file_exists(LOGS . 'error.log')); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->assertFalse(file_exists(LOGS . 'shops.log')); $this->_deleteLogs(); CakeLog::write('orders', 'order message'); $this->assertFalse(file_exists(LOGS . 'error.log')); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->assertFalse(file_exists(LOGS . 'orders.log')); $this->assertTrue(file_exists(LOGS . 'shops.log')); $this->_deleteLogs(); CakeLog::write('warning', 'warning message'); $this->assertTrue(file_exists(LOGS . 'error.log')); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); CakeLog::drop('shops'); } /** * Test that scopes are exclusive and don't bleed. * * @return void */ public function testScopedLoggingExclusive() { $this->_deleteLogs(); CakeLog::config('shops', array( 'engine' => 'File', 'types' => array('info', 'notice', 'warning'), 'scopes' => array('transactions', 'orders'), 'file' => 'shops.log', )); CakeLog::config('eggs', array( 'engine' => 'File', 'types' => array('info', 'notice', 'warning'), 'scopes' => array('eggs'), 'file' => 'eggs.log', )); CakeLog::write('info', 'transactions message', 'transactions'); $this->assertFalse(file_exists(LOGS . 'eggs.log')); $this->assertTrue(file_exists(LOGS . 'shops.log')); $this->_deleteLogs(); CakeLog::write('info', 'eggs message', 'eggs'); $this->assertTrue(file_exists(LOGS . 'eggs.log')); $this->assertFalse(file_exists(LOGS . 'shops.log')); } /** * test scoped logging * * @return void */ public function testScopedLogging() { $this->_resetLogConfig(); $this->_deleteLogs(); CakeLog::config('string-scope', array( 'engine' => 'File', 'types' => array('info', 'notice', 'warning'), 'scopes' => 'string-scope', 'file' => 'string-scope.log' )); CakeLog::write('info', 'info message', 'string-scope'); $this->assertTrue(file_exists(LOGS . 'string-scope.log')); CakeLog::drop('string-scope'); CakeLog::config('shops', array( 'engine' => 'File', 'types' => array('info', 'notice', 'warning'), 'scopes' => array('transactions', 'orders'), 'file' => 'shops.log', )); CakeLog::write('info', 'info message', 'transactions'); $this->assertFalse(file_exists(LOGS . 'error.log')); $this->assertTrue(file_exists(LOGS . 'shops.log')); $this->assertTrue(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); CakeLog::write('transactions', 'transaction message', 'orders'); $this->assertTrue(file_exists(LOGS . 'shops.log')); $this->assertFalse(file_exists(LOGS . 'transactions.log')); $this->assertFalse(file_exists(LOGS . 'error.log')); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); CakeLog::write('error', 'error message', 'orders'); $this->assertTrue(file_exists(LOGS . 'error.log')); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->assertFalse(file_exists(LOGS . 'shops.log')); $this->_deleteLogs(); CakeLog::write('orders', 'order message', 'transactions'); $this->assertFalse(file_exists(LOGS . 'error.log')); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->assertFalse(file_exists(LOGS . 'orders.log')); $this->assertTrue(file_exists(LOGS . 'shops.log')); $this->_deleteLogs(); CakeLog::write('warning', 'warning message', 'orders'); $this->assertTrue(file_exists(LOGS . 'error.log')); $this->assertTrue(file_exists(LOGS . 'shops.log')); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); CakeLog::drop('shops'); } /** * test bogus type and scope * * @return void */ public function testBogusTypeAndScope() { $this->_resetLogConfig(); $this->_deleteLogs(); CakeLog::config('file', array( 'engine' => 'File', 'path' => LOGS )); CakeLog::write('bogus', 'bogus message'); $this->assertTrue(file_exists(LOGS . 'bogus.log')); $this->assertFalse(file_exists(LOGS . 'error.log')); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); CakeLog::write('bogus', 'bogus message', 'bogus'); $this->assertTrue(file_exists(LOGS . 'bogus.log')); $this->assertFalse(file_exists(LOGS . 'error.log')); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); CakeLog::write('error', 'bogus message', 'bogus'); $this->assertFalse(file_exists(LOGS . 'bogus.log')); $this->assertTrue(file_exists(LOGS . 'error.log')); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); } /** * test scoped logging with convenience methods * * @return void */ public function testConvenienceScopedLogging() { if (file_exists(LOGS . 'shops.log')) { unlink(LOGS . 'shops.log'); } if (file_exists(LOGS . 'error.log')) { unlink(LOGS . 'error.log'); } if (file_exists(LOGS . 'debug.log')) { unlink(LOGS . 'debug.log'); } $this->_resetLogConfig(); CakeLog::config('shops', array( 'engine' => 'File', 'types' => array('info', 'debug', 'notice', 'warning'), 'scopes' => array('transactions', 'orders'), 'file' => 'shops', )); CakeLog::info('info message', 'transactions'); $this->assertFalse(file_exists(LOGS . 'error.log')); $this->assertTrue(file_exists(LOGS . 'shops.log')); $this->assertTrue(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); CakeLog::error('error message', 'orders'); $this->assertTrue(file_exists(LOGS . 'error.log')); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->assertFalse(file_exists(LOGS . 'shops.log')); $this->_deleteLogs(); CakeLog::warning('warning message', 'orders'); $this->assertTrue(file_exists(LOGS . 'error.log')); $this->assertTrue(file_exists(LOGS . 'shops.log')); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); CakeLog::drop('shops'); } /** * test convenience methods * * @return void */ public function testConvenienceMethods() { $this->_deleteLogs(); CakeLog::config('debug', array( 'engine' => 'File', 'types' => array('notice', 'info', 'debug'), 'file' => 'debug', )); CakeLog::config('error', array( 'engine' => 'File', 'types' => array('emergency', 'alert', 'critical', 'error', 'warning'), 'file' => 'error', )); $testMessage = 'emergency message'; CakeLog::emergency($testMessage); $contents = file_get_contents(LOGS . 'error.log'); $this->assertRegExp('/(Emergency|Critical): ' . $testMessage . '/', $contents); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); $testMessage = 'alert message'; CakeLog::alert($testMessage); $contents = file_get_contents(LOGS . 'error.log'); $this->assertRegExp('/(Alert|Critical): ' . $testMessage . '/', $contents); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); $testMessage = 'critical message'; CakeLog::critical($testMessage); $contents = file_get_contents(LOGS . 'error.log'); $this->assertContains('Critical: ' . $testMessage, $contents); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); $testMessage = 'error message'; CakeLog::error($testMessage); $contents = file_get_contents(LOGS . 'error.log'); $this->assertContains('Error: ' . $testMessage, $contents); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); $testMessage = 'warning message'; CakeLog::warning($testMessage); $contents = file_get_contents(LOGS . 'error.log'); $this->assertContains('Warning: ' . $testMessage, $contents); $this->assertFalse(file_exists(LOGS . 'debug.log')); $this->_deleteLogs(); $testMessage = 'notice message'; CakeLog::notice($testMessage); $contents = file_get_contents(LOGS . 'debug.log'); $this->assertRegExp('/(Notice|Debug): ' . $testMessage . '/', $contents); $this->assertFalse(file_exists(LOGS . 'error.log')); $this->_deleteLogs(); $testMessage = 'info message'; CakeLog::info($testMessage); $contents = file_get_contents(LOGS . 'debug.log'); $this->assertRegExp('/(Info|Debug): ' . $testMessage . '/', $contents); $this->assertFalse(file_exists(LOGS . 'error.log')); $this->_deleteLogs(); $testMessage = 'debug message'; CakeLog::debug($testMessage); $contents = file_get_contents(LOGS . 'debug.log'); $this->assertContains('Debug: ' . $testMessage, $contents); $this->assertFalse(file_exists(LOGS . 'error.log')); $this->_deleteLogs(); } /** * test levels customization * * @return void */ public function testLevelCustomization() { $this->skipIf(DIRECTORY_SEPARATOR === '\\', 'Log level tests not supported on Windows.'); $levels = CakeLog::defaultLevels(); $this->assertNotEmpty($levels); $result = array_keys($levels); $this->assertEquals(array(0, 1, 2, 3, 4, 5, 6, 7), $result); $levels = CakeLog::levels(array('foo', 'bar')); CakeLog::defaultLevels(); $this->assertEquals('foo', $levels[8]); $this->assertEquals('bar', $levels[9]); $levels = CakeLog::levels(array(11 => 'spam', 'bar' => 'eggs')); CakeLog::defaultLevels(); $this->assertEquals('spam', $levels[8]); $this->assertEquals('eggs', $levels[9]); $levels = CakeLog::levels(array(11 => 'spam', 'bar' => 'eggs'), false); CakeLog::defaultLevels(); $this->assertEquals(array('spam', 'eggs'), $levels); $levels = CakeLog::levels(array('ham', 9 => 'spam', '12' => 'fam'), false); CakeLog::defaultLevels(); $this->assertEquals(array('ham', 'spam', 'fam'), $levels); } /** * Test writing log files with custom levels * * @return void */ public function testCustomLevelWrites() { $this->_deleteLogs(); $this->_resetLogConfig(); CakeLog::levels(array('spam', 'eggs')); $testMessage = 'error message'; CakeLog::write('error', $testMessage); CakeLog::defaultLevels(); $this->assertTrue(file_exists(LOGS . 'error.log')); $contents = file_get_contents(LOGS . 'error.log'); $this->assertContains('Error: ' . $testMessage, $contents); CakeLog::config('spam', array( 'engine' => 'File', 'file' => 'spam.log', 'types' => 'spam', )); CakeLog::config('eggs', array( 'engine' => 'File', 'file' => 'eggs.log', 'types' => array('spam', 'eggs'), )); $testMessage = 'spam message'; CakeLog::write('spam', $testMessage); CakeLog::defaultLevels(); $this->assertTrue(file_exists(LOGS . 'spam.log')); $this->assertTrue(file_exists(LOGS . 'eggs.log')); $contents = file_get_contents(LOGS . 'spam.log'); $this->assertContains('Spam: ' . $testMessage, $contents); $testMessage = 'egg message'; CakeLog::write('eggs', $testMessage); CakeLog::defaultLevels(); $contents = file_get_contents(LOGS . 'spam.log'); $this->assertNotContains('Eggs: ' . $testMessage, $contents); $contents = file_get_contents(LOGS . 'eggs.log'); $this->assertContains('Eggs: ' . $testMessage, $contents); CakeLog::drop('spam'); CakeLog::drop('eggs'); $this->_deleteLogs(); } } cakephp-2.8.0/lib/Cake/Test/Case/Log/Engine/000077500000000000000000000000001265552240500202735ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Log/Engine/ConsoleLogTest.php000066400000000000000000000100151265552240500237050ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Log.Engine * @since CakePHP(tm) v 1.3 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('ConsoleLog', 'Log/Engine'); /** * Class TestConsoleLog * * @package Cake.Test.Case.Log.Engine */ class TestConsoleLog extends ConsoleLog { } /** * Class TestCakeLog * * @package Cake.Test.Case.Log.Engine */ class TestCakeLog extends CakeLog { public static function replace($key, &$engine) { static::$_Collection->{$key} = $engine; } } /** * ConsoleLogTest class * * @package Cake.Test.Case.Log.Engine */ class ConsoleLogTest extends CakeTestCase { public function setUp() { parent::setUp(); CakeLog::config('debug', array( 'engine' => 'File', 'types' => array('notice', 'info', 'debug'), 'file' => 'debug', )); CakeLog::config('error', array( 'engine' => 'File', 'types' => array('error', 'warning'), 'file' => 'error', )); } public function tearDown() { parent::tearDown(); if (file_exists(LOGS . 'error.log')) { unlink(LOGS . 'error.log'); } if (file_exists(LOGS . 'debug.log')) { unlink(LOGS . 'debug.log'); } } /** * Test writing to ConsoleOutput * * @return void */ public function testConsoleOutputWrites() { TestCakeLog::config('test_console_log', array( 'engine' => 'TestConsole', )); $mock = $this->getMock('TestConsoleLog', array('write'), array( array('types' => 'error'), )); TestCakeLog::replace('test_console_log', $mock); $message = 'Test error message'; $mock->expects($this->once()) ->method('write'); TestCakeLog::write(LOG_ERR, $message); } /** * Test logging to both ConsoleLog and FileLog * * @return void */ public function testCombinedLogWriting() { TestCakeLog::config('test_console_log', array( 'engine' => 'TestConsole', )); $mock = $this->getMock('TestConsoleLog', array('write'), array( array('types' => 'error'), )); TestCakeLog::replace('test_console_log', $mock); // log to both file and console $message = 'Test error message'; $mock->expects($this->once()) ->method('write'); TestCakeLog::write(LOG_ERR, $message); $this->assertTrue(file_exists(LOGS . 'error.log'), 'error.log missing'); $logOutput = file_get_contents(LOGS . 'error.log'); $this->assertContains($message, $logOutput); // TestConsoleLog is only interested in `error` type $message = 'Test info message'; $mock->expects($this->never()) ->method('write'); TestCakeLog::write(LOG_INFO, $message); // checks that output is correctly written in the correct logfile $this->assertTrue(file_exists(LOGS . 'error.log'), 'error.log missing'); $this->assertTrue(file_exists(LOGS . 'debug.log'), 'debug.log missing'); $logOutput = file_get_contents(LOGS . 'error.log'); $this->assertNotContains($message, $logOutput); $logOutput = file_get_contents(LOGS . 'debug.log'); $this->assertContains($message, $logOutput); } /** * test default value of stream 'outputAs' * * @return void */ public function testDefaultOutputAs() { TestCakeLog::config('test_console_log', array( 'engine' => 'TestConsole', )); if ((DS === '\\' && !(bool)env('ANSICON') && env('ConEmuANSI') !== 'ON') || (function_exists('posix_isatty') && !posix_isatty(null)) ) { $expected = ConsoleOutput::PLAIN; } else { $expected = ConsoleOutput::COLOR; } $stream = TestCakeLog::stream('test_console_log'); $config = $stream->config(); $this->assertEquals($expected, $config['outputAs']); } } cakephp-2.8.0/lib/Cake/Test/Case/Log/Engine/FileLogTest.php000066400000000000000000000137671265552240500232030ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Log.Engine * @since CakePHP(tm) v 1.3 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('FileLog', 'Log/Engine'); /** * CakeLogTest class * * @package Cake.Test.Case.Log.Engine */ class FileLogTest extends CakeTestCase { /** * testLogFileWriting method * * @return void */ public function testLogFileWriting() { $this->_deleteLogs(LOGS); $log = new FileLog(); $log->write('warning', 'Test warning'); $this->assertTrue(file_exists(LOGS . 'error.log')); $result = file_get_contents(LOGS . 'error.log'); $this->assertRegExp('/^2[0-9]{3}-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+ Warning: Test warning/', $result); $log->write('debug', 'Test warning'); $this->assertTrue(file_exists(LOGS . 'debug.log')); $result = file_get_contents(LOGS . 'debug.log'); $this->assertRegExp('/^2[0-9]{3}-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+ Debug: Test warning/', $result); $log->write('random', 'Test warning'); $this->assertTrue(file_exists(LOGS . 'random.log')); $result = file_get_contents(LOGS . 'random.log'); $this->assertRegExp('/^2[0-9]{3}-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+ Random: Test warning/', $result); } /** * test using the path setting to write logs in other places. * * @return void */ public function testPathSetting() { $path = TMP . 'tests' . DS; $this->_deleteLogs($path); $log = new FileLog(compact('path')); $log->write('warning', 'Test warning'); $this->assertTrue(file_exists($path . 'error.log')); } /** * test log rotation * * @return void */ public function testRotation() { $path = TMP . 'tests' . DS; $this->_deleteLogs($path); file_put_contents($path . 'error.log', "this text is under 35 bytes\n"); $log = new FileLog(array( 'path' => $path, 'size' => 35, 'rotate' => 2 )); $log->write('warning', 'Test warning one'); $this->assertTrue(file_exists($path . 'error.log')); $result = file_get_contents($path . 'error.log'); $this->assertRegExp('/Warning: Test warning one/', $result); $this->assertEquals(0, count(glob($path . 'error.log.*'))); clearstatcache(); $log->write('warning', 'Test warning second'); $files = glob($path . 'error.log.*'); $this->assertEquals(1, count($files)); $result = file_get_contents($files[0]); $this->assertRegExp('/this text is under 35 bytes/', $result); $this->assertRegExp('/Warning: Test warning one/', $result); sleep(1); clearstatcache(); $log->write('warning', 'Test warning third'); $result = file_get_contents($path . 'error.log'); $this->assertRegExp('/Warning: Test warning third/', $result); $files = glob($path . 'error.log.*'); $this->assertEquals(2, count($files)); $result = file_get_contents($files[0]); $this->assertRegExp('/this text is under 35 bytes/', $result); $result = file_get_contents($files[1]); $this->assertRegExp('/Warning: Test warning second/', $result); file_put_contents($path . 'error.log.0000000000', "The oldest log file with over 35 bytes.\n"); sleep(1); clearstatcache(); $log->write('warning', 'Test warning fourth'); // rotate count reached so file count should not increase $files = glob($path . 'error.log.*'); $this->assertEquals(2, count($files)); $result = file_get_contents($path . 'error.log'); $this->assertRegExp('/Warning: Test warning fourth/', $result); $result = file_get_contents(array_pop($files)); $this->assertRegExp('/Warning: Test warning third/', $result); $result = file_get_contents(array_pop($files)); $this->assertRegExp('/Warning: Test warning second/', $result); file_put_contents($path . 'debug.log', "this text is just greater than 35 bytes\n"); $log = new FileLog(array( 'path' => $path, 'size' => 35, 'rotate' => 0 )); file_put_contents($path . 'debug.log.0000000000', "The oldest log file with over 35 bytes.\n"); $log->write('debug', 'Test debug'); $this->assertTrue(file_exists($path . 'debug.log')); $result = file_get_contents($path . 'debug.log'); $this->assertRegExp('/^2[0-9]{3}-[0-9]+-[0-9]+ [0-9]+:[0-9]+:[0-9]+ Debug: Test debug/', $result); $this->assertFalse(strstr($result, 'greater than 5 bytes')); $this->assertEquals(0, count(glob($path . 'debug.log.*'))); } public function testMaskSetting() { if (DS === '\\') { $this->markTestSkipped('File permission testing does not work on Windows.'); } $path = TMP . 'tests' . DS; $this->_deleteLogs($path); $log = new FileLog(array('path' => $path, 'mask' => 0666)); $log->write('warning', 'Test warning one'); $result = substr(sprintf('%o', fileperms($path . 'error.log')), -4); $expected = '0666'; $this->assertEquals($expected, $result); unlink($path . 'error.log'); $log = new FileLog(array('path' => $path, 'mask' => 0644)); $log->write('warning', 'Test warning two'); $result = substr(sprintf('%o', fileperms($path . 'error.log')), -4); $expected = '0644'; $this->assertEquals($expected, $result); unlink($path . 'error.log'); $log = new FileLog(array('path' => $path, 'mask' => 0640)); $log->write('warning', 'Test warning three'); $result = substr(sprintf('%o', fileperms($path . 'error.log')), -4); $expected = '0640'; $this->assertEquals($expected, $result); unlink($path . 'error.log'); } /** * helper function to clears all log files in specified directory * * @return void */ protected function _deleteLogs($dir) { $files = array_merge(glob($dir . '*.log'), glob($dir . '*.log.*')); foreach ($files as $file) { unlink($file); } } } cakephp-2.8.0/lib/Cake/Test/Case/Log/Engine/SyslogLogTest.php000066400000000000000000000051511265552240500235700ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Log.Engine * @since CakePHP(tm) v 2.4 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('SyslogLog', 'Log/Engine'); /** * SyslogLogTest class * * @package Cake.Test.Case.Log.Engine */ class SyslogLogTest extends CakeTestCase { /** * Tests that the connection to the logger is open with the right arguments * * @return void */ public function testOpenLog() { $log = $this->getMock('SyslogLog', array('_open', '_write')); $log->expects($this->once())->method('_open')->with('', LOG_ODELAY, LOG_USER); $log->write('debug', 'message'); $log = $this->getMock('SyslogLog', array('_open', '_write')); $log->config(array( 'prefix' => 'thing', 'flag' => LOG_NDELAY, 'facility' => LOG_MAIL, 'format' => '%s: %s' )); $log->expects($this->once())->method('_open') ->with('thing', LOG_NDELAY, LOG_MAIL); $log->write('debug', 'message'); } /** * Tests that single lines are written to syslog * * @dataProvider typesProvider * @return void */ public function testWriteOneLine($type, $expected) { $log = $this->getMock('SyslogLog', array('_open', '_write')); $log->expects($this->once())->method('_write')->with($expected, $type . ': Foo'); $log->write($type, 'Foo'); } /** * Tests that multiple lines are split and logged separately * * @return void */ public function testWriteMultiLine() { $log = $this->getMock('SyslogLog', array('_open', '_write')); $log->expects($this->at(1))->method('_write')->with(LOG_DEBUG, 'debug: Foo'); $log->expects($this->at(2))->method('_write')->with(LOG_DEBUG, 'debug: Bar'); $log->expects($this->exactly(2))->method('_write'); $log->write('debug', "Foo\nBar"); } /** * Data provider for the write function test * * @return array */ public function typesProvider() { return array( array('emergency', LOG_EMERG), array('alert', LOG_ALERT), array('critical', LOG_CRIT), array('error', LOG_ERR), array('warning', LOG_WARNING), array('notice', LOG_NOTICE), array('info', LOG_INFO), array('debug', LOG_DEBUG) ); } } cakephp-2.8.0/lib/Cake/Test/Case/Log/LogEngineCollectionTest.php000066400000000000000000000042001265552240500243160ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Log * @since CakePHP(tm) v 2.4 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('LogEngineCollection', 'Log'); App::uses('FileLog', 'Log/Engine'); /** * LoggerEngineLog class */ class LoggerEngineLog extends FileLog { } /** * LogEngineCollectionTest class * * @package Cake.Test.Case.Log */ class LogEngineCollectionTest extends CakeTestCase { public $Collection; /** * Start test callback * * @return void */ public function setUp() { parent::setUp(); $this->Collection = new LogEngineCollection(); } /** * test load * * @return void */ public function testLoad() { $result = $this->Collection->load('key', array('engine' => 'File')); $this->assertInstanceOf('CakeLogInterface', $result); } /** * test load with deprecated Log suffix * * @return void */ public function testLoadWithSuffix() { $result = $this->Collection->load('key', array('engine' => 'FileLog')); $this->assertInstanceOf('CakeLogInterface', $result); } /** * test that engines starting with Log also work properly * * @return void */ public function testLoadWithSuffixAtBeginning() { $result = $this->Collection->load('key', array('engine' => 'LoggerEngine')); $this->assertInstanceOf('CakeLogInterface', $result); } /** * test load with invalid Log * * @return void * @expectedException CakeLogException */ public function testLoadInvalid() { $result = $this->Collection->load('key', array('engine' => 'ImaginaryFile')); $this->assertInstanceOf('CakeLogInterface', $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/000077500000000000000000000000001265552240500174055ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Model/AclNodeTest.php000066400000000000000000000201071265552240500222630ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('DbAcl', 'Controller/Component/Acl'); App::uses('AclNode', 'Model'); /** * DB ACL wrapper test class * * @package Cake.Test.Case.Model */ class DbAclNodeTestBase extends AclNode { /** * useDbConfig property * * @var string */ public $useDbConfig = 'test'; /** * cacheSources property * * @var bool */ public $cacheSources = false; } /** * Aro Test Wrapper * * @package Cake.Test.Case.Model */ class DbAroTest extends DbAclNodeTestBase { /** * useTable property * * @var string */ public $useTable = 'aros'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('DbAcoTest' => array('with' => 'DbPermissionTest')); } /** * Aco Test Wrapper * * @package Cake.Test.Case.Model */ class DbAcoTest extends DbAclNodeTestBase { /** * useTable property * * @var string */ public $useTable = 'acos'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('DbAroTest' => array('with' => 'DbPermissionTest')); } /** * Permission Test Wrapper * * @package Cake.Test.Case.Model */ class DbPermissionTest extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'aros_acos'; /** * cacheQueries property * * @var bool */ public $cacheQueries = false; /** * belongsTo property * * @var array */ public $belongsTo = array('DbAroTest' => array('foreignKey' => 'aro_id'), 'DbAcoTest' => array('foreignKey' => 'aco_id')); } /** * DboActionTest class * * @package Cake.Test.Case.Model */ class DbAcoActionTest extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'aco_actions'; /** * belongsTo property * * @var array */ public $belongsTo = array('DbAcoTest' => array('foreignKey' => 'aco_id')); } /** * DbAroUserTest class * * @package Cake.Test.Case.Model */ class DbAroUserTest extends CakeTestModel { /** * name property * * @var string */ public $name = 'AuthUser'; /** * useTable property * * @var string */ public $useTable = 'auth_users'; /** * bindNode method * * @param string|array|Model $ref * @return void */ public function bindNode($ref = null) { if (Configure::read('DbAclbindMode') === 'string') { return 'ROOT/admins/Gandalf'; } elseif (Configure::read('DbAclbindMode') === 'array') { return array('DbAroTest' => array('DbAroTest.model' => 'AuthUser', 'DbAroTest.foreign_key' => 2)); } } } /** * TestDbAcl class * * @package Cake.Test.Case.Model */ class TestDbAcl extends DbAcl { /** * Constructor */ public function __construct() { $this->Aro = new DbAroTest(); $this->Aro->Permission = new DbPermissionTest(); $this->Aco = new DbAcoTest(); $this->Aro->Permission = new DbPermissionTest(); } } /** * AclNodeTest class * * @package Cake.Test.Case.Model */ class AclNodeTest extends CakeTestCase { /** * fixtures property * * @var array */ public $fixtures = array('core.aro', 'core.aco', 'core.aros_aco', 'core.aco_action', 'core.auth_user'); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); Configure::write('Acl.classname', 'TestDbAcl'); Configure::write('Acl.database', 'test'); } /** * testNode method * * @return void */ public function testNode() { $Aco = new DbAcoTest(); $result = Hash::extract($Aco->node('Controller1'), '{n}.DbAcoTest.id'); $expected = array(2, 1); $this->assertEquals($expected, $result); $result = Hash::extract($Aco->node('Controller1/action1'), '{n}.DbAcoTest.id'); $expected = array(3, 2, 1); $this->assertEquals($expected, $result); $result = Hash::extract($Aco->node('Controller2/action1'), '{n}.DbAcoTest.id'); $expected = array(7, 6, 1); $this->assertEquals($expected, $result); $result = Hash::extract($Aco->node('Controller1/action2'), '{n}.DbAcoTest.id'); $expected = array(5, 2, 1); $this->assertEquals($expected, $result); $result = Hash::extract($Aco->node('Controller1/action1/record1'), '{n}.DbAcoTest.id'); $expected = array(4, 3, 2, 1); $this->assertEquals($expected, $result); $result = Hash::extract($Aco->node('Controller2/action1/record1'), '{n}.DbAcoTest.id'); $expected = array(8, 7, 6, 1); $this->assertEquals($expected, $result); $this->assertFalse($Aco->node('Controller2/action3')); $this->assertFalse($Aco->node('Controller2/action3/record5')); $result = $Aco->node(''); $this->assertEquals(null, $result); } /** * test that node() doesn't dig deeper than it should. * * @return void */ public function testNodeWithDuplicatePathSegments() { $Aco = new DbAcoTest(); $nodes = $Aco->node('ROOT/Users'); $this->assertEquals(1, $nodes[0]['DbAcoTest']['parent_id'], 'Parent id does not point at ROOT. %s'); } /** * testNodeArrayFind method * * @return void */ public function testNodeArrayFind() { $Aro = new DbAroTest(); Configure::write('DbAclbindMode', 'string'); $result = Hash::extract($Aro->node(array('DbAroUserTest' => array('id' => '1', 'foreign_key' => '1'))), '{n}.DbAroTest.id'); $expected = array(3, 2, 1); $this->assertEquals($expected, $result); Configure::write('DbAclbindMode', 'array'); $result = Hash::extract($Aro->node(array('DbAroUserTest' => array('id' => 4, 'foreign_key' => 2))), '{n}.DbAroTest.id'); $expected = array(4); $this->assertEquals($expected, $result); } /** * testNodeObjectFind method * * @return void */ public function testNodeObjectFind() { $Aro = new DbAroTest(); $Model = new DbAroUserTest(); $Model->id = 1; $result = Hash::extract($Aro->node($Model), '{n}.DbAroTest.id'); $expected = array(3, 2, 1); $this->assertEquals($expected, $result); $Model->id = 2; $result = Hash::extract($Aro->node($Model), '{n}.DbAroTest.id'); $expected = array(4, 2, 1); $this->assertEquals($expected, $result); } /** * testNodeAliasParenting method * * @return void */ public function testNodeAliasParenting() { $Aco = ClassRegistry::init('DbAcoTest'); $db = $Aco->getDataSource(); $db->truncate($Aco); $Aco->create(array('model' => null, 'foreign_key' => null, 'parent_id' => null, 'alias' => 'Application')); $Aco->save(); $Aco->create(array('model' => null, 'foreign_key' => null, 'parent_id' => $Aco->id, 'alias' => 'Pages')); $Aco->save(); $result = $Aco->find('all'); $expected = array( array('DbAcoTest' => array('id' => '1', 'parent_id' => null, 'model' => null, 'foreign_key' => null, 'alias' => 'Application', 'lft' => '1', 'rght' => '4'), 'DbAroTest' => array()), array('DbAcoTest' => array('id' => '2', 'parent_id' => '1', 'model' => null, 'foreign_key' => null, 'alias' => 'Pages', 'lft' => '2', 'rght' => '3'), 'DbAroTest' => array()) ); $this->assertEquals($expected, $result); } /** * testNodeActionAuthorize method * * @return void */ public function testNodeActionAuthorize() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); $Aro = new DbAroTest(); $Aro->create(); $Aro->save(array('model' => 'TestPluginAuthUser', 'foreign_key' => 1)); $result = $Aro->id; $expected = 5; $this->assertEquals($expected, $result); $node = $Aro->node(array('TestPlugin.TestPluginAuthUser' => array('id' => 1, 'user' => 'mariano'))); $result = Hash::get($node, '0.DbAroTest.id'); $expected = $Aro->id; $this->assertEquals($expected, $result); CakePlugin::unload('TestPlugin'); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Behavior/000077500000000000000000000000001265552240500211445ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Model/Behavior/AclBehaviorTest.php000066400000000000000000000236631265552240500247060ustar00rootroot00000000000000 'both'); /** * belongsTo property * * @var array */ public $belongsTo = array( 'Mother' => array( 'className' => 'AclPerson', 'foreignKey' => 'mother_id', ) ); /** * hasMany property * * @var array */ public $hasMany = array( 'Child' => array( 'className' => 'AclPerson', 'foreignKey' => 'mother_id' ) ); /** * parentNode method * * @return void */ public function parentNode() { if (!$this->id && empty($this->data)) { return null; } if (isset($this->data['AclPerson']['mother_id'])) { $motherId = $this->data['AclPerson']['mother_id']; } else { $motherId = $this->field('mother_id'); } if (!$motherId) { return null; } return array('AclPerson' => array('id' => $motherId)); } } /** * AclUser class * * @package Cake.Test.Case.Model.Behavior */ class AclUser extends CakeTestModel { /** * name property * * @var string */ public $name = 'User'; /** * useTable property * * @var string */ public $useTable = 'users'; /** * actsAs property * * @var array */ public $actsAs = array('Acl' => array('type' => 'requester')); /** * parentNode * * @return null */ public function parentNode() { return null; } } /** * AclPost class * * @package Cake.Test.Case.Model.Behavior */ class AclPost extends CakeTestModel { /** * name property * * @var string */ public $name = 'Post'; /** * useTable property * * @var string */ public $useTable = 'posts'; /** * actsAs property * * @var array */ public $actsAs = array('Acl' => array('type' => 'Controlled')); /** * parentNode * * @return null */ public function parentNode() { return null; } } /** * AclBehaviorTest class * * @package Cake.Test.Case.Model.Behavior */ class AclBehaviorTest extends CakeTestCase { /** * Aco property * * @var Aco */ public $Aco; /** * Aro property * * @var Aro */ public $Aro; /** * fixtures property * * @var array */ public $fixtures = array('core.person', 'core.user', 'core.post', 'core.aco', 'core.aro', 'core.aros_aco'); /** * Set up the test * * @return void */ public function setUp() { parent::setUp(); Configure::write('Acl.database', 'test'); $this->Aco = new Aco(); $this->Aro = new Aro(); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Aro, $this->Aco); } /** * Test Setup of AclBehavior * * @return void */ public function testSetup() { parent::setUp(); $User = new AclUser(); $this->assertTrue(isset($User->Behaviors->Acl->settings['User'])); $this->assertEquals('requester', $User->Behaviors->Acl->settings['User']['type']); $this->assertTrue(is_object($User->Aro)); $Post = new AclPost(); $this->assertTrue(isset($Post->Behaviors->Acl->settings['Post'])); $this->assertEquals('controlled', $Post->Behaviors->Acl->settings['Post']['type']); $this->assertTrue(is_object($Post->Aco)); } /** * Test Setup of AclBehavior as both requester and controlled * * @return void */ public function testSetupMulti() { $User = new AclPerson(); $this->assertTrue(isset($User->Behaviors->Acl->settings['AclPerson'])); $this->assertEquals('both', $User->Behaviors->Acl->settings['AclPerson']['type']); $this->assertTrue(is_object($User->Aro)); $this->assertTrue(is_object($User->Aco)); } /** * test After Save * * @return void */ public function testAfterSave() { $Post = new AclPost(); $data = array( 'Post' => array( 'author_id' => 1, 'title' => 'Acl Post', 'body' => 'post body', 'published' => 1 ), ); $Post->save($data); $result = $this->Aco->find('first', array( 'conditions' => array('Aco.model' => 'Post', 'Aco.foreign_key' => $Post->id) )); $this->assertTrue(is_array($result)); $this->assertEquals('Post', $result['Aco']['model']); $this->assertEquals($Post->id, $result['Aco']['foreign_key']); $aroData = array( 'Aro' => array( 'model' => 'AclPerson', 'foreign_key' => 2, 'parent_id' => null ) ); $this->Aro->save($aroData); $acoData = array( 'Aco' => array( 'model' => 'AclPerson', 'foreign_key' => 2, 'parent_id' => null ) ); $this->Aco->save($acoData); $Person = new AclPerson(); $data = array( 'AclPerson' => array( 'name' => 'Trent', 'mother_id' => 2, 'father_id' => 3, ), ); $Person->save($data); $result = $this->Aro->find('first', array( 'conditions' => array('Aro.model' => 'AclPerson', 'Aro.foreign_key' => $Person->id) )); $this->assertTrue(is_array($result)); $this->assertEquals(5, $result['Aro']['parent_id']); $node = $Person->node(array('model' => 'AclPerson', 'foreign_key' => 8), 'Aro'); $this->assertEquals(2, count($node)); $this->assertEquals(5, $node[0]['Aro']['parent_id']); $this->assertEquals(null, $node[1]['Aro']['parent_id']); $aroData = array( 'Aro' => array( 'model' => 'AclPerson', 'foreign_key' => 1, 'parent_id' => null ) ); $this->Aro->create(); $this->Aro->save($aroData); $acoData = array( 'Aco' => array( 'model' => 'AclPerson', 'foreign_key' => 1, 'parent_id' => null )); $this->Aco->create(); $this->Aco->save($acoData); $Person->read(null, 8); $Person->set('mother_id', 1); $Person->save(); $result = $this->Aro->find('first', array( 'conditions' => array('Aro.model' => 'AclPerson', 'Aro.foreign_key' => $Person->id) )); $this->assertTrue(is_array($result)); $this->assertEquals(7, $result['Aro']['parent_id']); $node = $Person->node(array('model' => 'AclPerson', 'foreign_key' => 8), 'Aro'); $this->assertEquals(2, count($node)); $this->assertEquals(7, $node[0]['Aro']['parent_id']); $this->assertEquals(null, $node[1]['Aro']['parent_id']); } /** * test that an afterSave on an update does not cause parent_id to become null. * * @return void */ public function testAfterSaveUpdateParentIdNotNull() { $aroData = array( 'Aro' => array( 'model' => 'AclPerson', 'foreign_key' => 2, 'parent_id' => null ) ); $this->Aro->save($aroData); $acoData = array( 'Aco' => array( 'model' => 'AclPerson', 'foreign_key' => 2, 'parent_id' => null ) ); $this->Aco->save($acoData); $Person = new AclPerson(); $data = array( 'AclPerson' => array( 'name' => 'Trent', 'mother_id' => 2, 'father_id' => 3, ), ); $Person->save($data); $result = $this->Aro->find('first', array( 'conditions' => array('Aro.model' => 'AclPerson', 'Aro.foreign_key' => $Person->id) )); $this->assertTrue(is_array($result)); $this->assertEquals(5, $result['Aro']['parent_id']); $Person->save(array('id' => $Person->id, 'name' => 'Bruce')); $result = $this->Aro->find('first', array( 'conditions' => array('Aro.model' => 'AclPerson', 'Aro.foreign_key' => $Person->id) )); $this->assertEquals(5, $result['Aro']['parent_id']); } /** * Test After Delete * * @return void */ public function testAfterDelete() { $aroData = array( 'Aro' => array( 'model' => 'AclPerson', 'foreign_key' => 2, 'parent_id' => null ) ); $this->Aro->save($aroData); $acoData = array( 'Aco' => array( 'model' => 'AclPerson', 'foreign_key' => 2, 'parent_id' => null ) ); $this->Aco->save($acoData); $Person = new AclPerson(); $data = array( 'AclPerson' => array( 'name' => 'Trent', 'mother_id' => 2, 'father_id' => 3, ), ); $Person->save($data); $id = $Person->id; $node = $Person->node(null, 'Aro'); $this->assertEquals(2, count($node)); $this->assertEquals(5, $node[0]['Aro']['parent_id']); $this->assertEquals(null, $node[1]['Aro']['parent_id']); $Person->delete($id); $result = $this->Aro->find('first', array( 'conditions' => array('Aro.model' => 'AclPerson', 'Aro.foreign_key' => $id) )); $this->assertTrue(empty($result)); $result = $this->Aro->find('first', array( 'conditions' => array('Aro.model' => 'AclPerson', 'Aro.foreign_key' => 2) )); $this->assertFalse(empty($result)); $data = array( 'AclPerson' => array( 'name' => 'Trent', 'mother_id' => 2, 'father_id' => 3, ), ); $Person->save($data); $id = $Person->id; $Person->delete(2); $result = $this->Aro->find('first', array( 'conditions' => array('Aro.model' => 'AclPerson', 'Aro.foreign_key' => $id) )); $this->assertTrue(empty($result)); $result = $this->Aro->find('first', array( 'conditions' => array('Aro.model' => 'AclPerson', 'Aro.foreign_key' => 2) )); $this->assertTrue(empty($result)); } /** * Test Node() * * @return void */ public function testNode() { $Person = new AclPerson(); $aroData = array( 'Aro' => array( 'model' => 'AclPerson', 'foreign_key' => 2, 'parent_id' => null ) ); $this->Aro->save($aroData); $Person->id = 2; $result = $Person->node(null, 'Aro'); $this->assertTrue(is_array($result)); $this->assertEquals(1, count($result)); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Behavior/ContainableBehaviorTest.php000066400000000000000000004605441265552240500264310ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model.Behavior * @since CakePHP(tm) v 1.2.0.5669 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Model', 'Model'); App::uses('AppModel', 'Model'); require_once dirname(dirname(__FILE__)) . DS . 'models.php'; /** * ContainableTest class * * @package Cake.Test.Case.Model.Behavior */ class ContainableBehaviorTest extends CakeTestCase { /** * Fixtures associated with this test case * * @var array */ public $fixtures = array( 'core.article', 'core.article_featured', 'core.article_featureds_tags', 'core.articles_tag', 'core.attachment', 'core.category', 'core.comment', 'core.featured', 'core.tag', 'core.user', 'core.join_a', 'core.join_b', 'core.join_c', 'core.join_a_c', 'core.join_a_b' ); /** * Method executed before each test * * @return void */ public function setUp() { parent::setUp(); $this->User = ClassRegistry::init('User'); $this->Article = ClassRegistry::init('Article'); $this->Tag = ClassRegistry::init('Tag'); $this->User->bindModel(array( 'hasMany' => array('Article', 'ArticleFeatured', 'Comment') ), false); $this->User->ArticleFeatured->unbindModel(array('belongsTo' => array('Category')), false); $this->User->ArticleFeatured->hasMany['Comment']['foreignKey'] = 'article_id'; $this->Tag->bindModel(array( 'hasAndBelongsToMany' => array('Article') ), false); $this->User->Behaviors->load('Containable'); $this->Article->Behaviors->load('Containable'); $this->Tag->Behaviors->load('Containable'); } /** * Method executed after each test * * @return void */ public function tearDown() { unset($this->Article); unset($this->User); unset($this->Tag); parent::tearDown(); } /** * testContainments method * * @return void */ public function testContainments() { $r = $this->_containments($this->Article, array('Comment' => array('conditions' => array('Comment.user_id' => 2)))); $this->assertTrue(Set::matches('/Article/keep/Comment/conditions[Comment.user_id=2]', $r)); $r = $this->_containments($this->User, array( 'ArticleFeatured' => array( 'Featured' => array( 'id', 'Category' => 'name' ) ))); $this->assertEquals(array('id'), Hash::extract($r, 'ArticleFeatured.keep.Featured.fields')); $r = $this->_containments($this->Article, array( 'Comment' => array( 'User', 'conditions' => array('Comment' => array('user_id' => 2)), ), )); $this->assertTrue(Set::matches('/User', $r)); $this->assertTrue(Set::matches('/Comment', $r)); $this->assertTrue(Set::matches('/Article/keep/Comment/conditions/Comment[user_id=2]', $r)); $r = $this->_containments($this->Article, array('Comment(comment, published)' => 'Attachment(attachment)', 'User(user)')); $this->assertTrue(Set::matches('/Comment', $r)); $this->assertTrue(Set::matches('/User', $r)); $this->assertTrue(Set::matches('/Article/keep/Comment', $r)); $this->assertTrue(Set::matches('/Article/keep/User', $r)); $this->assertEquals(array('comment', 'published'), Hash::extract($r, 'Article.keep.Comment.fields')); $this->assertEquals(array('user'), Hash::extract($r, 'Article.keep.User.fields')); $this->assertTrue(Set::matches('/Comment/keep/Attachment', $r)); $this->assertEquals(array('attachment'), Hash::extract($r, 'Comment.keep.Attachment.fields')); $r = $this->_containments($this->Article, array('Comment' => array('limit' => 1))); $this->assertEquals(array('Comment', 'Article'), array_keys($r)); $result = Hash::extract($r, 'Comment[keep]'); $this->assertEquals(array('keep' => array()), array_shift($result)); $this->assertTrue(Set::matches('/Article/keep/Comment', $r)); $result = Hash::extract($r, 'Article.keep'); $this->assertEquals(array('limit' => 1), array_shift($result)); $r = $this->_containments($this->Article, array('Comment.User')); $this->assertEquals(array('User', 'Comment', 'Article'), array_keys($r)); $result = Hash::extract($r, 'User[keep]'); $this->assertEquals(array('keep' => array()), array_shift($result)); $result = Hash::extract($r, 'Comment[keep]'); $this->assertEquals(array('keep' => array('User' => array())), array_shift($result)); $result = Hash::extract($r, 'Article[keep]'); $this->assertEquals(array('keep' => array('Comment' => array())), array_shift($result)); $r = $this->_containments($this->Tag, array('Article' => array('User' => array('Comment' => array( 'Attachment' => array('conditions' => array('Attachment.id >' => 1)) ))))); $this->assertTrue(Set::matches('/Attachment', $r)); $this->assertTrue(Set::matches('/Comment/keep/Attachment/conditions', $r)); $this->assertEquals(array('Attachment.id >' => 1), $r['Comment']['keep']['Attachment']['conditions']); $this->assertTrue(Set::matches('/User/keep/Comment', $r)); $this->assertTrue(Set::matches('/Article/keep/User', $r)); $this->assertTrue(Set::matches('/Tag/keep/Article', $r)); } /** * testInvalidContainments method * * @expectedException PHPUnit_Framework_Error * @return void */ public function testInvalidContainments() { $this->_containments($this->Article, array('Comment', 'InvalidBinding')); } /** * testInvalidContainments method with suppressing error notices * * @return void */ public function testInvalidContainmentsNoNotices() { $this->Article->Behaviors->load('Containable', array('notices' => false)); $this->_containments($this->Article, array('Comment', 'InvalidBinding')); } /** * testBeforeFind method * * @return void */ public function testBeforeFind() { $r = $this->Article->find('all', array('contain' => array('Comment'))); $this->assertFalse(Set::matches('/User', $r)); $this->assertTrue(Set::matches('/Comment', $r)); $this->assertFalse(Set::matches('/Comment/User', $r)); $r = $this->Article->find('all', array('contain' => 'Comment.User')); $this->assertTrue(Set::matches('/Comment/User', $r)); $this->assertFalse(Set::matches('/Comment/Article', $r)); $r = $this->Article->find('all', array('contain' => array('Comment' => array('User', 'Article')))); $this->assertTrue(Set::matches('/Comment/User', $r)); $this->assertTrue(Set::matches('/Comment/Article', $r)); $r = $this->Article->find('all', array('contain' => array('Comment' => array('conditions' => array('Comment.user_id' => 2))))); $this->assertFalse(Set::matches('/Comment[user_id!=2]', $r)); $this->assertTrue(Set::matches('/Comment[user_id=2]', $r)); $r = $this->Article->find('all', array('contain' => array('Comment.user_id = 2'))); $this->assertFalse(Set::matches('/Comment[user_id!=2]', $r)); $r = $this->Article->find('all', array('contain' => 'Comment.id DESC')); $ids = $descIds = Hash::extract($r, 'Comment[1].id'); rsort($descIds); $this->assertEquals($ids, $descIds); $r = $this->Article->find('all', array('contain' => 'Comment')); $this->assertTrue(Set::matches('/Comment[user_id!=2]', $r)); $r = $this->Article->find('all', array('contain' => array('Comment' => array('fields' => 'comment')))); $this->assertFalse(Set::matches('/Comment/created', $r)); $this->assertTrue(Set::matches('/Comment/comment', $r)); $this->assertFalse(Set::matches('/Comment/updated', $r)); $r = $this->Article->find('all', array('contain' => array('Comment' => array('fields' => array('comment', 'updated'))))); $this->assertFalse(Set::matches('/Comment/created', $r)); $this->assertTrue(Set::matches('/Comment/comment', $r)); $this->assertTrue(Set::matches('/Comment/updated', $r)); $r = $this->Article->find('all', array('contain' => array('Comment' => array('comment', 'updated')))); $this->assertFalse(Set::matches('/Comment/created', $r)); $this->assertTrue(Set::matches('/Comment/comment', $r)); $this->assertTrue(Set::matches('/Comment/updated', $r)); $r = $this->Article->find('all', array('contain' => array('Comment(comment,updated)'))); $this->assertFalse(Set::matches('/Comment/created', $r)); $this->assertTrue(Set::matches('/Comment/comment', $r)); $this->assertTrue(Set::matches('/Comment/updated', $r)); $r = $this->Article->find('all', array('contain' => 'Comment.created')); $this->assertTrue(Set::matches('/Comment/created', $r)); $this->assertFalse(Set::matches('/Comment/comment', $r)); $r = $this->Article->find('all', array('contain' => array('User.Article(title)', 'Comment(comment)'))); $this->assertFalse(Set::matches('/Comment/Article', $r)); $this->assertFalse(Set::matches('/Comment/User', $r)); $this->assertTrue(Set::matches('/Comment/comment', $r)); $this->assertFalse(Set::matches('/Comment/created', $r)); $this->assertTrue(Set::matches('/User/Article/title', $r)); $this->assertFalse(Set::matches('/User/Article/created', $r)); $r = $this->Article->find('all', array('contain' => array())); $this->assertFalse(Set::matches('/User', $r)); $this->assertFalse(Set::matches('/Comment', $r)); } /** * testBeforeFindWithNonExistingBinding method * * @expectedException PHPUnit_Framework_Error * @return void */ public function testBeforeFindWithNonExistingBinding() { $this->Article->find('all', array('contain' => array('Comment' => 'NonExistingBinding'))); } /** * testContain method * * @return void */ public function testContain() { $this->Article->contain('Comment.User'); $r = $this->Article->find('all'); $this->assertTrue(Set::matches('/Comment/User', $r)); $this->assertFalse(Set::matches('/Comment/Article', $r)); $r = $this->Article->find('all'); $this->assertFalse(Set::matches('/Comment/User', $r)); } /** * testContainFindList method * * @return void */ public function testContainFindList() { $this->Article->contain('Comment.User'); $result = $this->Article->find('list'); $expected = array( 1 => 'First Article', 2 => 'Second Article', 3 => 'Third Article' ); $this->assertEquals($expected, $result); $result = $this->Article->find('list', array('fields' => array('Article.id', 'User.id'), 'contain' => array('User'))); $expected = array( 1 => '1', 2 => '3', 3 => '1' ); $this->assertEquals($expected, $result); } /** * Test that mixing contain() and the contain find option. * * @return void */ public function testContainAndContainOption() { $this->Article->contain(); $r = $this->Article->find('all', array( 'contain' => array('Comment') )); $this->assertTrue(isset($r[0]['Comment']), 'No comment returned'); } /** * testFindEmbeddedNoBindings method * * @return void */ public function testFindEmbeddedNoBindings() { $result = $this->Article->find('all', array('contain' => false)); $expected = array( array('Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' )), array('Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' )), array('Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' )) ); $this->assertEquals($expected, $result); } /** * testFindFirstLevel method * * @return void */ public function testFindFirstLevel() { $this->Article->contain('User'); $result = $this->Article->find('all', array('recursive' => 1)); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ) ); $this->assertEquals($expected, $result); $this->Article->contain('User', 'Comment'); $result = $this->Article->find('all', array('recursive' => 1)); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31' ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' ) ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Comment' => array() ) ); $this->assertEquals($expected, $result); } /** * testFindEmbeddedFirstLevel method * * @return void */ public function testFindEmbeddedFirstLevel() { $result = $this->Article->find('all', array('contain' => array('User'))); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ) ); $this->assertEquals($expected, $result); $result = $this->Article->find('all', array('contain' => array('User', 'Comment'))); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31' ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' ) ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Comment' => array() ) ); $this->assertEquals($expected, $result); } /** * testFindSecondLevel method * * @return void */ public function testFindSecondLevel() { $this->Article->contain(array('Comment' => 'User')); $result = $this->Article->find('all', array('recursive' => 2)); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ) ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31', 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ) ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31', 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31', 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ) ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ) ) ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'Comment' => array() ) ); $this->assertEquals($expected, $result); $this->Article->contain(array('User' => 'ArticleFeatured')); $result = $this->Article->find('all', array('recursive' => 2)); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31', 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ) ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ) ) ); $this->assertEquals($expected, $result); $this->Article->contain(array('User' => array('id', 'ArticleFeatured'))); $result = $this->Article->find('all', array('recursive' => 2)); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => 1, 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => 3, 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ) ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => 1, 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ) ) ); $this->assertEquals($expected, $result); $this->Article->contain(array('User' => array('ArticleFeatured', 'Comment'))); $result = $this->Article->find('all', array('recursive' => 2)); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ), 'Comment' => array( array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ), array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ) ) ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31', 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ), 'Comment' => array() ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ), 'Comment' => array( array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ), array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ) ) ) ) ); $this->assertEquals($expected, $result); $this->Article->contain(array('User' => array('ArticleFeatured')), 'Tag', array('Comment' => 'Attachment')); $result = $this->Article->find('all', array('recursive' => 2)); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'Attachment' => array() ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31', 'Attachment' => array() ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31', 'Attachment' => array() ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31', 'Attachment' => array() ) ), 'Tag' => array( array('id' => 1, 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31'), array('id' => 2, 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31') ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31', 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ) ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'Attachment' => array( 'id' => 1, 'comment_id' => 5, 'attachment' => 'attachment.zip', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'Attachment' => array() ) ), 'Tag' => array( array('id' => 1, 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31'), array('id' => 3, 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31') ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ), 'Comment' => array(), 'Tag' => array() ) ); $this->assertEquals($expected, $result); } /** * testFindEmbeddedSecondLevel method * * @return void */ public function testFindEmbeddedSecondLevel() { $result = $this->Article->find('all', array('contain' => array('Comment' => 'User'))); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ) ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31', 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ) ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31', 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31', 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ) ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ) ) ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'Comment' => array() ) ); $this->assertEquals($expected, $result); $result = $this->Article->find('all', array('contain' => array('User' => 'ArticleFeatured'))); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31', 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ) ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ) ) ); $this->assertEquals($expected, $result); $result = $this->Article->find('all', array('contain' => array('User' => array('ArticleFeatured', 'Comment')))); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ), 'Comment' => array( array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ), array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ) ) ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31', 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ), 'Comment' => array() ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ), 'Comment' => array( array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ), array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ) ) ) ) ); $this->assertEquals($expected, $result); $result = $this->Article->find('all', array('contain' => array('User' => 'ArticleFeatured', 'Tag', 'Comment' => 'Attachment'))); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'Attachment' => array() ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31', 'Attachment' => array() ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31', 'Attachment' => array() ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31', 'Attachment' => array() ) ), 'Tag' => array( array('id' => 1, 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31'), array('id' => 2, 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31') ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31', 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ) ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'Attachment' => array( 'id' => 1, 'comment_id' => 5, 'attachment' => 'attachment.zip', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'Attachment' => array() ) ), 'Tag' => array( array('id' => 1, 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31'), array('id' => 3, 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31') ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ), 'Comment' => array(), 'Tag' => array() ) ); $this->assertEquals($expected, $result); } /** * testFindThirdLevel method * * @return void */ public function testFindThirdLevel() { $this->User->contain(array('ArticleFeatured' => array('Featured' => 'Category'))); $result = $this->User->find('all', array('recursive' => 3)); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); $this->User->contain(array('ArticleFeatured' => array('Featured' => 'Category', 'Comment' => array('Article', 'Attachment')))); $result = $this->User->find('all', array('recursive' => 3)); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array(), 'Comment' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Attachment' => array( 'id' => 1, 'comment_id' => 5, 'attachment' => 'attachment.zip', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Attachment' => array() ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); $this->User->contain(array('ArticleFeatured' => array('Featured' => 'Category', 'Comment' => 'Attachment'), 'Article')); $result = $this->User->find('all', array('recursive' => 3)); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Article' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'Attachment' => array() ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31', 'Attachment' => array() ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31', 'Attachment' => array() ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31', 'Attachment' => array() ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array(), 'Comment' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'Article' => array(), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'Article' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'Attachment' => array( 'id' => 1, 'comment_id' => 5, 'attachment' => 'attachment.zip', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'Attachment' => array() ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'Article' => array(), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); } /** * testFindEmbeddedThirdLevel method * * @return void */ public function testFindEmbeddedThirdLevel() { $result = $this->User->find('all', array('contain' => array('ArticleFeatured' => array('Featured' => 'Category')))); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); $result = $this->User->find('all', array('contain' => array('ArticleFeatured' => array('Featured' => 'Category', 'Comment' => array('Article', 'Attachment'))))); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array(), 'Comment' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Attachment' => array( 'id' => 1, 'comment_id' => 5, 'attachment' => 'attachment.zip', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Attachment' => array() ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); $result = $this->User->find('all', array('contain' => array('ArticleFeatured' => array('Featured' => 'Category', 'Comment' => 'Attachment'), 'Article'))); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Article' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'Attachment' => array() ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31', 'Attachment' => array() ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31', 'Attachment' => array() ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31', 'Attachment' => array() ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array(), 'Comment' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'Article' => array(), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'Article' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'Attachment' => array( 'id' => 1, 'comment_id' => 5, 'attachment' => 'attachment.zip', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'Attachment' => array() ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'Article' => array(), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); } /** * testSettingsThirdLevel method * * @return void */ public function testSettingsThirdLevel() { $result = $this->User->find('all', array('contain' => array('ArticleFeatured' => array('Featured' => array('Category' => array('id', 'name')))))); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'name' => 'Category 1' ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'name' => 'Category 1' ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); $r = $this->User->find('all', array('contain' => array( 'ArticleFeatured' => array( 'id', 'title', 'Featured' => array( 'id', 'category_id', 'Category' => array('id', 'name') ) ) ))); $this->assertTrue(Set::matches('/User[id=1]', $r)); $this->assertFalse(Set::matches('/Article', $r) || Set::matches('/Comment', $r)); $this->assertTrue(Set::matches('/ArticleFeatured', $r)); $this->assertFalse(Set::matches('/ArticleFeatured/User', $r) || Set::matches('/ArticleFeatured/Comment', $r) || Set::matches('/ArticleFeatured/Tag', $r)); $this->assertTrue(Set::matches('/ArticleFeatured/Featured', $r)); $this->assertFalse(Set::matches('/ArticleFeatured/Featured/ArticleFeatured', $r)); $this->assertTrue(Set::matches('/ArticleFeatured/Featured/Category', $r)); $this->assertTrue(Set::matches('/ArticleFeatured/Featured[id=1]', $r)); $this->assertTrue(Set::matches('/ArticleFeatured/Featured[id=1]/Category[id=1]', $r)); $this->assertTrue(Set::matches('/ArticleFeatured/Featured[id=1]/Category[name=Category 1]', $r)); $r = $this->User->find('all', array('contain' => array( 'ArticleFeatured' => array( 'title', 'Featured' => array( 'id', 'Category' => 'name' ) ) ))); $this->assertTrue(Set::matches('/User[id=1]', $r)); $this->assertFalse(Set::matches('/Article', $r) || Set::matches('/Comment', $r)); $this->assertTrue(Set::matches('/ArticleFeatured', $r)); $this->assertFalse(Set::matches('/ArticleFeatured/User', $r) || Set::matches('/ArticleFeatured/Comment', $r) || Set::matches('/ArticleFeatured/Tag', $r)); $this->assertTrue(Set::matches('/ArticleFeatured/Featured', $r)); $this->assertFalse(Set::matches('/ArticleFeatured/Featured/ArticleFeatured', $r)); $this->assertTrue(Set::matches('/ArticleFeatured/Featured/Category', $r)); $this->assertTrue(Set::matches('/ArticleFeatured/Featured[id=1]', $r)); $this->assertTrue(Set::matches('/ArticleFeatured/Featured[id=1]/Category[name=Category 1]', $r)); $result = $this->User->find('all', array('contain' => array( 'ArticleFeatured' => array( 'title', 'Featured' => array( 'category_id', 'Category' => 'name' ) ) ))); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'ArticleFeatured' => array( array( 'title' => 'First Article', 'id' => 1, 'user_id' => 1, 'Featured' => array( 'category_id' => 1, 'id' => 1, 'Category' => array( 'name' => 'Category 1' ) ) ), array( 'title' => 'Third Article', 'id' => 3, 'user_id' => 1, 'Featured' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'ArticleFeatured' => array( array( 'title' => 'Second Article', 'id' => 2, 'user_id' => 3, 'Featured' => array( 'category_id' => 1, 'id' => 2, 'Category' => array( 'name' => 'Category 1' ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); $orders = array( 'title DESC', 'title DESC, published DESC', array('title' => 'DESC'), array('title' => 'DESC', 'published' => 'DESC'), ); foreach ($orders as $order) { $result = $this->User->find('all', array('contain' => array( 'ArticleFeatured' => array( 'title', 'order' => $order, 'Featured' => array( 'category_id', 'Category' => 'name' ) ) ))); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'ArticleFeatured' => array( array( 'title' => 'Third Article', 'id' => 3, 'user_id' => 1, 'Featured' => array() ), array( 'title' => 'First Article', 'id' => 1, 'user_id' => 1, 'Featured' => array( 'category_id' => 1, 'id' => 1, 'Category' => array( 'name' => 'Category 1' ) ) ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'ArticleFeatured' => array( array( 'title' => 'Second Article', 'id' => 2, 'user_id' => 3, 'Featured' => array( 'category_id' => 1, 'id' => 2, 'Category' => array( 'name' => 'Category 1' ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); } } /** * testFindThirdLevelNonReset method * * @return void */ public function testFindThirdLevelNonReset() { $this->User->contain(false, array('ArticleFeatured' => array('Featured' => 'Category'))); $result = $this->User->find('all', array('recursive' => 3)); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); $this->User->resetBindings(); $this->User->contain(false, array('ArticleFeatured' => array('Featured' => 'Category', 'Comment' => array('Article', 'Attachment')))); $result = $this->User->find('all', array('recursive' => 3)); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array(), 'Comment' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Attachment' => array( 'id' => 1, 'comment_id' => 5, 'attachment' => 'attachment.zip', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Attachment' => array() ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); $this->User->resetBindings(); $this->User->contain(false, array('ArticleFeatured' => array('Featured' => 'Category', 'Comment' => 'Attachment'), 'Article')); $result = $this->User->find('all', array('recursive' => 3)); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Article' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'Attachment' => array() ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31', 'Attachment' => array() ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31', 'Attachment' => array() ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31', 'Attachment' => array() ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array(), 'Comment' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'Article' => array(), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'Article' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'Attachment' => array( 'id' => 1, 'comment_id' => 5, 'attachment' => 'attachment.zip', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'Attachment' => array() ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'Article' => array(), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); } /** * testFindEmbeddedThirdLevelNonReset method * * @return void */ public function testFindEmbeddedThirdLevelNonReset() { $result = $this->User->find('all', array('reset' => false, 'contain' => array('ArticleFeatured' => array('Featured' => 'Category')))); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); $this->_assertBindings($this->User, array('hasMany' => array('ArticleFeatured'))); $this->_assertBindings($this->User->ArticleFeatured, array('hasOne' => array('Featured'))); $this->_assertBindings($this->User->ArticleFeatured->Featured, array('belongsTo' => array('Category'))); $this->User->resetBindings(); $this->_assertBindings($this->User, array('hasMany' => array('Article', 'ArticleFeatured', 'Comment'))); $this->_assertBindings($this->User->ArticleFeatured, array('belongsTo' => array('User'), 'hasOne' => array('Featured'), 'hasMany' => array('Comment'), 'hasAndBelongsToMany' => array('Tag'))); $this->_assertBindings($this->User->ArticleFeatured->Featured, array('belongsTo' => array('ArticleFeatured', 'Category'))); $this->_assertBindings($this->User->ArticleFeatured->Comment, array('belongsTo' => array('Article', 'User'), 'hasOne' => array('Attachment'))); $result = $this->User->find('all', array('reset' => false, 'contain' => array('ArticleFeatured' => array('Featured' => 'Category', 'Comment' => array('Article', 'Attachment'))))); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array(), 'Comment' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Attachment' => array( 'id' => 1, 'comment_id' => 5, 'attachment' => 'attachment.zip', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Attachment' => array() ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); $this->_assertBindings($this->User, array('hasMany' => array('ArticleFeatured'))); $this->_assertBindings($this->User->ArticleFeatured, array('hasOne' => array('Featured'), 'hasMany' => array('Comment'))); $this->_assertBindings($this->User->ArticleFeatured->Featured, array('belongsTo' => array('Category'))); $this->_assertBindings($this->User->ArticleFeatured->Comment, array('belongsTo' => array('Article'), 'hasOne' => array('Attachment'))); $this->User->resetBindings(); $this->_assertBindings($this->User, array('hasMany' => array('Article', 'ArticleFeatured', 'Comment'))); $this->_assertBindings($this->User->ArticleFeatured, array('belongsTo' => array('User'), 'hasOne' => array('Featured'), 'hasMany' => array('Comment'), 'hasAndBelongsToMany' => array('Tag'))); $this->_assertBindings($this->User->ArticleFeatured->Featured, array('belongsTo' => array('ArticleFeatured', 'Category'))); $this->_assertBindings($this->User->ArticleFeatured->Comment, array('belongsTo' => array('Article', 'User'), 'hasOne' => array('Attachment'))); $result = $this->User->find('all', array('contain' => array('ArticleFeatured' => array('Featured' => 'Category', 'Comment' => array('Article', 'Attachment')), false))); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31', 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Attachment' => array() ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array(), 'Comment' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Attachment' => array( 'id' => 1, 'comment_id' => 5, 'attachment' => 'attachment.zip', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Attachment' => array() ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); $this->_assertBindings($this->User, array('hasMany' => array('ArticleFeatured'))); $this->_assertBindings($this->User->ArticleFeatured, array('hasOne' => array('Featured'), 'hasMany' => array('Comment'))); $this->_assertBindings($this->User->ArticleFeatured->Featured, array('belongsTo' => array('Category'))); $this->_assertBindings($this->User->ArticleFeatured->Comment, array('belongsTo' => array('Article'), 'hasOne' => array('Attachment'))); $this->User->resetBindings(); $this->_assertBindings($this->User, array('hasMany' => array('Article', 'ArticleFeatured', 'Comment'))); $this->_assertBindings($this->User->ArticleFeatured, array('belongsTo' => array('User'), 'hasOne' => array('Featured'), 'hasMany' => array('Comment'), 'hasAndBelongsToMany' => array('Tag'))); $this->_assertBindings($this->User->ArticleFeatured->Featured, array('belongsTo' => array('ArticleFeatured', 'Category'))); $this->_assertBindings($this->User->ArticleFeatured->Comment, array('belongsTo' => array('Article', 'User'), 'hasOne' => array('Attachment'))); $result = $this->User->find('all', array('reset' => false, 'contain' => array('ArticleFeatured' => array('Featured' => 'Category', 'Comment' => 'Attachment'), 'Article'))); $expected = array( array( 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Article' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ), 'ArticleFeatured' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Featured' => array( 'id' => 1, 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'Attachment' => array() ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31', 'Attachment' => array() ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31', 'Attachment' => array() ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31', 'Attachment' => array() ) ) ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Featured' => array(), 'Comment' => array() ) ) ), array( 'User' => array( 'id' => 2, 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'Article' => array(), 'ArticleFeatured' => array() ), array( 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'Article' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ), 'ArticleFeatured' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'Featured' => array( 'id' => 2, 'article_featured_id' => 2, 'category_id' => 1, 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ) ), 'Comment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'Attachment' => array( 'id' => 1, 'comment_id' => 5, 'attachment' => 'attachment.zip', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'Attachment' => array() ) ) ) ) ), array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'Article' => array(), 'ArticleFeatured' => array() ) ); $this->assertEquals($expected, $result); $this->_assertBindings($this->User, array('hasMany' => array('Article', 'ArticleFeatured'))); $this->_assertBindings($this->User->Article); $this->_assertBindings($this->User->ArticleFeatured, array('hasOne' => array('Featured'), 'hasMany' => array('Comment'))); $this->_assertBindings($this->User->ArticleFeatured->Featured, array('belongsTo' => array('Category'))); $this->_assertBindings($this->User->ArticleFeatured->Comment, array('hasOne' => array('Attachment'))); $this->User->resetBindings(); $this->_assertBindings($this->User, array('hasMany' => array('Article', 'ArticleFeatured', 'Comment'))); $this->_assertBindings($this->User->Article, array('belongsTo' => array('User'), 'hasMany' => array('Comment'), 'hasAndBelongsToMany' => array('Tag'))); $this->_assertBindings($this->User->ArticleFeatured, array('belongsTo' => array('User'), 'hasOne' => array('Featured'), 'hasMany' => array('Comment'), 'hasAndBelongsToMany' => array('Tag'))); $this->_assertBindings($this->User->ArticleFeatured->Featured, array('belongsTo' => array('ArticleFeatured', 'Category'))); $this->_assertBindings($this->User->ArticleFeatured->Comment, array('belongsTo' => array('Article', 'User'), 'hasOne' => array('Attachment'))); } /** * testEmbeddedFindFields method * * @return void */ public function testEmbeddedFindFields() { $result = $this->Article->find('all', array( 'contain' => array('User(user)'), 'fields' => array('title'), 'order' => array('Article.id' => 'ASC') )); $expected = array( array('Article' => array('title' => 'First Article'), 'User' => array('user' => 'mariano', 'id' => 1)), array('Article' => array('title' => 'Second Article'), 'User' => array('user' => 'larry', 'id' => 3)), array('Article' => array('title' => 'Third Article'), 'User' => array('user' => 'mariano', 'id' => 1)), ); $this->assertEquals($expected, $result); $result = $this->Article->find('all', array( 'contain' => array('User(id, user)'), 'fields' => array('title'), 'order' => array('Article.id' => 'ASC') )); $expected = array( array('Article' => array('title' => 'First Article'), 'User' => array('user' => 'mariano', 'id' => 1)), array('Article' => array('title' => 'Second Article'), 'User' => array('user' => 'larry', 'id' => 3)), array('Article' => array('title' => 'Third Article'), 'User' => array('user' => 'mariano', 'id' => 1)), ); $this->assertEquals($expected, $result); $result = $this->Article->find('all', array( 'contain' => array( 'Comment(comment, published)' => 'Attachment(attachment)', 'User(user)' ), 'fields' => array('title'), 'order' => array('Article.id' => 'ASC') )); if (!empty($result)) { foreach ($result as $i => $article) { foreach ($article['Comment'] as $j => $comment) { $result[$i]['Comment'][$j] = array_diff_key($comment, array('id' => true)); } } } $expected = array( array( 'Article' => array('title' => 'First Article', 'id' => 1), 'User' => array('user' => 'mariano', 'id' => 1), 'Comment' => array( array('comment' => 'First Comment for First Article', 'published' => 'Y', 'article_id' => 1, 'Attachment' => array()), array('comment' => 'Second Comment for First Article', 'published' => 'Y', 'article_id' => 1, 'Attachment' => array()), array('comment' => 'Third Comment for First Article', 'published' => 'Y', 'article_id' => 1, 'Attachment' => array()), array('comment' => 'Fourth Comment for First Article', 'published' => 'N', 'article_id' => 1, 'Attachment' => array()), ) ), array( 'Article' => array('title' => 'Second Article', 'id' => 2), 'User' => array('user' => 'larry', 'id' => 3), 'Comment' => array( array('comment' => 'First Comment for Second Article', 'published' => 'Y', 'article_id' => 2, 'Attachment' => array( 'attachment' => 'attachment.zip', 'id' => 1 )), array('comment' => 'Second Comment for Second Article', 'published' => 'Y', 'article_id' => 2, 'Attachment' => array()) ) ), array( 'Article' => array('title' => 'Third Article', 'id' => 3), 'User' => array('user' => 'mariano', 'id' => 1), 'Comment' => array() ), ); $this->assertEquals($expected, $result); } /** * test that hasOne and belongsTo fields act the same in a contain array. * * @return void */ public function testHasOneFieldsInContain() { $this->Article->unbindModel(array( 'hasMany' => array('Comment') ), true); unset($this->Article->Comment); $this->Article->bindModel(array( 'hasOne' => array('Comment') )); $result = $this->Article->find('all', array( 'fields' => array('title', 'body'), 'contain' => array( 'Comment' => array( 'fields' => array('comment') ), 'User' => array( 'fields' => array('user') ) ), 'order' => 'Article.id ASC', )); $this->assertTrue(isset($result[0]['Article']['title']), 'title missing %s'); $this->assertTrue(isset($result[0]['Article']['body']), 'body missing %s'); $this->assertTrue(isset($result[0]['Comment']['comment']), 'comment missing %s'); $this->assertTrue(isset($result[0]['User']['user']), 'body missing %s'); $this->assertFalse(isset($result[0]['Comment']['published']), 'published found %s'); $this->assertFalse(isset($result[0]['User']['password']), 'password found %s'); } /** * testFindConditionalBinding method * * @return void */ public function testFindConditionalBinding() { $this->Article->contain(array( 'User(user)', 'Tag' => array( 'fields' => array('tag', 'created'), 'conditions' => array('created >=' => '2007-03-18 12:24') ) )); $result = $this->Article->find('all', array( 'fields' => array('title'), 'order' => array('Article.id' => 'ASC') )); $expected = array( array( 'Article' => array('id' => 1, 'title' => 'First Article'), 'User' => array('id' => 1, 'user' => 'mariano'), 'Tag' => array(array('tag' => 'tag2', 'created' => '2007-03-18 12:24:23')) ), array( 'Article' => array('id' => 2, 'title' => 'Second Article'), 'User' => array('id' => 3, 'user' => 'larry'), 'Tag' => array(array('tag' => 'tag3', 'created' => '2007-03-18 12:26:23')) ), array( 'Article' => array('id' => 3, 'title' => 'Third Article'), 'User' => array('id' => 1, 'user' => 'mariano'), 'Tag' => array() ) ); $this->assertEquals($expected, $result); $this->Article->contain(array('User(id,user)', 'Tag' => array('fields' => array('tag', 'created')))); $result = $this->Article->find('all', array('fields' => array('title'), 'order' => array('Article.id' => 'ASC'))); $expected = array( array( 'Article' => array('id' => 1, 'title' => 'First Article'), 'User' => array('id' => 1, 'user' => 'mariano'), 'Tag' => array( array('tag' => 'tag1', 'created' => '2007-03-18 12:22:23'), array('tag' => 'tag2', 'created' => '2007-03-18 12:24:23') ) ), array( 'Article' => array('id' => 2, 'title' => 'Second Article'), 'User' => array('id' => 3, 'user' => 'larry'), 'Tag' => array( array('tag' => 'tag1', 'created' => '2007-03-18 12:22:23'), array('tag' => 'tag3', 'created' => '2007-03-18 12:26:23') ) ), array( 'Article' => array('id' => 3, 'title' => 'Third Article'), 'User' => array('id' => 1, 'user' => 'mariano'), 'Tag' => array() ) ); $this->assertEquals($expected, $result); $result = $this->Article->find('all', array( 'fields' => array('title'), 'contain' => array('User(id,user)', 'Tag' => array('fields' => array('tag', 'created'))), 'order' => array('Article.id' => 'ASC') )); $expected = array( array( 'Article' => array('id' => 1, 'title' => 'First Article'), 'User' => array('id' => 1, 'user' => 'mariano'), 'Tag' => array( array('tag' => 'tag1', 'created' => '2007-03-18 12:22:23'), array('tag' => 'tag2', 'created' => '2007-03-18 12:24:23') ) ), array( 'Article' => array('id' => 2, 'title' => 'Second Article'), 'User' => array('id' => 3, 'user' => 'larry'), 'Tag' => array( array('tag' => 'tag1', 'created' => '2007-03-18 12:22:23'), array('tag' => 'tag3', 'created' => '2007-03-18 12:26:23') ) ), array( 'Article' => array('id' => 3, 'title' => 'Third Article'), 'User' => array('id' => 1, 'user' => 'mariano'), 'Tag' => array() ) ); $this->assertEquals($expected, $result); $this->Article->contain(array( 'User(id,user)', 'Tag' => array( 'fields' => array('tag', 'created'), 'conditions' => array('created >=' => '2007-03-18 12:24') ) )); $result = $this->Article->find('all', array('fields' => array('title'), 'order' => array('Article.id' => 'ASC'))); $expected = array( array( 'Article' => array('id' => 1, 'title' => 'First Article'), 'User' => array('id' => 1, 'user' => 'mariano'), 'Tag' => array(array('tag' => 'tag2', 'created' => '2007-03-18 12:24:23')) ), array( 'Article' => array('id' => 2, 'title' => 'Second Article'), 'User' => array('id' => 3, 'user' => 'larry'), 'Tag' => array(array('tag' => 'tag3', 'created' => '2007-03-18 12:26:23')) ), array( 'Article' => array('id' => 3, 'title' => 'Third Article'), 'User' => array('id' => 1, 'user' => 'mariano'), 'Tag' => array() ) ); $this->assertEquals($expected, $result); $this->assertTrue(empty($this->User->Article->hasAndBelongsToMany['Tag']['conditions'])); $result = $this->User->find('all', array('contain' => array( 'Article.Tag' => array('conditions' => array('created >=' => '2007-03-18 12:24')) ))); $this->assertTrue(Set::matches('/User[id=1]', $result)); $this->assertFalse(Set::matches('/Article[id=1]/Tag[id=1]', $result)); $this->assertTrue(Set::matches('/Article[id=1]/Tag[id=2]', $result)); $this->assertTrue(empty($this->User->Article->hasAndBelongsToMany['Tag']['conditions'])); $this->assertTrue(empty($this->User->Article->hasAndBelongsToMany['Tag']['order'])); $result = $this->User->find('all', array('contain' => array( 'Article.Tag' => array('order' => 'created DESC') ))); $this->assertTrue(Set::matches('/User[id=1]', $result)); $this->assertTrue(Set::matches('/Article[id=1]/Tag[id=1]', $result)); $this->assertTrue(Set::matches('/Article[id=1]/Tag[id=2]', $result)); $this->assertTrue(empty($this->User->Article->hasAndBelongsToMany['Tag']['order'])); } /** * testOtherFinds method * * @return void */ public function testOtherFinds() { $result = $this->Article->find('count'); $expected = 3; $this->assertEquals($expected, $result); $result = $this->Article->find('count', array('conditions' => array('Article.id >' => '1'))); $expected = 2; $this->assertEquals($expected, $result); $result = $this->Article->find('count', array('contain' => array())); $expected = 3; $this->assertEquals($expected, $result); $this->Article->contain(array('User(id,user)', 'Tag' => array('fields' => array('tag', 'created'), 'conditions' => array('created >=' => '2007-03-18 12:24')))); $result = $this->Article->find('first', array('fields' => array('title'))); $expected = array( 'Article' => array('id' => 1, 'title' => 'First Article'), 'User' => array('id' => 1, 'user' => 'mariano'), 'Tag' => array(array('tag' => 'tag2', 'created' => '2007-03-18 12:24:23')) ); $this->assertEquals($expected, $result); $this->Article->contain(array('User(id,user)', 'Tag' => array('fields' => array('tag', 'created')))); $result = $this->Article->find('first', array('fields' => array('title'))); $expected = array( 'Article' => array('id' => 1, 'title' => 'First Article'), 'User' => array('id' => 1, 'user' => 'mariano'), 'Tag' => array( array('tag' => 'tag1', 'created' => '2007-03-18 12:22:23'), array('tag' => 'tag2', 'created' => '2007-03-18 12:24:23') ) ); $this->assertEquals($expected, $result); $result = $this->Article->find('first', array( 'fields' => array('title'), 'order' => 'Article.id DESC', 'contain' => array('User(id,user)', 'Tag' => array('fields' => array('tag', 'created'))) )); $expected = array( 'Article' => array('id' => 3, 'title' => 'Third Article'), 'User' => array('id' => 1, 'user' => 'mariano'), 'Tag' => array() ); $this->assertEquals($expected, $result); $result = $this->Article->find('list', array( 'contain' => array('User(id,user)'), 'fields' => array('Article.id', 'Article.title') )); $expected = array( 1 => 'First Article', 2 => 'Second Article', 3 => 'Third Article' ); $this->assertEquals($expected, $result); } /** * testOriginalAssociations method * * @return void */ public function testOriginalAssociations() { $this->Article->Comment->Behaviors->load('Containable'); $options = array( 'conditions' => array( 'Comment.published' => 'Y', ), 'contain' => 'User', 'recursive' => 1 ); $firstResult = $this->Article->Comment->find('all', $options); $this->Article->Comment->find('all', array( 'conditions' => array( 'User.user' => 'mariano' ), 'fields' => array('User.password'), 'contain' => array('User.password'), )); $result = $this->Article->Comment->find('all', $options); $this->assertEquals($firstResult, $result); $this->Article->unbindModel(array('hasMany' => array('Comment'), 'belongsTo' => array('User'), 'hasAndBelongsToMany' => array('Tag')), false); $this->Article->bindModel(array('hasMany' => array('Comment'), 'belongsTo' => array('User')), false); $r = $this->Article->find('all', array('contain' => array('Comment(comment)', 'User(user)'), 'fields' => array('title'))); $this->assertTrue(Set::matches('/Article[id=1]', $r)); $this->assertTrue(Set::matches('/User[id=1]', $r)); $this->assertTrue(Set::matches('/Comment[article_id=1]', $r)); $this->assertFalse(Set::matches('/Comment[id=1]', $r)); $r = $this->Article->find('all'); $this->assertTrue(Set::matches('/Article[id=1]', $r)); $this->assertTrue(Set::matches('/User[id=1]', $r)); $this->assertTrue(Set::matches('/Comment[article_id=1]', $r)); $this->assertTrue(Set::matches('/Comment[id=1]', $r)); $this->Article->bindModel(array('hasAndBelongsToMany' => array('Tag')), false); $this->Article->contain(false, array('User(id,user)', 'Comment' => array('fields' => array('comment'), 'conditions' => array('created >=' => '2007-03-18 10:49')))); $result = $this->Article->find('all', array('fields' => array('title'), 'limit' => 1, 'page' => 1, 'order' => 'Article.id ASC')); $expected = array(array( 'Article' => array('id' => 1, 'title' => 'First Article'), 'User' => array('id' => 1, 'user' => 'mariano'), 'Comment' => array( array('comment' => 'Third Comment for First Article', 'article_id' => 1), array('comment' => 'Fourth Comment for First Article', 'article_id' => 1) ) )); $this->assertEquals($expected, $result); $result = $this->Article->find('all', array('fields' => array('title', 'User.id', 'User.user'), 'limit' => 1, 'page' => 2, 'order' => 'Article.id ASC')); $expected = array(array( 'Article' => array('id' => 2, 'title' => 'Second Article'), 'User' => array('id' => 3, 'user' => 'larry'), 'Comment' => array( array('comment' => 'First Comment for Second Article', 'article_id' => 2), array('comment' => 'Second Comment for Second Article', 'article_id' => 2) ) )); $this->assertEquals($expected, $result); $result = $this->Article->find('all', array('fields' => array('title', 'User.id', 'User.user'), 'limit' => 1, 'page' => 3, 'order' => 'Article.id ASC')); $expected = array(array( 'Article' => array('id' => 3, 'title' => 'Third Article'), 'User' => array('id' => 1, 'user' => 'mariano'), 'Comment' => array() )); $this->assertEquals($expected, $result); $this->Article->contain(false, array('User' => array('fields' => 'user'), 'Comment')); $result = $this->Article->find('all'); $this->assertTrue(Set::matches('/Article[id=1]', $result)); $this->assertTrue(Set::matches('/User[user=mariano]', $result)); $this->assertTrue(Set::matches('/Comment[article_id=1]', $result)); $this->Article->resetBindings(); $this->Article->contain(false, array('User' => array('fields' => array('user')), 'Comment')); $result = $this->Article->find('all'); $this->assertTrue(Set::matches('/Article[id=1]', $result)); $this->assertTrue(Set::matches('/User[user=mariano]', $result)); $this->assertTrue(Set::matches('/Comment[article_id=1]', $result)); $this->Article->resetBindings(); } /** * testResetAddedAssociation method * * @return void */ public function testResetAddedAssociation() { $this->assertTrue(empty($this->Article->hasMany['ArticlesTag'])); $this->Article->bindModel(array( 'hasMany' => array('ArticlesTag') )); $this->assertTrue(!empty($this->Article->hasMany['ArticlesTag'])); $result = $this->Article->find('first', array( 'conditions' => array('Article.id' => 1), 'contain' => array('ArticlesTag') )); $expected = array('Article', 'ArticlesTag'); $this->assertTrue(!empty($result)); $this->assertEquals('First Article', $result['Article']['title']); $this->assertTrue(!empty($result['ArticlesTag'])); $this->assertEquals($expected, array_keys($result)); $this->assertTrue(empty($this->Article->hasMany['ArticlesTag'])); $this->JoinA = ClassRegistry::init('JoinA'); $this->JoinB = ClassRegistry::init('JoinB'); $this->JoinC = ClassRegistry::init('JoinC'); $this->JoinA->Behaviors->load('Containable'); $this->JoinB->Behaviors->load('Containable'); $this->JoinC->Behaviors->load('Containable'); $this->JoinA->JoinB->find('all', array('contain' => array('JoinA'))); $this->JoinA->bindModel(array('hasOne' => array('JoinAsJoinC' => array('joinTable' => 'as_cs'))), false); $result = $this->JoinA->hasOne; $this->JoinA->find('all'); $resultAfter = $this->JoinA->hasOne; $this->assertEquals($result, $resultAfter); } /** * testResetAssociation method * * @return void */ public function testResetAssociation() { $this->Article->Behaviors->load('Containable'); $this->Article->Comment->Behaviors->load('Containable'); $this->Article->User->Behaviors->load('Containable'); $initialOptions = array( 'conditions' => array( 'Comment.published' => 'Y', ), 'contain' => 'User', 'recursive' => 1, ); $initialModels = $this->Article->Comment->find('all', $initialOptions); $findOptions = array( 'conditions' => array( 'User.user' => 'mariano', ), 'fields' => array('User.password'), 'contain' => array('User.password') ); $result = $this->Article->Comment->find('all', $findOptions); $result = $this->Article->Comment->find('all', $initialOptions); $this->assertEquals($initialModels, $result); } /** * testResetDeeperHasOneAssociations method * * @return void */ public function testResetDeeperHasOneAssociations() { $this->Article->User->unbindModel(array( 'hasMany' => array('ArticleFeatured', 'Comment') ), false); $userHasOne = array('hasOne' => array('ArticleFeatured', 'Comment')); $this->Article->User->bindModel($userHasOne, false); $expected = $this->Article->User->hasOne; $this->Article->find('all'); $this->assertEquals($expected, $this->Article->User->hasOne); $this->Article->User->bindModel($userHasOne, false); $expected = $this->Article->User->hasOne; $this->Article->find('all', array( 'contain' => array( 'User' => array('ArticleFeatured', 'Comment') ) )); $this->assertEquals($expected, $this->Article->User->hasOne); $this->Article->User->bindModel($userHasOne, false); $expected = $this->Article->User->hasOne; $this->Article->find('all', array( 'contain' => array( 'User' => array( 'ArticleFeatured', 'Comment' => array('fields' => array('created')) ) ) )); $this->assertEquals($expected, $this->Article->User->hasOne); $this->Article->User->bindModel($userHasOne, false); $expected = $this->Article->User->hasOne; $this->Article->find('all', array( 'contain' => array( 'User' => array( 'Comment' => array('fields' => array('created')) ) ) )); $this->assertEquals($expected, $this->Article->User->hasOne); $this->Article->User->bindModel($userHasOne, false); $expected = $this->Article->User->hasOne; $this->Article->find('all', array( 'contain' => array( 'User.ArticleFeatured' => array( 'conditions' => array('ArticleFeatured.published' => 'Y') ), 'User.Comment' ) )); $this->assertEquals($expected, $this->Article->User->hasOne); } /** * testResetMultipleHabtmAssociations method * * @return void */ public function testResetMultipleHabtmAssociations() { $articleHabtm = array( 'hasAndBelongsToMany' => array( 'Tag' => array( 'className' => 'Tag', 'joinTable' => 'articles_tags', 'foreignKey' => 'article_id', 'associationForeignKey' => 'tag_id' ), 'ShortTag' => array( 'className' => 'Tag', 'joinTable' => 'articles_tags', 'foreignKey' => 'article_id', 'associationForeignKey' => 'tag_id', // LENGTH function mysql-only, using LIKE does almost the same 'conditions' => "ShortTag.tag LIKE '???'" ) ) ); $this->Article->resetBindings(); $this->Article->bindModel($articleHabtm, false); $expected = $this->Article->hasAndBelongsToMany; $this->Article->find('all'); $this->assertEquals($expected, $this->Article->hasAndBelongsToMany); $this->Article->resetBindings(); $this->Article->bindModel($articleHabtm, false); $expected = $this->Article->hasAndBelongsToMany; $this->Article->find('all', array('contain' => 'Tag.tag')); $this->assertEquals($expected, $this->Article->hasAndBelongsToMany); $this->Article->resetBindings(); $this->Article->bindModel($articleHabtm, false); $expected = $this->Article->hasAndBelongsToMany; $this->Article->find('all', array('contain' => 'Tag')); $this->assertEquals($expected, $this->Article->hasAndBelongsToMany); $this->Article->resetBindings(); $this->Article->bindModel($articleHabtm, false); $expected = $this->Article->hasAndBelongsToMany; $this->Article->find('all', array('contain' => array('Tag' => array('fields' => array(null))))); $this->assertEquals($expected, $this->Article->hasAndBelongsToMany); $this->Article->resetBindings(); $this->Article->bindModel($articleHabtm, false); $expected = $this->Article->hasAndBelongsToMany; $this->Article->find('all', array('contain' => array('Tag' => array('fields' => array('Tag.tag'))))); $this->assertEquals($expected, $this->Article->hasAndBelongsToMany); $this->Article->resetBindings(); $this->Article->bindModel($articleHabtm, false); $expected = $this->Article->hasAndBelongsToMany; $this->Article->find('all', array('contain' => array('Tag' => array('fields' => array('Tag.tag', 'Tag.created'))))); $this->assertEquals($expected, $this->Article->hasAndBelongsToMany); $this->Article->resetBindings(); $this->Article->bindModel($articleHabtm, false); $expected = $this->Article->hasAndBelongsToMany; $this->Article->find('all', array('contain' => 'ShortTag.tag')); $this->assertEquals($expected, $this->Article->hasAndBelongsToMany); $this->Article->resetBindings(); $this->Article->bindModel($articleHabtm, false); $expected = $this->Article->hasAndBelongsToMany; $this->Article->find('all', array('contain' => 'ShortTag')); $this->assertEquals($expected, $this->Article->hasAndBelongsToMany); $this->Article->resetBindings(); $this->Article->bindModel($articleHabtm, false); $expected = $this->Article->hasAndBelongsToMany; $this->Article->find('all', array('contain' => array('ShortTag' => array('fields' => array(null))))); $this->assertEquals($expected, $this->Article->hasAndBelongsToMany); $this->Article->resetBindings(); $this->Article->bindModel($articleHabtm, false); $expected = $this->Article->hasAndBelongsToMany; $this->Article->find('all', array('contain' => array('ShortTag' => array('fields' => array('ShortTag.tag'))))); $this->assertEquals($expected, $this->Article->hasAndBelongsToMany); $this->Article->resetBindings(); $this->Article->bindModel($articleHabtm, false); $expected = $this->Article->hasAndBelongsToMany; $this->Article->find('all', array('contain' => array('ShortTag' => array('fields' => array('ShortTag.tag', 'ShortTag.created'))))); $this->assertEquals($expected, $this->Article->hasAndBelongsToMany); } /** * test that bindModel and unbindModel work with find() calls in between. * * @return void */ public function testBindMultipleTimesWithFind() { $binding = array( 'hasOne' => array( 'ArticlesTag' => array( 'foreignKey' => false, 'type' => 'INNER', 'conditions' => array( 'ArticlesTag.article_id = Article.id' ) ), 'Tag' => array( 'type' => 'INNER', 'foreignKey' => false, 'conditions' => array( 'ArticlesTag.tag_id = Tag.id' ) ) ) ); $this->Article->unbindModel(array('hasAndBelongsToMany' => array('Tag'))); $this->Article->bindModel($binding); $result = $this->Article->find('all', array('limit' => 1, 'contain' => array('ArticlesTag', 'Tag'))); $this->Article->unbindModel(array('hasAndBelongsToMany' => array('Tag'))); $this->Article->bindModel($binding); $result = $this->Article->find('all', array('limit' => 1, 'contain' => array('ArticlesTag', 'Tag'))); $associated = $this->Article->getAssociated(); $this->assertEquals('hasAndBelongsToMany', $associated['Tag']); $this->assertFalse(isset($associated['ArticleTag'])); } /** * test that autoFields doesn't splice in fields from other databases. * * @return void */ public function testAutoFieldsWithMultipleDatabases() { $config = new DATABASE_CONFIG(); $this->skipIf( !isset($config->test) || !isset($config->test2), 'Primary and secondary test databases not configured, ' . 'skipping cross-database join tests. ' . ' To run these tests, you must define $test and $test2 ' . 'in your database configuration.' ); $db = ConnectionManager::getDataSource('test2'); $this->fixtureManager->loadSingle('User', $db); $this->Article->User->setDataSource('test2'); $result = $this->Article->find('all', array( 'fields' => array('Article.title'), 'contain' => array('User') )); $this->assertTrue(isset($result[0]['Article'])); $this->assertTrue(isset($result[0]['User'])); } /** * test that autoFields doesn't splice in columns that aren't part of the join. * * @return void */ public function testAutoFieldsWithRecursiveNegativeOne() { $this->Article->recursive = -1; $result = $this->Article->field('title', array('Article.title' => 'First Article')); $this->assertNoErrors(); $this->assertEquals('First Article', $result, 'Field is wrong'); } /** * test that find(all) doesn't return incorrect values when mixed with containable. * * @return void */ public function testFindAllReturn() { $result = $this->Article->find('all', array( 'conditions' => array('Article.id' => 999999999) )); $this->assertEmpty($result, 'Should be empty.'); } /** * testLazyLoad method * * @return void */ public function testLazyLoad() { // Local set up $this->User = ClassRegistry::init('User'); $this->User->bindModel(array( 'hasMany' => array('Article', 'ArticleFeatured', 'Comment') ), false); try { $this->User->find('first', array( 'contain' => 'Comment', 'lazyLoad' => true )); } catch (Exception $e) { $exceptions = true; } $this->assertTrue(empty($exceptions)); } /** * _containments method * * @param Model $Model * @param array $contain * @return void */ protected function _containments($Model, $contain = array()) { if (!is_array($Model)) { $result = $Model->containments($contain); return $this->_containments($result['models']); } $result = $Model; foreach ($result as $i => $containment) { $result[$i] = array_diff_key($containment, array('instance' => true)); } return $result; } /** * _assertBindings method * * @param Model $Model * @param array $expected * @return void */ protected function _assertBindings(Model $Model, $expected = array()) { $expected = array_merge(array( 'belongsTo' => array(), 'hasOne' => array(), 'hasMany' => array(), 'hasAndBelongsToMany' => array() ), $expected); foreach ($expected as $binding => $expect) { $this->assertEquals($expect, array_keys($Model->$binding)); } } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Behavior/TranslateBehaviorTest.php000066400000000000000000001240561265552240500261420ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @since CakePHP(tm) v 1.2.0.5669 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Model', 'Model'); App::uses('AppModel', 'Model'); require_once dirname(dirname(__FILE__)) . DS . 'models.php'; /** * TranslateBehaviorTest class * * @package Cake.Test.Case.Model.Behavior */ class TranslateBehaviorTest extends CakeTestCase { /** * autoFixtures property * * @var bool */ public $autoFixtures = false; /** * fixtures property * * @var array */ public $fixtures = array( 'core.translated_item', 'core.translate', 'core.translate_table', 'core.translated_article', 'core.translate_article', 'core.user', 'core.comment', 'core.tag', 'core.articles_tag', 'core.translate_with_prefix' ); /** * Test that count queries with conditions get the correct joins * * @return void */ public function testCountWithConditions() { $this->loadFixtures('Translate', 'TranslatedItem'); $Model = new TranslatedItem(); $Model->locale = 'eng'; $result = $Model->find('count', array( 'conditions' => array( 'I18n__content.locale' => 'eng' ) )); $this->assertEquals(3, $result); } /** * testTranslateModel method * * @return void */ public function testTranslateModel() { $this->loadFixtures('TranslateTable', 'Tag', 'TranslatedItem', 'Translate', 'User', 'TranslatedArticle', 'TranslateArticle'); $TestModel = new Tag(); $TestModel->translateTable = 'another_i18n'; $TestModel->Behaviors->load('Translate', array('title')); $translateModel = $TestModel->Behaviors->Translate->translateModel($TestModel); $this->assertEquals('I18nModel', $translateModel->name); $this->assertEquals('another_i18n', $translateModel->useTable); $TestModel = new User(); $TestModel->Behaviors->load('Translate', array('title')); $translateModel = $TestModel->Behaviors->Translate->translateModel($TestModel); $this->assertEquals('I18nModel', $translateModel->name); $this->assertEquals('i18n', $translateModel->useTable); $TestModel = new TranslatedArticle(); $translateModel = $TestModel->Behaviors->Translate->translateModel($TestModel); $this->assertEquals('TranslateArticleModel', $translateModel->name); $this->assertEquals('article_i18n', $translateModel->useTable); $TestModel = new TranslatedItem(); $translateModel = $TestModel->Behaviors->Translate->translateModel($TestModel); $this->assertEquals('TranslateTestModel', $translateModel->name); $this->assertEquals('i18n', $translateModel->useTable); } /** * testLocaleFalsePlain method * * @return void */ public function testLocaleFalsePlain() { $this->loadFixtures('Translate', 'TranslatedItem', 'User'); $TestModel = new TranslatedItem(); $TestModel->locale = false; $result = $TestModel->read(null, 1); $expected = array('TranslatedItem' => array( 'id' => 1, 'slug' => 'first_translated', 'translated_article_id' => 1, )); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array('fields' => array('slug'))); $expected = array( array('TranslatedItem' => array('slug' => 'first_translated')), array('TranslatedItem' => array('slug' => 'second_translated')), array('TranslatedItem' => array('slug' => 'third_translated')) ); $this->assertEquals($expected, $result); } /** * testLocaleFalseAssociations method * * @return void */ public function testLocaleFalseAssociations() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = false; $TestModel->unbindTranslation(); $translations = array('title' => 'Title', 'content' => 'Content'); $TestModel->bindTranslation($translations, false); $result = $TestModel->read(null, 1); $expected = array( 'TranslatedItem' => array('id' => 1, 'slug' => 'first_translated', 'translated_article_id' => 1), 'Title' => array( array('id' => 1, 'locale' => 'eng', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'title', 'content' => 'Title #1'), array('id' => 3, 'locale' => 'deu', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'title', 'content' => 'Titel #1'), array('id' => 5, 'locale' => 'cze', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'title', 'content' => 'Titulek #1') ), 'Content' => array( array('id' => 2, 'locale' => 'eng', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'content', 'content' => 'Content #1'), array('id' => 4, 'locale' => 'deu', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'content', 'content' => 'Inhalt #1'), array('id' => 6, 'locale' => 'cze', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'content', 'content' => 'Obsah #1') ) ); $this->assertEquals($expected, $result); $TestModel->hasMany['Title']['fields'] = $TestModel->hasMany['Content']['fields'] = array('content'); $TestModel->hasMany['Title']['conditions']['locale'] = $TestModel->hasMany['Content']['conditions']['locale'] = 'eng'; $result = $TestModel->find('all', array('fields' => array('TranslatedItem.slug'))); $expected = array( array( 'TranslatedItem' => array('id' => 1, 'slug' => 'first_translated'), 'Title' => array(array('foreign_key' => 1, 'content' => 'Title #1')), 'Content' => array(array('foreign_key' => 1, 'content' => 'Content #1')) ), array( 'TranslatedItem' => array('id' => 2, 'slug' => 'second_translated'), 'Title' => array(array('foreign_key' => 2, 'content' => 'Title #2')), 'Content' => array(array('foreign_key' => 2, 'content' => 'Content #2')) ), array( 'TranslatedItem' => array('id' => 3, 'slug' => 'third_translated'), 'Title' => array(array('foreign_key' => 3, 'content' => 'Title #3')), 'Content' => array(array('foreign_key' => 3, 'content' => 'Content #3')) ) ); $this->assertEquals($expected, $result); } /** * testLocaleSingle method * * @return void */ public function testLocaleSingle() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'eng'; $result = $TestModel->read(null, 1); $expected = array( 'TranslatedItem' => array( 'id' => 1, 'slug' => 'first_translated', 'locale' => 'eng', 'title' => 'Title #1', 'content' => 'Content #1', 'translated_article_id' => 1, ) ); $this->assertEquals($expected, $result); $result = $TestModel->find('all'); $expected = array( array( 'TranslatedItem' => array( 'id' => 1, 'slug' => 'first_translated', 'locale' => 'eng', 'title' => 'Title #1', 'content' => 'Content #1', 'translated_article_id' => 1, ) ), array( 'TranslatedItem' => array( 'id' => 2, 'slug' => 'second_translated', 'locale' => 'eng', 'title' => 'Title #2', 'content' => 'Content #2', 'translated_article_id' => 1, ) ), array( 'TranslatedItem' => array( 'id' => 3, 'slug' => 'third_translated', 'locale' => 'eng', 'title' => 'Title #3', 'content' => 'Content #3', 'translated_article_id' => 1, ) ) ); $this->assertEquals($expected, $result); $result = $TestModel->field('title', array('TranslatedItem.id' => 1)); $expected = 'Title #1'; $this->assertEquals($expected, $result); $result = $TestModel->read('title', 1); $expected = array( 'TranslatedItem' => array( 'id' => 1, 'slug' => 'first_translated', 'locale' => 'eng', 'title' => 'Title #1', 'translated_article_id' => 1, ) ); $this->assertEquals($expected, $result); $result = $TestModel->read('id, title', 1); $expected = array( 'TranslatedItem' => array( 'id' => 1, 'locale' => 'eng', 'title' => 'Title #1', ) ); $this->assertEquals($expected, $result); } /** * testLocaleSingleWithConditions method * * @return void */ public function testLocaleSingleWithConditions() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'eng'; $result = $TestModel->find('all', array('conditions' => array('slug' => 'first_translated'))); $expected = array( array( 'TranslatedItem' => array( 'id' => 1, 'slug' => 'first_translated', 'locale' => 'eng', 'title' => 'Title #1', 'content' => 'Content #1', 'translated_article_id' => 1, ) ) ); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array('conditions' => "TranslatedItem.slug = 'first_translated'")); $expected = array( array( 'TranslatedItem' => array( 'id' => 1, 'slug' => 'first_translated', 'locale' => 'eng', 'title' => 'Title #1', 'content' => 'Content #1', 'translated_article_id' => 1, ) ) ); $this->assertEquals($expected, $result); } /** * testLocaleSingleCountWithConditions method * * @return void */ public function testLocaleSingleCountWithConditions() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'eng'; $result = $TestModel->find('all', array( 'conditions' => array('slug' => 'first_translated') )); $expected = array( array( 'TranslatedItem' => array( 'id' => 1, 'slug' => 'first_translated', 'locale' => 'eng', 'title' => 'Title #1', 'content' => 'Content #1', 'translated_article_id' => 1, ) ) ); $this->assertEquals($expected, $result); $result = $TestModel->find('count', array( 'conditions' => array('slug' => 'first_translated') )); $expected = 1; $this->assertEquals($expected, $result); } /** * testLocaleSingleAssociations method * * @return void */ public function testLocaleSingleAssociations() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'eng'; $TestModel->unbindTranslation(); $translations = array('title' => 'Title', 'content' => 'Content'); $TestModel->bindTranslation($translations, false); $result = $TestModel->read(null, 1); $expected = array( 'TranslatedItem' => array( 'id' => 1, 'slug' => 'first_translated', 'locale' => 'eng', 'title' => 'Title #1', 'content' => 'Content #1', 'translated_article_id' => 1, ), 'Title' => array( array('id' => 1, 'locale' => 'eng', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'title', 'content' => 'Title #1'), array('id' => 3, 'locale' => 'deu', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'title', 'content' => 'Titel #1'), array('id' => 5, 'locale' => 'cze', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'title', 'content' => 'Titulek #1') ), 'Content' => array( array('id' => 2, 'locale' => 'eng', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'content', 'content' => 'Content #1'), array('id' => 4, 'locale' => 'deu', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'content', 'content' => 'Inhalt #1'), array('id' => 6, 'locale' => 'cze', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'content', 'content' => 'Obsah #1') ) ); $this->assertEquals($expected, $result); $TestModel->hasMany['Title']['fields'] = $TestModel->hasMany['Content']['fields'] = array('content'); $TestModel->hasMany['Title']['conditions']['locale'] = $TestModel->hasMany['Content']['conditions']['locale'] = 'eng'; $result = $TestModel->find('all', array('fields' => array('TranslatedItem.title'))); $expected = array( array( 'TranslatedItem' => array( 'id' => 1, 'locale' => 'eng', 'title' => 'Title #1', 'slug' => 'first_translated', 'translated_article_id' => 1, ), 'Title' => array(array('foreign_key' => 1, 'content' => 'Title #1')), 'Content' => array(array('foreign_key' => 1, 'content' => 'Content #1')) ), array( 'TranslatedItem' => array( 'id' => 2, 'locale' => 'eng', 'title' => 'Title #2', 'slug' => 'second_translated', 'translated_article_id' => 1, ), 'Title' => array(array('foreign_key' => 2, 'content' => 'Title #2')), 'Content' => array(array('foreign_key' => 2, 'content' => 'Content #2')) ), array( 'TranslatedItem' => array( 'id' => 3, 'locale' => 'eng', 'title' => 'Title #3', 'slug' => 'third_translated', 'translated_article_id' => 1, ), 'Title' => array(array('foreign_key' => 3, 'content' => 'Title #3')), 'Content' => array(array('foreign_key' => 3, 'content' => 'Content #3')) ) ); $this->assertEquals($expected, $result); } /** * Test loading fields with 0 as the translated value. * * @return void */ public function testFetchTranslationsWithZero() { $this->loadFixtures('Translate', 'TranslatedItem'); $model = new TranslatedItem(); $translateModel = $model->translateModel(); $translateModel->updateAll(array('content' => "'0'")); $model->locale = 'eng'; $result = $model->read(null, 1); $expected = array( 'TranslatedItem' => array( 'id' => 1, 'slug' => 'first_translated', 'locale' => 'eng', 'title' => '0', 'content' => '0', 'translated_article_id' => 1, ) ); $this->assertEquals($expected, $result); } /** * testLocaleMultiple method * * @return void */ public function testLocaleMultiple() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = array('deu', 'eng', 'cze'); $result = $TestModel->read(null, 1); $expected = array( 'TranslatedItem' => array( 'id' => 1, 'slug' => 'first_translated', 'locale' => 'deu', 'title' => 'Titel #1', 'content' => 'Inhalt #1', 'translated_article_id' => 1, ) ); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array('fields' => array('slug', 'title', 'content'))); $expected = array( array( 'TranslatedItem' => array( 'slug' => 'first_translated', 'locale' => 'deu', 'content' => 'Inhalt #1', 'title' => 'Titel #1', ) ), array( 'TranslatedItem' => array( 'slug' => 'second_translated', 'locale' => 'deu', 'title' => 'Titel #2', 'content' => 'Inhalt #2', ) ), array( 'TranslatedItem' => array( 'slug' => 'third_translated', 'locale' => 'deu', 'title' => 'Titel #3', 'content' => 'Inhalt #3', ) ) ); $this->assertEquals($expected, $result); $TestModel = new TranslatedItem(); $TestModel->locale = array('pt-br'); $result = $TestModel->find('all'); $this->assertCount(3, $result, '3 records should have been found, no SQL error.'); } /** * testMissingTranslation method * * @return void */ public function testMissingTranslation() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'rus'; $result = $TestModel->read(null, 1); $this->assertSame(array(), $result); $TestModel->locale = array('rus'); $result = $TestModel->read(null, 1); $expected = array( 'TranslatedItem' => array( 'id' => 1, 'slug' => 'first_translated', 'locale' => 'rus', 'title' => '', 'content' => '', 'translated_article_id' => 1, ) ); $this->assertEquals($expected, $result); } /** * testTranslatedFindList method * * @return void */ public function testTranslatedFindList() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'deu'; $TestModel->displayField = 'title'; $result = $TestModel->find('list', array('recursive' => 1)); $expected = array(1 => 'Titel #1', 2 => 'Titel #2', 3 => 'Titel #3'); $this->assertEquals($expected, $result); // SQL Server trigger an error and stops the page even if the debug = 0 if ($this->db instanceof Sqlserver) { $debug = Configure::read('debug'); Configure::write('debug', 0); $result = $TestModel->find('list', array('recursive' => 1, 'callbacks' => false)); $this->assertSame(array(), $result); $result = $TestModel->find('list', array('recursive' => 1, 'callbacks' => 'after')); $this->assertSame(array(), $result); Configure::write('debug', $debug); } $result = $TestModel->find('list', array('recursive' => 1, 'callbacks' => 'before')); $expected = array(1 => null, 2 => null, 3 => null); $this->assertEquals($expected, $result); } /** * testReadSelectedFields method * * @return void */ public function testReadSelectedFields() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'eng'; $result = $TestModel->find('all', array('fields' => array('slug', 'TranslatedItem.content'))); $expected = array( array('TranslatedItem' => array('slug' => 'first_translated', 'locale' => 'eng', 'content' => 'Content #1')), array('TranslatedItem' => array('slug' => 'second_translated', 'locale' => 'eng', 'content' => 'Content #2')), array('TranslatedItem' => array('slug' => 'third_translated', 'locale' => 'eng', 'content' => 'Content #3')) ); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array('fields' => array('TranslatedItem.slug', 'content'))); $this->assertEquals($expected, $result); $TestModel->locale = array('eng', 'deu', 'cze'); $delete = array(array('locale' => 'deu'), array('field' => 'content', 'locale' => 'eng')); $I18nModel = ClassRegistry::getObject('TranslateTestModel'); $I18nModel->deleteAll(array('or' => $delete)); $result = $TestModel->find('all', array('fields' => array('title', 'content'))); $expected = array( array('TranslatedItem' => array('locale' => 'eng', 'title' => 'Title #1', 'content' => 'Obsah #1')), array('TranslatedItem' => array('locale' => 'eng', 'title' => 'Title #2', 'content' => 'Obsah #2')), array('TranslatedItem' => array('locale' => 'eng', 'title' => 'Title #3', 'content' => 'Obsah #3')) ); $this->assertEquals($expected, $result); } /** * testSaveCreate method * * @return void */ public function testSaveCreate() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'spa'; $data = array( 'slug' => 'fourth_translated', 'title' => 'Leyenda #4', 'content' => 'Contenido #4', 'translated_article_id' => 1, ); $TestModel->create($data); $TestModel->save(); $result = $TestModel->read(); $expected = array('TranslatedItem' => array_merge($data, array('id' => $TestModel->id, 'locale' => 'spa'))); $this->assertEquals($expected, $result); } /** * test saving/deleting with an alias, uses the model name. * * @return void */ public function testSaveDeleteIgnoreAlias() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(array('alias' => 'SomethingElse')); $TestModel->locale = 'spa'; $data = array( 'slug' => 'fourth_translated', 'title' => 'Leyenda #4', 'content' => 'Contenido #4', 'translated_article_id' => 1, ); $TestModel->create($data); $TestModel->save(); $id = $TestModel->id; $result = $TestModel->read(); $expected = array($TestModel->alias => array_merge($data, array('id' => $id, 'locale' => 'spa'))); $this->assertEquals($expected, $result); $TestModel->delete($id); $result = $TestModel->translateModel()->find('count', array( 'conditions' => array('foreign_key' => $id) )); $this->assertEquals(0, $result); } /** * test save multiple locales method * * @return void */ public function testSaveMultipleLocales() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $data = array( 'slug' => 'fourth_translated', 'title' => array( 'eng' => 'Title #4', 'spa' => 'Leyenda #4', ), 'content' => array( 'eng' => 'Content #4', 'spa' => 'Contenido #4', ), 'translated_article_id' => 1, ); $TestModel->create(); $TestModel->save($data); $translations = array('title' => 'Title', 'content' => 'Content'); $TestModel->bindTranslation($translations, false); $TestModel->locale = array('eng', 'spa'); $result = $TestModel->read(); $this->assertCount(2, $result['Title']); $this->assertEquals($result['Title'][0]['locale'], 'eng'); $this->assertEquals($result['Title'][0]['content'], 'Title #4'); $this->assertEquals($result['Title'][1]['locale'], 'spa'); $this->assertEquals($result['Title'][1]['content'], 'Leyenda #4'); $this->assertCount(2, $result['Content']); } /** * testSaveAssociatedCreate method * * @return void */ public function testSaveAssociatedMultipleLocale() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $data = array( 'slug' => 'fourth_translated', 'title' => array( 'eng' => 'Title #4', 'spa' => 'Leyenda #4', ), 'content' => array( 'eng' => 'Content #4', 'spa' => 'Contenido #4', ), 'translated_article_id' => 1, ); $TestModel->create(); $TestModel->saveAssociated($data); $translations = array('title' => 'Title', 'content' => 'Content'); $TestModel->bindTranslation($translations, false); $TestModel->locale = array('eng', 'spa'); $result = $TestModel->read(); $this->assertCount(2, $result['Title']); $this->assertCount(2, $result['Content']); } /** * testSaveAssociatedAtomic method * * @return void */ public function testSaveAssociatedAtomic() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $data = array( 'slug' => 'fourth_translated', 'title' => array( 'eng' => 'Title #4' ), 'content' => array( 'eng' => 'Content #4' ), 'translated_article_id' => 1, ); $Mock = $this->getMockForModel('TranslateTestModel', array('save')); $TestModel->Behaviors->Translate->runtime[$TestModel->alias]['model'] = $Mock; $with = array( 'TranslateTestModel' => array ( 'model' => 'TranslatedItem', 'foreign_key' => '4', 'field' => 'content', 'locale' => 'eng', 'content' => 'Content #4', ) ); $Mock->expects($this->at(0))->method('save')->with($with, array('atomic' => false)); $with = array( 'TranslateTestModel' => array ( 'model' => 'TranslatedItem', 'foreign_key' => '4', 'field' => 'title', 'locale' => 'eng', 'content' => 'Title #4', ) ); $Mock->expects($this->at(1))->method('save')->with($with, array('atomic' => false)); $TestModel->create(); $TestModel->saveAssociated($data, array('atomic' => false)); } /** * Test that saving only some of the translated fields allows the record to be found again. * * @return void */ public function testSavePartialFields() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'spa'; $data = array( 'slug' => 'fourth_translated', 'title' => 'Leyenda #4', ); $TestModel->create($data); $TestModel->save(); $result = $TestModel->read(); $expected = array( 'TranslatedItem' => array( 'id' => $TestModel->id, 'translated_article_id' => null, 'locale' => 'spa', 'content' => '', ) + $data ); $this->assertEquals($expected, $result); } /** * Test that all fields are create with partial data + multiple locales. * * @return void */ public function testSavePartialFieldMultipleLocales() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'eng'; $data = array( 'slug' => 'fifth_translated', 'title' => array('eng' => 'Title #5', 'spa' => 'Leyenda #5'), ); $TestModel->create($data); $TestModel->save(); $TestModel->unbindTranslation(); $translations = array('title' => 'Title', 'content' => 'Content'); $TestModel->bindTranslation($translations, false); $result = $TestModel->read(null, $TestModel->id); $expected = array( 'TranslatedItem' => array( 'id' => '4', 'translated_article_id' => null, 'slug' => 'fifth_translated', 'locale' => 'eng', 'title' => 'Title #5', 'content' => '' ), 'Title' => array( 0 => array( 'id' => '19', 'locale' => 'eng', 'model' => 'TranslatedItem', 'foreign_key' => '4', 'field' => 'title', 'content' => 'Title #5' ), 1 => array( 'id' => '20', 'locale' => 'spa', 'model' => 'TranslatedItem', 'foreign_key' => '4', 'field' => 'title', 'content' => 'Leyenda #5' ) ), 'Content' => array( 0 => array( 'id' => '21', 'locale' => 'eng', 'model' => 'TranslatedItem', 'foreign_key' => '4', 'field' => 'content', 'content' => '' ), 1 => array( 'id' => '22', 'locale' => 'spa', 'model' => 'TranslatedItem', 'foreign_key' => '4', 'field' => 'content', 'content' => '' ) ) ); $this->assertEquals($expected, $result); } /** * testSaveUpdate method * * @return void */ public function testSaveUpdate() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'spa'; $oldData = array('slug' => 'fourth_translated', 'title' => 'Leyenda #4', 'translated_article_id' => 1); $TestModel->create($oldData); $TestModel->save(); $id = $TestModel->id; $newData = array('id' => $id, 'content' => 'Contenido #4'); $TestModel->create($newData); $TestModel->save(); $result = $TestModel->read(null, $id); $expected = array('TranslatedItem' => array_merge($oldData, $newData, array('locale' => 'spa'))); $this->assertEquals($expected, $result); } /** * testMultipleCreate method * * @return void */ public function testMultipleCreate() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'deu'; $data = array( 'slug' => 'new_translated', 'title' => array('eng' => 'New title', 'spa' => 'Nuevo leyenda'), 'content' => array('eng' => 'New content', 'spa' => 'Nuevo contenido') ); $TestModel->create($data); $TestModel->save(); $TestModel->unbindTranslation(); $translations = array('title' => 'Title', 'content' => 'Content'); $TestModel->bindTranslation($translations, false); $TestModel->locale = array('eng', 'spa'); $result = $TestModel->read(); $expected = array( 'TranslatedItem' => array( 'id' => 4, 'slug' => 'new_translated', 'locale' => 'eng', 'title' => 'New title', 'content' => 'New content', 'translated_article_id' => null, ), 'Title' => array( array('id' => 21, 'locale' => 'eng', 'model' => 'TranslatedItem', 'foreign_key' => 4, 'field' => 'title', 'content' => 'New title'), array('id' => 22, 'locale' => 'spa', 'model' => 'TranslatedItem', 'foreign_key' => 4, 'field' => 'title', 'content' => 'Nuevo leyenda') ), 'Content' => array( array('id' => 19, 'locale' => 'eng', 'model' => 'TranslatedItem', 'foreign_key' => 4, 'field' => 'content', 'content' => 'New content'), array('id' => 20, 'locale' => 'spa', 'model' => 'TranslatedItem', 'foreign_key' => 4, 'field' => 'content', 'content' => 'Nuevo contenido') ) ); $this->assertEquals($expected, $result); } /** * testMultipleUpdate method * * @return void */ public function testMultipleUpdate() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'eng'; $TestModel->validate['title'] = 'notBlank'; $data = array('TranslatedItem' => array( 'id' => 1, 'title' => array('eng' => 'New Title #1', 'deu' => 'Neue Titel #1', 'cze' => 'Novy Titulek #1'), 'content' => array('eng' => 'New Content #1', 'deu' => 'Neue Inhalt #1', 'cze' => 'Novy Obsah #1') )); $TestModel->create(); $TestModel->save($data); $TestModel->unbindTranslation(); $translations = array('title' => 'Title', 'content' => 'Content'); $TestModel->bindTranslation($translations, false); $result = $TestModel->read(null, 1); $expected = array( 'TranslatedItem' => array( 'id' => '1', 'slug' => 'first_translated', 'locale' => 'eng', 'title' => 'New Title #1', 'content' => 'New Content #1', 'translated_article_id' => 1, ), 'Title' => array( array('id' => 1, 'locale' => 'eng', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'title', 'content' => 'New Title #1'), array('id' => 3, 'locale' => 'deu', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'title', 'content' => 'Neue Titel #1'), array('id' => 5, 'locale' => 'cze', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'title', 'content' => 'Novy Titulek #1') ), 'Content' => array( array('id' => 2, 'locale' => 'eng', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'content', 'content' => 'New Content #1'), array('id' => 4, 'locale' => 'deu', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'content', 'content' => 'Neue Inhalt #1'), array('id' => 6, 'locale' => 'cze', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'content', 'content' => 'Novy Obsah #1') ) ); $this->assertEquals($expected, $result); $TestModel->unbindTranslation($translations); $TestModel->bindTranslation(array('title', 'content'), false); } /** * testMixedCreateUpdateWithArrayLocale method * * @return void */ public function testMixedCreateUpdateWithArrayLocale() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = array('cze', 'deu'); $data = array('TranslatedItem' => array( 'id' => 1, 'title' => array('eng' => 'Updated Title #1', 'spa' => 'Nuevo leyenda #1'), 'content' => 'Upraveny obsah #1' )); $TestModel->create(); $TestModel->save($data); $TestModel->unbindTranslation(); $translations = array('title' => 'Title', 'content' => 'Content'); $TestModel->bindTranslation($translations, false); $result = $TestModel->read(null, 1); $result['Title'] = Hash::sort($result['Title'], '{n}.id', 'asc'); $result['Content'] = Hash::sort($result['Content'], '{n}.id', 'asc'); $expected = array( 'TranslatedItem' => array( 'id' => 1, 'slug' => 'first_translated', 'locale' => 'cze', 'title' => 'Titulek #1', 'content' => 'Upraveny obsah #1', 'translated_article_id' => 1, ), 'Title' => array( array('id' => 1, 'locale' => 'eng', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'title', 'content' => 'Updated Title #1'), array('id' => 3, 'locale' => 'deu', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'title', 'content' => 'Titel #1'), array('id' => 5, 'locale' => 'cze', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'title', 'content' => 'Titulek #1'), array('id' => 19, 'locale' => 'spa', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'title', 'content' => 'Nuevo leyenda #1') ), 'Content' => array( array('id' => 2, 'locale' => 'eng', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'content', 'content' => 'Content #1'), array('id' => 4, 'locale' => 'deu', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'content', 'content' => 'Inhalt #1'), array('id' => 6, 'locale' => 'cze', 'model' => 'TranslatedItem', 'foreign_key' => 1, 'field' => 'content', 'content' => 'Upraveny obsah #1') ) ); $this->assertEquals($expected, $result); } /** * Test that saveAll() works with hasMany associations that contain * translations. * * @return void */ public function testSaveAllTranslatedAssociations() { $this->loadFixtures('Translate', 'TranslateArticle', 'TranslatedItem', 'TranslatedArticle', 'User'); $Model = new TranslatedArticle(); $Model->locale = 'eng'; $data = array( 'TranslatedArticle' => array( 'id' => 4, 'user_id' => 1, 'published' => 'Y', 'title' => 'Title (eng) #1', 'body' => 'Body (eng) #1' ), 'TranslatedItem' => array( array( 'slug' => '', 'title' => 'Nuevo leyenda #1', 'content' => 'Upraveny obsah #1' ), array( 'slug' => '', 'title' => 'New Title #2', 'content' => 'New Content #2' ), ) ); $result = $Model->saveAll($data); $this->assertTrue($result); $result = $Model->TranslatedItem->find('all', array( 'conditions' => array('translated_article_id' => $Model->id) )); $this->assertCount(2, $result); $this->assertEquals($data['TranslatedItem'][0]['title'], $result[0]['TranslatedItem']['title']); $this->assertEquals($data['TranslatedItem'][1]['title'], $result[1]['TranslatedItem']['title']); } /** * testValidation method * * @return void */ public function testValidation() { Configure::write('Config.language', 'eng'); $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'eng'; $TestModel->validate['title'] = '/Only this title/'; $data = array( 'TranslatedItem' => array( 'id' => 1, 'title' => array('eng' => 'New Title #1', 'deu' => 'Neue Titel #1', 'cze' => 'Novy Titulek #1'), 'content' => array('eng' => 'New Content #1', 'deu' => 'Neue Inhalt #1', 'cze' => 'Novy Obsah #1') ) ); $TestModel->create(); $this->assertFalse($TestModel->save($data)); $this->assertEquals(array('This field cannot be left blank'), $TestModel->validationErrors['title']); $TestModel->locale = 'eng'; $TestModel->validate['title'] = '/Only this title/'; $data = array('TranslatedItem' => array( 'id' => 1, 'title' => array('eng' => 'Only this title', 'deu' => 'Neue Titel #1', 'cze' => 'Novy Titulek #1'), 'content' => array('eng' => 'New Content #1', 'deu' => 'Neue Inhalt #1', 'cze' => 'Novy Obsah #1') )); $TestModel->create(); $result = $TestModel->save($data); $this->assertFalse(empty($result)); } /** * test restoring fields after temporary binds method * * @return void */ public function testFieldsRestoreAfterBind() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $translations = array('title' => 'Title'); $TestModel->bindTranslation($translations); $result = $TestModel->find('first'); $this->assertArrayHasKey('Title', $result); $this->assertArrayHasKey('content', $result['Title'][0]); $this->assertArrayNotHasKey('title', $result); $result = $TestModel->find('first'); $this->assertArrayNotHasKey('Title', $result); $this->assertEquals('Title #1', $result['TranslatedItem']['title']); } /** * testAttachDetach method * * @return void */ public function testAttachDetach() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->unbindTranslation(); $translations = array('title' => 'Title', 'content' => 'Content'); $TestModel->bindTranslation($translations, false); $result = array_keys($TestModel->hasMany); $expected = array('Title', 'Content'); $this->assertEquals($expected, $result); $TestModel->Behaviors->unload('Translate'); $result = array_keys($TestModel->hasMany); $expected = array(); $this->assertEquals($expected, $result); $result = isset($TestModel->Behaviors->Translate); $this->assertFalse($result); $result = isset($Behavior->settings[$TestModel->alias]); $this->assertFalse($result); $result = isset($Behavior->runtime[$TestModel->alias]); $this->assertFalse($result); $TestModel->Behaviors->load('Translate', array('title' => 'Title', 'content' => 'Content')); $result = array_keys($TestModel->hasMany); $expected = array('Title', 'Content'); $this->assertEquals($expected, $result); $result = isset($TestModel->Behaviors->Translate); $this->assertTrue($result); $Behavior = $TestModel->Behaviors->Translate; $result = isset($Behavior->settings[$TestModel->alias]); $this->assertTrue($result); $result = isset($Behavior->runtime[$TestModel->alias]); $this->assertTrue($result); } /** * testAnotherTranslateTable method * * @return void */ public function testAnotherTranslateTable() { $this->loadFixtures('Translate', 'TranslatedItem', 'TranslateTable'); $TestModel = new TranslatedItemWithTable(); $TestModel->locale = 'eng'; $result = $TestModel->read(null, 1); $expected = array( 'TranslatedItemWithTable' => array( 'id' => 1, 'slug' => 'first_translated', 'locale' => 'eng', 'title' => 'Another Title #1', 'content' => 'Another Content #1', 'translated_article_id' => 1, ) ); $this->assertEquals($expected, $result); } /** * testTranslateWithAssociations method * * @return void */ public function testTranslateWithAssociations() { $this->loadFixtures('TranslateArticle', 'TranslatedArticle', 'TranslatedItem', 'User', 'Comment', 'ArticlesTag', 'Tag'); $TestModel = new TranslatedArticle(); $TestModel->locale = 'eng'; $recursive = $TestModel->recursive; $result = $TestModel->read(null, 1); $expected = array( 'TranslatedArticle' => array( 'id' => 1, 'user_id' => 1, 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'locale' => 'eng', 'title' => 'Title (eng) #1', 'body' => 'Body (eng) #1' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'TranslatedItem' => array( array( 'id' => 1, 'translated_article_id' => 1, 'slug' => 'first_translated' ), array( 'id' => 2, 'translated_article_id' => 1, 'slug' => 'second_translated' ), array( 'id' => 3, 'translated_article_id' => 1, 'slug' => 'third_translated' ), ) ); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array('recursive' => -1)); $expected = array( array( 'TranslatedArticle' => array( 'id' => 1, 'user_id' => 1, 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'locale' => 'eng', 'title' => 'Title (eng) #1', 'body' => 'Body (eng) #1' ) ), array( 'TranslatedArticle' => array( 'id' => 2, 'user_id' => 3, 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'locale' => 'eng', 'title' => 'Title (eng) #2', 'body' => 'Body (eng) #2' ) ), array( 'TranslatedArticle' => array( 'id' => 3, 'user_id' => 1, 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'locale' => 'eng', 'title' => 'Title (eng) #3', 'body' => 'Body (eng) #3' ) ) ); $this->assertEquals($expected, $result); $this->assertEquals($TestModel->recursive, $recursive); $TestModel->recursive = -1; $result = $TestModel->read(null, 1); $expected = array( 'TranslatedArticle' => array( 'id' => 1, 'user_id' => 1, 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'locale' => 'eng', 'title' => 'Title (eng) #1', 'body' => 'Body (eng) #1' ) ); $this->assertEquals($expected, $result); } /** * testTranslateTableWithPrefix method * Tests that is possible to have a translation model with a custom tablePrefix * * @return void */ public function testTranslateTableWithPrefix() { $this->loadFixtures('TranslateWithPrefix', 'TranslatedItem'); $TestModel = new TranslatedItem2; $TestModel->locale = 'eng'; $result = $TestModel->read(null, 1); $expected = array('TranslatedItem' => array( 'id' => 1, 'slug' => 'first_translated', 'locale' => 'eng', 'content' => 'Content #1', 'title' => 'Title #1', 'translated_article_id' => 1, )); $this->assertEquals($expected, $result); } /** * Test infinite loops not occurring with unbindTranslation() * * @return void */ public function testUnbindTranslationInfinteLoop() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->Behaviors->unload('Translate'); $TestModel->actsAs = array(); $TestModel->Behaviors->load('Translate'); $TestModel->bindTranslation(array('title', 'content'), true); $result = $TestModel->unbindTranslation(); $this->assertFalse($result); } /** * Test that an exception is raised when you try to over-write the name attribute. * * @expectedException CakeException * @return void */ public function testExceptionOnNameTranslation() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->bindTranslation(array('name' => 'name')); } /** * Test that translations can be bound and unbound dynamically. * * @return void */ public function testUnbindTranslation() { $this->loadFixtures('Translate', 'TranslatedItem'); $Model = new TranslatedItem(); $Model->unbindTranslation(); $Model->bindTranslation(array('body', 'slug'), false); $result = $Model->Behaviors->Translate->settings['TranslatedItem']; $this->assertEquals(array('body', 'slug'), $result); $Model->unbindTranslation(array('body')); $result = $Model->Behaviors->Translate->settings['TranslatedItem']; $this->assertNotContains('body', $result); $Model->unbindTranslation('slug'); $result = $Model->Behaviors->Translate->settings['TranslatedItem']; $this->assertNotContains('slug', $result); } /** * Test that additional records are not inserted for associated translations. * * @return void */ public function testNoExtraRowsForAssociatedTranslations() { $this->loadFixtures('Translate', 'TranslatedItem'); $TestModel = new TranslatedItem(); $TestModel->locale = 'spa'; $TestModel->unbindTranslation(); $TestModel->bindTranslation(array('name' => 'nameTranslate')); $data = array( 'TranslatedItem' => array( 'slug' => 'spanish-name', 'name' => 'Spanish name', ), ); $TestModel->create($data); $TestModel->save(); $Translate = $TestModel->translateModel(); $results = $Translate->find('all', array( 'conditions' => array( 'locale' => $TestModel->locale, 'foreign_key' => $TestModel->id ) )); $this->assertCount(1, $results, 'Only one field should be saved'); $this->assertEquals('name', $results[0]['TranslateTestModel']['field']); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Behavior/TreeBehaviorAfterTest.php000066400000000000000000000041761265552240500260660ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model.Behavior * @since CakePHP(tm) v 1.2.0.5330 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Model', 'Model'); App::uses('AppModel', 'Model'); require_once dirname(dirname(__FILE__)) . DS . 'models.php'; /** * TreeBehaviorAfterTest class * * @package Cake.Test.Case.Model.Behavior */ class TreeBehaviorAfterTest extends CakeTestCase { /** * Whether backup global state for each test method or not * * @var bool */ public $backupGlobals = false; /** * settings property * * @var array */ public $settings = array( 'modelClass' => 'AfterTree', 'leftField' => 'lft', 'rightField' => 'rght', 'parentField' => 'parent_id' ); /** * fixtures property * * @var array */ public $fixtures = array('core.after_tree'); /** * Tests the afterSave callback in the model * * @return void */ public function testAftersaveCallback() { $this->Tree = new AfterTree(); $this->Tree->order = null; $expected = array('AfterTree' => array('name' => 'Six and One Half Changed in AfterTree::afterSave() but not in database', 'parent_id' => 6, 'lft' => 11, 'rght' => 12)); $result = $this->Tree->save(array('AfterTree' => array('name' => 'Six and One Half', 'parent_id' => 6))); $expected['AfterTree']['id'] = $this->Tree->id; $this->assertEquals($expected, $result); $expected = array('AfterTree' => array('name' => 'Six and One Half', 'parent_id' => 6, 'lft' => 11, 'rght' => 12, 'id' => 8)); $result = $this->Tree->find('all'); $this->assertEquals($expected, $result[7]); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Behavior/TreeBehaviorNumberTest.php000066400000000000000000001410761265552240500262560ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model.Behavior * @since CakePHP(tm) v 1.2.0.5330 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Model', 'Model'); App::uses('AppModel', 'Model'); require_once dirname(dirname(__FILE__)) . DS . 'models.php'; /** * TreeBehaviorNumberTest class * * @package Cake.Test.Case.Model.Behavior */ class TreeBehaviorNumberTest extends CakeTestCase { /** * Whether backup global state for each test method or not * * @var bool */ public $backupGlobals = false; /** * settings property * * @var array */ public $settings = array( 'modelClass' => 'NumberTree', 'leftField' => 'lft', 'rightField' => 'rght', 'parentField' => 'parent_id', 'level' => 'level' ); /** * fixtures property * * @var array */ public $fixtures = array('core.number_tree', 'core.person'); /** * testInitialize method * * @return void */ public function testInitialize() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $result = $this->Tree->find('count'); $this->assertEquals(7, $result); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testDetectInvalidLeft method * * @return void */ public function testDetectInvalidLeft() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $result = $this->Tree->findByName('1.1'); $save[$modelClass]['id'] = $result[$modelClass]['id']; $save[$modelClass][$leftField] = 0; $this->Tree->create(); $this->Tree->save($save); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $result = $this->Tree->recover(); $this->assertTrue($result); $result = $this->Tree->verify(); $this->assertTrue($result); } /** * testDetectInvalidRight method * * @return void */ public function testDetectInvalidRight() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $result = $this->Tree->findByName('1.1'); $save[$modelClass]['id'] = $result[$modelClass]['id']; $save[$modelClass][$rightField] = 0; $this->Tree->create(); $this->Tree->save($save); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $result = $this->Tree->recover(); $this->assertTrue($result); $result = $this->Tree->verify(); $this->assertTrue($result); } /** * testDetectInvalidParent method * * @return void */ public function testDetectInvalidParent() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $result = $this->Tree->findByName('1.1'); // Bypass behavior and any other logic $this->Tree->updateAll(array($parentField => null), array('id' => $result[$modelClass]['id'])); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $result = $this->Tree->recover(); $this->assertTrue($result); $result = $this->Tree->verify(); $this->assertTrue($result); } /** * testDetectNoneExistentParent method * * @return void */ public function testDetectNoneExistentParent() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $result = $this->Tree->findByName('1.1'); $this->Tree->updateAll(array($parentField => 999999), array('id' => $result[$modelClass]['id'])); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $result = $this->Tree->recover('MPTT'); $this->assertTrue($result); $result = $this->Tree->verify(); $this->assertTrue($result); } /** * testRecoverUsingParentMode method * * @return void */ public function testRecoverUsingParentMode() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->Behaviors->disable('Tree'); $this->Tree->create(); $this->Tree->save(array('name' => 'Main', $parentField => null, $leftField => 0, $rightField => 0)); $node1 = $this->Tree->id; $this->Tree->create(); $this->Tree->save(array('name' => 'About Us', $parentField => $node1, $leftField => 0, $rightField => 0)); $node11 = $this->Tree->id; $this->Tree->create(); $this->Tree->save(array('name' => 'Programs', $parentField => $node1, $leftField => 0, $rightField => 0)); $node12 = $this->Tree->id; $this->Tree->create(); $this->Tree->save(array('name' => 'Mission and History', $parentField => $node11, $leftField => 0, $rightField => 0)); $this->Tree->create(); $this->Tree->save(array('name' => 'Overview', $parentField => $node12, $leftField => 0, $rightField => 0)); $this->Tree->Behaviors->enable('Tree'); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $result = $this->Tree->recover(); $this->assertTrue($result); $result = $this->Tree->verify(); $this->assertTrue($result); $result = $this->Tree->find('first', array( 'fields' => array('name', $parentField, $leftField, $rightField), 'conditions' => array('name' => 'Main'), 'recursive' => -1 )); $expected = array( $modelClass => array( 'name' => 'Main', $parentField => null, $leftField => 1, $rightField => 10 ) ); $this->assertEquals($expected, $result); } /** * testRecoverUsingParentModeAndDelete method * * @return void */ public function testRecoverUsingParentModeAndDelete() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->Behaviors->disable('Tree'); $this->Tree->create(); $this->Tree->save(array('name' => 'Main', $parentField => null, $leftField => 0, $rightField => 0)); $node1 = $this->Tree->id; $this->Tree->create(); $this->Tree->save(array('name' => 'About Us', $parentField => $node1, $leftField => 0, $rightField => 0)); $node11 = $this->Tree->id; $this->Tree->create(); $this->Tree->save(array('name' => 'Programs', $parentField => $node1, $leftField => 0, $rightField => 0)); $node12 = $this->Tree->id; $this->Tree->create(); $this->Tree->save(array('name' => 'Mission and History', $parentField => $node11, $leftField => 0, $rightField => 0)); $this->Tree->create(); $this->Tree->save(array('name' => 'Overview', $parentField => $node12, $leftField => 0, $rightField => 0)); $this->Tree->create(); $this->Tree->save(array('name' => 'Lost', $parentField => 9, $leftField => 0, $rightField => 0)); $this->Tree->Behaviors->enable('Tree'); $this->Tree->bindModel(array('belongsTo' => array('Parent' => array( 'className' => $this->Tree->name, 'foreignKey' => $parentField )))); $this->Tree->bindModel(array('hasMany' => array('Child' => array( 'className' => $this->Tree->name, 'foreignKey' => $parentField )))); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $count = $this->Tree->find('count'); $this->assertEquals(6, $count); $result = $this->Tree->recover('parent', 'delete'); $this->assertTrue($result); $result = $this->Tree->verify(); $this->assertTrue($result); $count = $this->Tree->find('count'); $this->assertEquals(5, $count); $result = $this->Tree->find('first', array( 'fields' => array('name', $parentField, $leftField, $rightField), 'conditions' => array('name' => 'Main'), 'recursive' => -1 )); $expected = array( $modelClass => array( 'name' => 'Main', $parentField => null, $leftField => 1, $rightField => 10 ) ); $this->assertEquals($expected, $result); } /** * testRecoverFromMissingParent method * * @return void */ public function testRecoverFromMissingParent() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $result = $this->Tree->findByName('1.1'); $this->Tree->updateAll(array($parentField => 999999), array('id' => $result[$modelClass]['id'])); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $result = $this->Tree->recover(); $this->assertTrue($result); $result = $this->Tree->verify(); $this->assertTrue($result); } /** * testDetectInvalidParents method * * @return void */ public function testDetectInvalidParents() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->updateAll(array($parentField => null)); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $result = $this->Tree->recover(); $this->assertTrue($result); $result = $this->Tree->verify(); $this->assertTrue($result); } /** * testDetectInvalidLftsRghts method * * @return void */ public function testDetectInvalidLftsRghts() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->updateAll(array($leftField => 0, $rightField => 0)); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $this->Tree->recover(); $result = $this->Tree->verify(); $this->assertTrue($result); } /** * Reproduces a situation where a single node has lft= rght, and all other lft and rght fields follow sequentially * * @return void */ public function testDetectEqualLftsRghts() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(1, 3); $result = $this->Tree->findByName('1.1'); $this->Tree->updateAll(array($rightField => $result[$modelClass][$leftField]), array('id' => $result[$modelClass]['id'])); $this->Tree->updateAll(array($leftField => $this->Tree->escapeField($leftField) . ' -1'), array($leftField . ' >' => $result[$modelClass][$leftField])); $this->Tree->updateAll(array($rightField => $this->Tree->escapeField($rightField) . ' -1'), array($rightField . ' >' => $result[$modelClass][$leftField])); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $result = $this->Tree->recover(); $this->assertTrue($result); $result = $this->Tree->verify(); $this->assertTrue($result); } /** * testAddOrphan method * * @return void */ public function testAddOrphan() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->create(); $this->Tree->save(array($modelClass => array('name' => 'testAddOrphan', $parentField => null))); $result = $this->Tree->find('first', array('fields' => array('name', $parentField), 'order' => $modelClass . '.' . $leftField . ' desc')); $expected = array($modelClass => array('name' => 'testAddOrphan', $parentField => null)); $this->assertEquals($expected, $result); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testAddMiddle method * * @return void */ public function testAddMiddle() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.1'))); $initialCount = $this->Tree->find('count'); $this->Tree->create(); $result = $this->Tree->save(array($modelClass => array('name' => 'testAddMiddle', $parentField => $data[$modelClass]['id']))); $expected = array_merge(array($modelClass => array('name' => 'testAddMiddle', $parentField => '2')), $result); $this->assertSame($expected, $result); $laterCount = $this->Tree->find('count'); $this->assertEquals($initialCount + 1, $laterCount); $children = $this->Tree->children($data[$modelClass]['id'], true, array('name')); $expected = array(array($modelClass => array('name' => '1.1.1')), array($modelClass => array('name' => '1.1.2')), array($modelClass => array('name' => 'testAddMiddle'))); $this->assertSame($expected, $children); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testAddWithPreSpecifiedId method * * @return void */ public function testAddWithPreSpecifiedId() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array( 'fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.1') )); $this->Tree->create(); $result = $this->Tree->save(array($modelClass => array( 'id' => 100, 'name' => 'testAddMiddle', $parentField => $data[$modelClass]['id']) )); $expected = array_merge( array($modelClass => array('id' => 100, 'name' => 'testAddMiddle', $parentField => '2')), $result ); $this->assertSame($expected, $result); $this->assertTrue($this->Tree->verify()); } /** * testAddInvalid method * * @return void */ public function testAddInvalid() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->id = null; $initialCount = $this->Tree->find('count'); //$this->expectError('Trying to save a node under a none-existant node in TreeBehavior::beforeSave'); $this->Tree->create(); $saveSuccess = $this->Tree->save(array($modelClass => array('name' => 'testAddInvalid', $parentField => 99999))); $this->assertFalse($saveSuccess); $laterCount = $this->Tree->find('count'); $this->assertSame($initialCount, $laterCount); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testAddNotIndexedByModel method * * @return void */ public function testAddNotIndexedByModel() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->create(); $this->Tree->save(array('name' => 'testAddNotIndexed', $parentField => null)); $result = $this->Tree->find('first', array('fields' => array('name', $parentField), 'order' => $modelClass . '.' . $leftField . ' desc')); $expected = array($modelClass => array('name' => 'testAddNotIndexed', $parentField => null)); $this->assertEquals($expected, $result); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testMovePromote method * * @return void */ public function testMovePromote() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->id = null; $parent = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1. Root'))); $parentId = $parent[$modelClass]['id']; $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.1.1'))); $this->Tree->id = $data[$modelClass]['id']; $this->Tree->saveField($parentField, $parentId); $direct = $this->Tree->children($parentId, true, array('id', 'name', $parentField, $leftField, $rightField)); $expected = array(array($modelClass => array('id' => 2, 'name' => '1.1', $parentField => 1, $leftField => 2, $rightField => 5)), array($modelClass => array('id' => 5, 'name' => '1.2', $parentField => 1, $leftField => 6, $rightField => 11)), array($modelClass => array('id' => 3, 'name' => '1.1.1', $parentField => 1, $leftField => 12, $rightField => 13))); $this->assertEquals($expected, $direct); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testGetLevel method * * @return void */ public function testGetLevel() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->id = null; $result = $this->Tree->getLevel(5); $this->assertEquals(1, $result); $result = $this->Tree->getLevel(3); $this->assertEquals(2, $result); $this->assertFalse($this->Tree->getLevel(999)); } /** * testMoveWithWhitelist method * * @return void */ public function testMoveWithWhitelist() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->id = null; $parent = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1. Root'))); $parentId = $parent[$modelClass]['id']; $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.1.1'))); $this->Tree->id = $data[$modelClass]['id']; $this->Tree->whitelist = array($parentField, 'name', 'description'); $this->Tree->saveField($parentField, $parentId); $result = $this->Tree->children($parentId, true, array('id', 'name', $parentField, $leftField, $rightField)); $expected = array(array($modelClass => array('id' => 2, 'name' => '1.1', $parentField => 1, $leftField => 2, $rightField => 5)), array($modelClass => array('id' => 5, 'name' => '1.2', $parentField => 1, $leftField => 6, $rightField => 11)), array($modelClass => array('id' => 3, 'name' => '1.1.1', $parentField => 1, $leftField => 12, $rightField => 13))); $this->assertEquals($expected, $result); $this->assertTrue($this->Tree->verify()); } /** * testInsertWithWhitelist method * * @return void */ public function testInsertWithWhitelist() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->whitelist = array('name', $parentField); $this->Tree->create(); $this->Tree->save(array($modelClass => array('name' => 'testAddOrphan', $parentField => null))); $result = $this->Tree->findByName('testAddOrphan', array('name', $parentField, $leftField, $rightField)); $expected = array('name' => 'testAddOrphan', $parentField => null, $leftField => '15', $rightField => 16); $this->assertEquals($expected, $result[$modelClass]); $this->assertTrue($this->Tree->verify()); } /** * testMoveBefore method * * @return void */ public function testMoveBefore() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->id = null; $parent = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1.1'))); $parentId = $parent[$modelClass]['id']; $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.2'))); $this->Tree->id = $data[$modelClass]['id']; $this->Tree->saveField($parentField, $parentId); $result = $this->Tree->children($parentId, true, array('name')); $expected = array(array($modelClass => array('name' => '1.1.1')), array($modelClass => array('name' => '1.1.2')), array($modelClass => array('name' => '1.2'))); $this->assertEquals($expected, $result); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testMoveAfter method * * @return void */ public function testMoveAfter() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->id = null; $parent = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1.2'))); $parentId = $parent[$modelClass]['id']; $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.1'))); $this->Tree->id = $data[$modelClass]['id']; $this->Tree->saveField($parentField, $parentId); $result = $this->Tree->children($parentId, true, array('name')); $expected = array(array($modelClass => array('name' => '1.2.1')), array($modelClass => array('name' => '1.2.2')), array($modelClass => array('name' => '1.1'))); $this->assertEquals($expected, $result); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testMoveDemoteInvalid method * * @return void */ public function testMoveDemoteInvalid() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->id = null; $parent = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1. Root'))); $parentId = $parent[$modelClass]['id']; $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.1.1'))); $expected = $this->Tree->find('all'); $before = $this->Tree->read(null, $data[$modelClass]['id']); $this->Tree->id = $parentId; $this->Tree->saveField($parentField, $data[$modelClass]['id']); $results = $this->Tree->find('all'); $after = $this->Tree->read(null, $data[$modelClass]['id']); $this->assertEquals($expected, $results); $this->assertEquals($before, $after); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testMoveInvalid method * * @return void */ public function testMoveInvalid() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->id = null; $initialCount = $this->Tree->find('count'); $data = $this->Tree->findByName('1.1'); $this->Tree->id = $data[$modelClass]['id']; $this->Tree->saveField($parentField, 999999); $laterCount = $this->Tree->find('count'); $this->assertSame($initialCount, $laterCount); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testMoveSelfInvalid method * * @return void */ public function testMoveSelfInvalid() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->id = null; $initialCount = $this->Tree->find('count'); $data = $this->Tree->findByName('1.1'); $this->Tree->id = $data[$modelClass]['id']; $saveSuccess = $this->Tree->saveField($parentField, $this->Tree->id); $this->assertFalse($saveSuccess); $laterCount = $this->Tree->find('count'); $this->assertSame($initialCount, $laterCount); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testMoveUpSuccess method * * @return void */ public function testMoveUpSuccess() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.2'))); $this->Tree->moveUp($data[$modelClass]['id']); $parent = $this->Tree->findByName('1. Root', array('id')); $this->Tree->id = $parent[$modelClass]['id']; $result = $this->Tree->children(null, true, array('name')); $expected = array(array($modelClass => array('name' => '1.2')), array($modelClass => array('name' => '1.1'))); $this->assertSame($expected, $result); } /** * testMoveUpFail method * * @return void */ public function testMoveUpFail() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1.1'))); $this->Tree->moveUp($data[$modelClass]['id']); $parent = $this->Tree->findByName('1. Root', array('id')); $this->Tree->id = $parent[$modelClass]['id']; $result = $this->Tree->children(null, true, array('name')); $expected = array(array($modelClass => array('name' => '1.1')), array($modelClass => array('name' => '1.2'))); $this->assertSame($expected, $result); } /** * testMoveUp2 method * * @return void */ public function testMoveUp2() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(1, 10); $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.5'))); $this->Tree->moveUp($data[$modelClass]['id'], 2); $parent = $this->Tree->findByName('1. Root', array('id')); $this->Tree->id = $parent[$modelClass]['id']; $result = $this->Tree->children(null, true, array('name')); $expected = array( array($modelClass => array('name' => '1.1')), array($modelClass => array('name' => '1.2')), array($modelClass => array('name' => '1.5')), array($modelClass => array('name' => '1.3')), array($modelClass => array('name' => '1.4')), array($modelClass => array('name' => '1.6')), array($modelClass => array('name' => '1.7')), array($modelClass => array('name' => '1.8')), array($modelClass => array('name' => '1.9')), array($modelClass => array('name' => '1.10'))); $this->assertSame($expected, $result); } /** * testMoveUpFirst method * * @return void */ public function testMoveUpFirst() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(1, 10); $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.5'))); $this->Tree->moveUp($data[$modelClass]['id'], true); $parent = $this->Tree->findByName('1. Root', array('id')); $this->Tree->id = $parent[$modelClass]['id']; $result = $this->Tree->children(null, true, array('name')); $expected = array( array($modelClass => array('name' => '1.5')), array($modelClass => array('name' => '1.1')), array($modelClass => array('name' => '1.2')), array($modelClass => array('name' => '1.3')), array($modelClass => array('name' => '1.4')), array($modelClass => array('name' => '1.6')), array($modelClass => array('name' => '1.7')), array($modelClass => array('name' => '1.8')), array($modelClass => array('name' => '1.9')), array($modelClass => array('name' => '1.10'))); $this->assertSame($expected, $result); } /** * testMoveDownSuccess method * * @return void */ public function testMoveDownSuccess() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.1'))); $this->Tree->moveDown($data[$modelClass]['id']); $parent = $this->Tree->findByName('1. Root', array('id')); $this->Tree->id = $parent[$modelClass]['id']; $result = $this->Tree->children(null, true, array('name')); $expected = array(array($modelClass => array('name' => '1.2')), array($modelClass => array('name' => '1.1'))); $this->assertSame($expected, $result); } /** * testMoveDownFail method * * @return void */ public function testMoveDownFail() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1.2'))); $this->Tree->moveDown($data[$modelClass]['id']); $parent = $this->Tree->findByName('1. Root', array('id')); $this->Tree->id = $parent[$modelClass]['id']; $result = $this->Tree->children(null, true, array('name')); $expected = array(array($modelClass => array('name' => '1.1')), array($modelClass => array('name' => '1.2'))); $this->assertSame($expected, $result); } /** * testMoveDownLast method * * @return void */ public function testMoveDownLast() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(1, 10); $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.5'))); $this->Tree->moveDown($data[$modelClass]['id'], true); $parent = $this->Tree->findByName('1. Root', array('id')); $this->Tree->id = $parent[$modelClass]['id']; $result = $this->Tree->children(null, true, array('name')); $expected = array( array($modelClass => array('name' => '1.1')), array($modelClass => array('name' => '1.2')), array($modelClass => array('name' => '1.3')), array($modelClass => array('name' => '1.4')), array($modelClass => array('name' => '1.6')), array($modelClass => array('name' => '1.7')), array($modelClass => array('name' => '1.8')), array($modelClass => array('name' => '1.9')), array($modelClass => array('name' => '1.10')), array($modelClass => array('name' => '1.5'))); $this->assertSame($expected, $result); } /** * testMoveDown2 method * * @return void */ public function testMoveDown2() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(1, 10); $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.5'))); $this->Tree->moveDown($data[$modelClass]['id'], 2); $parent = $this->Tree->findByName('1. Root', array('id')); $this->Tree->id = $parent[$modelClass]['id']; $result = $this->Tree->children(null, true, array('name')); $expected = array( array($modelClass => array('name' => '1.1')), array($modelClass => array('name' => '1.2')), array($modelClass => array('name' => '1.3')), array($modelClass => array('name' => '1.4')), array($modelClass => array('name' => '1.6')), array($modelClass => array('name' => '1.7')), array($modelClass => array('name' => '1.5')), array($modelClass => array('name' => '1.8')), array($modelClass => array('name' => '1.9')), array($modelClass => array('name' => '1.10'))); $this->assertSame($expected, $result); } /** * testSaveNoMove method * * @return void */ public function testSaveNoMove() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(1, 10); $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.5'))); $this->Tree->id = $data[$modelClass]['id']; $this->Tree->saveField('name', 'renamed'); $parent = $this->Tree->findByName('1. Root', array('id')); $this->Tree->id = $parent[$modelClass]['id']; $result = $this->Tree->children(null, true, array('name')); $expected = array( array($modelClass => array('name' => '1.1')), array($modelClass => array('name' => '1.2')), array($modelClass => array('name' => '1.3')), array($modelClass => array('name' => '1.4')), array($modelClass => array('name' => 'renamed')), array($modelClass => array('name' => '1.6')), array($modelClass => array('name' => '1.7')), array($modelClass => array('name' => '1.8')), array($modelClass => array('name' => '1.9')), array($modelClass => array('name' => '1.10'))); $this->assertSame($expected, $result); } /** * testMoveToRootAndMoveUp method * * @return void */ public function testMoveToRootAndMoveUp() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(1, 1); $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.1'))); $this->Tree->id = $data[$modelClass]['id']; $this->Tree->save(array($parentField => null)); $result = $this->Tree->verify(); $this->assertTrue($result); $this->Tree->moveUp(); $result = $this->Tree->find('all', array('fields' => 'name', 'order' => $modelClass . '.' . $leftField . ' ASC')); $expected = array(array($modelClass => array('name' => '1.1')), array($modelClass => array('name' => '1. Root'))); $this->assertSame($expected, $result); } /** * testDelete method * * @return void */ public function testDelete() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $initialCount = $this->Tree->find('count'); $result = $this->Tree->findByName('1.1.1'); $return = $this->Tree->delete($result[$modelClass]['id']); $this->assertEquals(true, $return); $laterCount = $this->Tree->find('count'); $this->assertEquals($initialCount - 1, $laterCount); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); $initialCount = $this->Tree->find('count'); $result = $this->Tree->findByName('1.1'); $return = $this->Tree->delete($result[$modelClass]['id']); $this->assertEquals(true, $return); $laterCount = $this->Tree->find('count'); $this->assertEquals($initialCount - 2, $laterCount); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * Test deleting a record that doesn't exist. * * @return void */ public function testDeleteDoesNotExist() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $this->Tree->delete(99999); } /** * testRemove method * * @return void */ public function testRemove() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $initialCount = $this->Tree->find('count'); $result = $this->Tree->findByName('1.1'); $this->Tree->removeFromTree($result[$modelClass]['id']); $laterCount = $this->Tree->find('count'); $this->assertEquals($initialCount, $laterCount); $children = $this->Tree->children($result[$modelClass][$parentField], true, array('name')); $expected = array(array($modelClass => array('name' => '1.1.1')), array($modelClass => array('name' => '1.1.2')), array($modelClass => array('name' => '1.2'))); $this->assertEquals($expected, $children); $topNodes = $this->Tree->children(false, true, array('name')); $expected = array(array($modelClass => array('name' => '1. Root')), array($modelClass => array('name' => '1.1'))); $this->assertEquals($expected, $topNodes); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testRemoveLastTopParent method * * @return void */ public function testRemoveLastTopParent() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $initialCount = $this->Tree->find('count'); $initialTopNodes = $this->Tree->childCount(false); $result = $this->Tree->findByName('1. Root'); $this->Tree->removeFromTree($result[$modelClass]['id']); $laterCount = $this->Tree->find('count'); $laterTopNodes = $this->Tree->childCount(false); $this->assertEquals($initialCount, $laterCount); $this->assertEquals($initialTopNodes, $laterTopNodes); $topNodes = $this->Tree->children(false, true, array('name')); $expected = array(array($modelClass => array('name' => '1.1')), array($modelClass => array('name' => '1.2')), array($modelClass => array('name' => '1. Root'))); $this->assertEquals($expected, $topNodes); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testRemoveNoChildren method * * @return void */ public function testRemoveNoChildren() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $initialCount = $this->Tree->find('count'); $result = $this->Tree->findByName('1.1.1'); $this->Tree->removeFromTree($result[$modelClass]['id']); $laterCount = $this->Tree->find('count'); $this->assertEquals($initialCount, $laterCount); $nodes = $this->Tree->find('list', array('order' => $leftField)); $expected = array( 1 => '1. Root', 2 => '1.1', 4 => '1.1.2', 5 => '1.2', 6 => '1.2.1', 7 => '1.2.2', 3 => '1.1.1', ); $this->assertEquals($expected, $nodes); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testRemoveAndDelete method * * @return void */ public function testRemoveAndDelete() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $initialCount = $this->Tree->find('count'); $result = $this->Tree->findByName('1.1'); $this->Tree->removeFromTree($result[$modelClass]['id'], true); $laterCount = $this->Tree->find('count'); $this->assertEquals($initialCount - 1, $laterCount); $children = $this->Tree->children($result[$modelClass][$parentField], true, array('name'), $leftField . ' asc'); $expected = array( array($modelClass => array('name' => '1.1.1')), array($modelClass => array('name' => '1.1.2')), array($modelClass => array('name' => '1.2')) ); $this->assertEquals($expected, $children); $topNodes = $this->Tree->children(false, true, array('name')); $expected = array(array($modelClass => array('name' => '1. Root'))); $this->assertEquals($expected, $topNodes); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testRemoveAndDeleteNoChildren method * * @return void */ public function testRemoveAndDeleteNoChildren() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $initialCount = $this->Tree->find('count'); $result = $this->Tree->findByName('1.1.1'); $this->Tree->removeFromTree($result[$modelClass]['id'], true); $laterCount = $this->Tree->find('count'); $this->assertEquals($initialCount - 1, $laterCount); $nodes = $this->Tree->find('list', array('order' => $leftField)); $expected = array( 1 => '1. Root', 2 => '1.1', 4 => '1.1.2', 5 => '1.2', 6 => '1.2.1', 7 => '1.2.2', ); $this->assertEquals($expected, $nodes); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testChildren method * * @return void */ public function testChildren() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1. Root'))); $this->Tree->id = $data[$modelClass]['id']; $direct = $this->Tree->children(null, true, array('id', 'name', $parentField, $leftField, $rightField)); $expected = array(array($modelClass => array('id' => 2, 'name' => '1.1', $parentField => 1, $leftField => 2, $rightField => 7)), array($modelClass => array('id' => 5, 'name' => '1.2', $parentField => 1, $leftField => 8, $rightField => 13))); $this->assertEquals($expected, $direct); $total = $this->Tree->children(null, null, array('id', 'name', $parentField, $leftField, $rightField)); $expected = array(array($modelClass => array('id' => 2, 'name' => '1.1', $parentField => 1, $leftField => 2, $rightField => 7)), array($modelClass => array('id' => 3, 'name' => '1.1.1', $parentField => 2, $leftField => 3, $rightField => 4)), array($modelClass => array('id' => 4, 'name' => '1.1.2', $parentField => 2, $leftField => 5, $rightField => 6)), array($modelClass => array('id' => 5, 'name' => '1.2', $parentField => 1, $leftField => 8, $rightField => 13)), array($modelClass => array('id' => 6, 'name' => '1.2.1', $parentField => 5, $leftField => 9, $rightField => 10)), array($modelClass => array('id' => 7, 'name' => '1.2.2', $parentField => 5, $leftField => 11, $rightField => 12))); $this->assertEquals($expected, $total); $this->assertEquals(array(), $this->Tree->children(10000)); } /** * testCountChildren method * * @return void */ public function testCountChildren() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1. Root'))); $this->Tree->id = $data[$modelClass]['id']; $direct = $this->Tree->childCount(null, true); $this->assertEquals(2, $direct); $total = $this->Tree->childCount(); $this->assertEquals(6, $total); $this->Tree->read(null, $data[$modelClass]['id']); $id = $this->Tree->field('id', array($modelClass . '.name' => '1.2')); $total = $this->Tree->childCount($id); $this->assertEquals(2, $total); } /** * testGetParentNode method * * @return void */ public function testGetParentNode() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1.2.2'))); $this->Tree->id = $data[$modelClass]['id']; $result = $this->Tree->getParentNode(null, array('name')); $expected = array($modelClass => array('name' => '1.2')); $this->assertSame($expected, $result); } /** * testGetPath method * * @return void */ public function testGetPath() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1.2.2'))); $this->Tree->id = $data[$modelClass]['id']; $result = $this->Tree->getPath(null, array('name')); $expected = array(array($modelClass => array('name' => '1. Root')), array($modelClass => array('name' => '1.2')), array($modelClass => array('name' => '1.2.2'))); $this->assertSame($expected, $result); } /** * testNoAmbiguousColumn method * * @return void */ public function testNoAmbiguousColumn() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->bindModel(array('belongsTo' => array('Dummy' => array('className' => $modelClass, 'foreignKey' => $parentField, 'conditions' => array('Dummy.id' => null)))), false); $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1. Root'))); $this->Tree->id = $data[$modelClass]['id']; $direct = $this->Tree->children(null, true, array('id', 'name', $parentField, $leftField, $rightField)); $expected = array(array($modelClass => array('id' => 2, 'name' => '1.1', $parentField => 1, $leftField => 2, $rightField => 7)), array($modelClass => array('id' => 5, 'name' => '1.2', $parentField => 1, $leftField => 8, $rightField => 13))); $this->assertEquals($expected, $direct); $total = $this->Tree->children(null, null, array('id', 'name', $parentField, $leftField, $rightField)); $expected = array( array($modelClass => array('id' => 2, 'name' => '1.1', $parentField => 1, $leftField => 2, $rightField => 7)), array($modelClass => array('id' => 3, 'name' => '1.1.1', $parentField => 2, $leftField => 3, $rightField => 4)), array($modelClass => array('id' => 4, 'name' => '1.1.2', $parentField => 2, $leftField => 5, $rightField => 6)), array($modelClass => array('id' => 5, 'name' => '1.2', $parentField => 1, $leftField => 8, $rightField => 13)), array($modelClass => array('id' => 6, 'name' => '1.2.1', $parentField => 5, $leftField => 9, $rightField => 10)), array($modelClass => array('id' => 7, 'name' => '1.2.2', $parentField => 5, $leftField => 11, $rightField => 12)) ); $this->assertEquals($expected, $total); } /** * testReorderTree method * * @return void */ public function testReorderTree() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(3, 3); $nodes = $this->Tree->find('list', array('order' => $leftField)); $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.1'))); $this->Tree->moveDown($data[$modelClass]['id']); $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.2.1'))); $this->Tree->moveDown($data[$modelClass]['id']); $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.3.2.2'))); $this->Tree->moveDown($data[$modelClass]['id']); $unsortedNodes = $this->Tree->find('list', array('order' => $leftField)); $this->assertEquals($nodes, $unsortedNodes); $this->assertNotEquals(array_keys($nodes), array_keys($unsortedNodes)); $this->Tree->reorder(); $sortedNodes = $this->Tree->find('list', array('order' => $leftField)); $this->assertSame($nodes, $sortedNodes); } /** * test reordering large-ish trees with cacheQueries = true. * This caused infinite loops when moving down elements as stale data is returned * from the memory cache * * @return void */ public function testReorderBigTreeWithQueryCaching() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 10); $original = $this->Tree->cacheQueries; $this->Tree->cacheQueries = true; $this->Tree->reorder(array('field' => 'name', 'direction' => 'DESC')); $this->assertTrue($this->Tree->cacheQueries, 'cacheQueries was not restored after reorder(). %s'); $this->Tree->cacheQueries = $original; } /** * testGenerateTreeListWithSelfJoin method * * @return void */ public function testGenerateTreeListWithSelfJoin() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->bindModel(array('belongsTo' => array('Dummy' => array('className' => $modelClass, 'foreignKey' => $parentField, 'conditions' => array('Dummy.id' => null)))), false); $this->Tree->initialize(2, 2); $result = $this->Tree->generateTreeList(); $expected = array(1 => '1. Root', 2 => '_1.1', 3 => '__1.1.1', 4 => '__1.1.2', 5 => '_1.2', 6 => '__1.2.1', 7 => '__1.2.2'); $this->assertSame($expected, $result); } /** * Test the formatting options of generateTreeList() * * @return void */ public function testGenerateTreeListFormatting() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $result = $this->Tree->generateTreeList( null, "{n}.$modelClass.id", array('%s - %s', "{n}.$modelClass.id", "{n}.$modelClass.name") ); $this->assertEquals('1 - 1. Root', $result[1]); $this->assertEquals('_2 - 1.1', $result[2]); $this->assertEquals('__3 - 1.1.1', $result[3]); } /** * Test the formatting options of formatTreeList() * * @return void */ public function testFormatTreeList() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(2, 2); $options = array('order' => array('lft' => 'asc')); $records = $this->Tree->find('all', $options); $options = array( 'keyPath' => "{n}.$modelClass.id", 'valuePath' => array('%s - %s', "{n}.$modelClass.id", "{n}.$modelClass.name"), 'spacer' => '--'); $result = $this->Tree->formatTreeList($records, $options); $this->assertEquals('1 - 1. Root', $result[1]); $this->assertEquals('--2 - 1.1', $result[2]); $this->assertEquals('----3 - 1.1.1', $result[3]); } /** * testArraySyntax method * * @return void */ public function testArraySyntax() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->initialize(3, 3); $this->assertSame($this->Tree->childCount(2), $this->Tree->childCount(array('id' => 2))); $this->assertSame($this->Tree->getParentNode(2), $this->Tree->getParentNode(array('id' => 2))); $this->assertSame($this->Tree->getPath(4), $this->Tree->getPath(array('id' => 4))); } /** * testFindThreaded method * * @return void */ public function testFindThreaded() { $Model = new Person(); $Model->recursive = -1; $Model->Behaviors->load('Tree', array('parent' => 'mother_id')); $result = $Model->find('threaded'); $expected = array( array( 'Person' => array( 'id' => '4', 'name' => 'mother - grand mother', 'mother_id' => '0', 'father_id' => '0' ), 'children' => array( array( 'Person' => array( 'id' => '2', 'name' => 'mother', 'mother_id' => '4', 'father_id' => '5' ), 'children' => array( array( 'Person' => array( 'id' => '1', 'name' => 'person', 'mother_id' => '2', 'father_id' => '3' ), 'children' => array() ) ) ) ) ), array( 'Person' => array( 'id' => '5', 'name' => 'mother - grand father', 'mother_id' => '0', 'father_id' => '0' ), 'children' => array() ), array( 'Person' => array( 'id' => '6', 'name' => 'father - grand mother', 'mother_id' => '0', 'father_id' => '0' ), 'children' => array( array( 'Person' => array( 'id' => '3', 'name' => 'father', 'mother_id' => '6', 'father_id' => '7' ), 'children' => array() ) ) ), array( 'Person' => array( 'id' => '7', 'name' => 'father - grand father', 'mother_id' => '0', 'father_id' => '0' ), 'children' => array() ) ); $this->assertEquals($expected, $result); } public function testLevel() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->Behaviors->attach('Tree', array('level' => 'level')); $this->Tree->initialize(2, 2); $result = $this->Tree->findByName('1. Root'); $this->assertEquals(0, $result[$modelClass][$level]); $result = $this->Tree->findByName('1.1'); $this->assertEquals(1, $result[$modelClass][$level]); $result = $this->Tree->findByName('1.2.2'); $this->assertEquals(2, $result[$modelClass][$level]); $result = $this->Tree->findByName('1.2.1'); $this->assertEquals(2, $result[$modelClass][$level]); // Save with parent_id not set $this->Tree->save(array('id' => $result[$modelClass]['id'], 'name' => 'foo')); $result = $this->Tree->findByName('foo'); $this->assertEquals(2, $result[$modelClass][$level]); // Save with parent_id not changed $this->Tree->save(array( 'id' => $result[$modelClass]['id'], 'parent_id' => $result[$modelClass]['parent_id'], 'name' => 'foo2' )); $result = $this->Tree->findByName('foo2'); $this->assertEquals(2, $result[$modelClass][$level]); // Save with parent_id changed $result = $this->Tree->findByName('1.1'); $this->Tree->save(array( 'id' => $result[$modelClass]['id'], 'parent_id' => '' )); $result = $this->Tree->findByName('1.1'); $this->assertEquals(0, $result[$modelClass][$level]); $result = $this->Tree->findByName('1.1.2'); $this->assertEquals(1, $result[$modelClass][$level]); $parent = $this->Tree->findByName('1.1.2'); $result = $this->Tree->findByName('1.2'); $this->Tree->save(array( 'id' => $result[$modelClass]['id'], 'parent_id' => $parent[$modelClass]['id'] )); $result = $this->Tree->findByName('1.2'); $this->assertEquals(2, $result[$modelClass][$level]); $result = $this->Tree->findByName('1.2.2'); $this->assertEquals(3, $result[$modelClass][$level]); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Behavior/TreeBehaviorScopedTest.php000066400000000000000000000376531265552240500262500ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model.Behavior * @since CakePHP(tm) v 1.2.0.5330 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Model', 'Model'); App::uses('AppModel', 'Model'); require_once dirname(dirname(__FILE__)) . DS . 'models.php'; /** * TreeBehaviorScopedTest class * * @package Cake.Test.Case.Model.Behavior */ class TreeBehaviorScopedTest extends CakeTestCase { /** * Whether backup global state for each test method or not * * @var bool */ public $backupGlobals = false; /** * settings property * * @var array */ public $settings = array( 'modelClass' => 'FlagTree', 'leftField' => 'lft', 'rightField' => 'rght', 'parentField' => 'parent_id' ); /** * fixtures property * * @var array */ public $fixtures = array('core.flag_tree', 'core.ad', 'core.campaign', 'core.translate', 'core.number_tree_two'); /** * testStringScope method * * @return void */ public function testStringScope() { $this->Tree = new FlagTree(); $this->Tree->order = null; $this->Tree->initialize(2, 3); $this->Tree->id = 1; $this->Tree->saveField('flag', 1); $this->Tree->id = 2; $this->Tree->saveField('flag', 1); $result = $this->Tree->children(); $expected = array( array('FlagTree' => array('id' => '3', 'name' => '1.1.1', 'parent_id' => '2', 'lft' => '3', 'rght' => '4', 'flag' => '0')), array('FlagTree' => array('id' => '4', 'name' => '1.1.2', 'parent_id' => '2', 'lft' => '5', 'rght' => '6', 'flag' => '0')), array('FlagTree' => array('id' => '5', 'name' => '1.1.3', 'parent_id' => '2', 'lft' => '7', 'rght' => '8', 'flag' => '0')) ); $this->assertEquals($expected, $result); $this->Tree->Behaviors->load('Tree', array('scope' => 'FlagTree.flag = 1')); $this->assertEquals(array(), $this->Tree->children()); $this->Tree->id = 1; $this->Tree->Behaviors->load('Tree', array('scope' => 'FlagTree.flag = 1')); $result = $this->Tree->children(); $expected = array(array('FlagTree' => array('id' => '2', 'name' => '1.1', 'parent_id' => '1', 'lft' => '2', 'rght' => '9', 'flag' => '1'))); $this->assertEquals($expected, $result); $this->assertTrue($this->Tree->delete()); $this->assertEquals(11, $this->Tree->find('count')); } /** * testArrayScope method * * @return void */ public function testArrayScope() { $this->Tree = new FlagTree(); $this->Tree->order = null; $this->Tree->initialize(2, 3); $this->Tree->id = 1; $this->Tree->saveField('flag', 1); $this->Tree->id = 2; $this->Tree->saveField('flag', 1); $result = $this->Tree->children(); $expected = array( array('FlagTree' => array('id' => '3', 'name' => '1.1.1', 'parent_id' => '2', 'lft' => '3', 'rght' => '4', 'flag' => '0')), array('FlagTree' => array('id' => '4', 'name' => '1.1.2', 'parent_id' => '2', 'lft' => '5', 'rght' => '6', 'flag' => '0')), array('FlagTree' => array('id' => '5', 'name' => '1.1.3', 'parent_id' => '2', 'lft' => '7', 'rght' => '8', 'flag' => '0')) ); $this->assertEquals($expected, $result); $this->Tree->Behaviors->load('Tree', array('scope' => array('FlagTree.flag' => 1))); $this->assertEquals(array(), $this->Tree->children()); $this->Tree->id = 1; $this->Tree->Behaviors->load('Tree', array('scope' => array('FlagTree.flag' => 1))); $result = $this->Tree->children(); $expected = array(array('FlagTree' => array('id' => '2', 'name' => '1.1', 'parent_id' => '1', 'lft' => '2', 'rght' => '9', 'flag' => '1'))); $this->assertEquals($expected, $result); $this->assertTrue($this->Tree->delete()); $this->assertEquals(11, $this->Tree->find('count')); } /** * testSaveWithParentAndInvalidScope method * * Attempting to save an invalid data should not trigger an `Undefined offset` * error * * @return void */ public function testSaveWithParentAndInvalidScope() { $this->Tree = new FlagTree(); $this->Tree->order = null; $data = $this->Tree->create(array( 'name' => 'Flag', )); $tree = $this->Tree->save($data); $this->Tree->Behaviors->load('Tree', array( 'scope' => array('FlagTree.flag' => 100) )); $tree['FlagTree']['parent_id'] = 1; $result = $this->Tree->save($tree); $this->assertFalse($result); } /** * testMoveUpWithScope method * * @return void */ public function testMoveUpWithScope() { $this->Ad = new Ad(); $this->Ad->order = null; $this->Ad->Behaviors->load('Tree', array('scope' => 'Campaign')); $this->Ad->moveUp(6); $this->Ad->id = 4; $result = $this->Ad->children(); $this->assertEquals(array(6, 5), Hash::extract($result, '{n}.Ad.id')); $this->assertEquals(array(2, 2), Hash::extract($result, '{n}.Campaign.id')); } /** * testMoveDownWithScope method * * @return void */ public function testMoveDownWithScope() { $this->Ad = new Ad(); $this->Ad->order = null; $this->Ad->Behaviors->load('Tree', array('scope' => 'Campaign')); $this->Ad->moveDown(6); $this->Ad->id = 4; $result = $this->Ad->children(); $this->assertEquals(array(5, 6), Hash::extract($result, '{n}.Ad.id')); $this->assertEquals(array(2, 2), Hash::extract($result, '{n}.Campaign.id')); } /** * Tests the interaction (non-interference) between TreeBehavior and other behaviors with respect * to callback hooks * * @return void */ public function testTranslatingTree() { $this->Tree = new FlagTree(); $this->Tree->order = null; $this->Tree->cacheQueries = false; $this->Tree->Behaviors->load('Translate', array('title')); //Save $this->Tree->create(); $this->Tree->locale = 'eng'; $data = array('FlagTree' => array( 'title' => 'name #1', 'name' => 'test', 'locale' => 'eng', 'parent_id' => null, )); $this->Tree->save($data); $result = $this->Tree->find('all'); $expected = array(array('FlagTree' => array( 'id' => 1, 'title' => 'name #1', 'name' => 'test', 'parent_id' => null, 'lft' => 1, 'rght' => 2, 'flag' => 0, 'locale' => 'eng', ))); $this->assertEquals($expected, $result); // update existing record, same locale $this->Tree->create(); $data['FlagTree']['title'] = 'Named 2'; $this->Tree->id = 1; $this->Tree->save($data); $result = $this->Tree->find('all'); $expected = array(array('FlagTree' => array( 'id' => 1, 'title' => 'Named 2', 'name' => 'test', 'parent_id' => null, 'lft' => 1, 'rght' => 2, 'flag' => 0, 'locale' => 'eng', ))); $this->assertEquals($expected, $result); // update different locale, same record $this->Tree->create(); $this->Tree->locale = 'deu'; $this->Tree->id = 1; $data = array('FlagTree' => array( 'id' => 1, 'parent_id' => null, 'title' => 'namen #1', 'name' => 'test', 'locale' => 'deu', )); $this->Tree->save($data); $this->Tree->locale = 'deu'; $result = $this->Tree->find('all'); $expected = array( array( 'FlagTree' => array( 'id' => 1, 'title' => 'namen #1', 'name' => 'test', 'parent_id' => null, 'lft' => 1, 'rght' => 2, 'flag' => 0, 'locale' => 'deu', ) ) ); $this->assertEquals($expected, $result); // Save with bindTranslation $this->Tree->locale = 'eng'; $data = array( 'title' => array('eng' => 'New title', 'spa' => 'Nuevo leyenda'), 'name' => 'test', 'parent_id' => null ); $this->Tree->create($data); $this->Tree->save(); $this->Tree->unbindTranslation(); $translations = array('title' => 'Title'); $this->Tree->bindTranslation($translations, false); $this->Tree->locale = array('eng', 'spa'); $result = $this->Tree->read(); $expected = array( 'FlagTree' => array( 'id' => 2, 'parent_id' => null, 'locale' => 'eng', 'name' => 'test', 'title' => 'New title', 'flag' => 0, 'lft' => 3, 'rght' => 4 ), 'Title' => array( array('id' => 21, 'locale' => 'eng', 'model' => 'FlagTree', 'foreign_key' => 2, 'field' => 'title', 'content' => 'New title'), array('id' => 22, 'locale' => 'spa', 'model' => 'FlagTree', 'foreign_key' => 2, 'field' => 'title', 'content' => 'Nuevo leyenda') ), ); $this->assertEquals($expected, $result); } /** * testGenerateTreeListWithSelfJoin method * * @return void */ public function testAliasesWithScopeInTwoTreeAssociations() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 2); $this->TreeTwo = new NumberTreeTwo(); $this->TreeTwo->order = null; $record = $this->Tree->find('first'); $this->Tree->bindModel(array( 'hasMany' => array( 'SecondTree' => array( 'className' => 'NumberTreeTwo', 'foreignKey' => 'number_tree_id' ) ) )); $this->TreeTwo->bindModel(array( 'belongsTo' => array( 'FirstTree' => array( 'className' => $modelClass, 'foreignKey' => 'number_tree_id' ) ) )); $this->TreeTwo->Behaviors->load('Tree', array( 'scope' => 'FirstTree' )); $data = array( 'NumberTreeTwo' => array( 'name' => 'First', 'number_tree_id' => $record['FlagTree']['id'] ) ); $this->TreeTwo->create(); $result = $this->TreeTwo->save($data); $this->assertFalse(empty($result)); $result = $this->TreeTwo->find('first'); $expected = array('NumberTreeTwo' => array( 'id' => 1, 'name' => 'First', 'number_tree_id' => $record['FlagTree']['id'], 'parent_id' => null, 'lft' => 1, 'rght' => 2 )); $this->assertEquals($expected, $result); } /** * testGenerateTreeListWithScope method * * @return void */ public function testGenerateTreeListWithScope() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 3); $this->Tree->id = 1; $this->Tree->saveField('flag', 1); $this->Tree->id = 2; $this->Tree->saveField('flag', 1); $this->Tree->Behaviors->load('Tree', array('scope' => array('FlagTree.flag' => 1))); $result = $this->Tree->generateTreeList(); $expected = array( 1 => '1. Root', 2 => '_1.1' ); $this->assertEquals($expected, $result); // As string. $this->Tree->Behaviors->load('Tree', array('scope' => 'FlagTree.flag = 1')); $result = $this->Tree->generateTreeList(); $this->assertEquals($expected, $result); // Merging conditions. $result = $this->Tree->generateTreeList(array('FlagTree.id >' => 1)); $expected = array( 2 => '1.1' ); $this->assertEquals($expected, $result); } /** * testRecoverUsingParentMode method * * @return void */ public function testRecoverUsingParentMode() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 3); $this->Tree->Behaviors->load('Tree', array('scope' => 'FlagTree.flag = 1')); $this->Tree->Behaviors->disable('Tree'); $this->Tree->create(); $this->Tree->save(array('name' => 'Main', $parentField => null, $leftField => 0, $rightField => 0, 'flag' => 1)); $node1 = $this->Tree->id; $this->Tree->create(); $this->Tree->save(array('name' => 'About Us', $parentField => $node1, $leftField => 0, $rightField => 0, 'flag' => 1)); $node11 = $this->Tree->id; $this->Tree->create(); $this->Tree->save(array('name' => 'Programs', $parentField => $node1, $leftField => 0, $rightField => 0, 'flag' => 1)); $node12 = $this->Tree->id; $this->Tree->create(); $this->Tree->save(array('name' => 'Mission and History', $parentField => $node11, $leftField => 0, $rightField => 0, 'flag' => 1)); $this->Tree->create(); $this->Tree->save(array('name' => 'Overview', $parentField => $node12, $leftField => 0, $rightField => 0, 'flag' => 1)); $this->Tree->Behaviors->enable('Tree'); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $result = $this->Tree->recover(); $this->assertTrue($result); $result = $this->Tree->verify(); $this->assertTrue($result); $result = $this->Tree->find('first', array( 'fields' => array('name', $parentField, $leftField, $rightField, 'flag'), 'conditions' => array('name' => 'Main'), 'recursive' => -1 )); $expected = array( $modelClass => array( 'name' => 'Main', $parentField => null, $leftField => 1, $rightField => 10, 'flag' => 1 ) ); $this->assertEquals($expected, $result); } /** * testRecoverFromMissingParent method * * @return void */ public function testRecoverFromMissingParent() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 2); $this->Tree->id = 1; $this->Tree->saveField('flag', 1); $this->Tree->id = 2; $this->Tree->saveField('flag', 1); $this->Tree->Behaviors->load('Tree', array('scope' => array('FlagTree.flag' => 1))); $result = $this->Tree->findByName('1.1'); $this->Tree->updateAll(array($parentField => 999999), array('id' => $result[$modelClass]['id'])); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $result = $this->Tree->recover(); $this->assertTrue($result); $result = $this->Tree->verify(); $this->assertTrue($result); } /** * testDetectInvalidParents method * * @return void */ public function testDetectInvalidParents() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 2); $this->Tree->id = 1; $this->Tree->saveField('flag', 1); $this->Tree->id = 2; $this->Tree->saveField('flag', 1); $this->Tree->Behaviors->load('Tree', array('scope' => array('FlagTree.flag' => 1))); $this->Tree->updateAll(array($parentField => null)); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $result = $this->Tree->recover(); $this->assertTrue($result); $result = $this->Tree->verify(); $this->assertTrue($result); } /** * testDetectInvalidLftsRghts method * * @return void */ public function testDetectInvalidLftsRghts() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 2); $this->Tree->id = 1; $this->Tree->saveField('flag', 1); $this->Tree->id = 2; $this->Tree->saveField('flag', 1); $this->Tree->Behaviors->load('Tree', array('scope' => array('FlagTree.flag' => 1))); $this->Tree->updateAll(array($leftField => 0, $rightField => 0)); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $this->Tree->recover(); $result = $this->Tree->verify(); $this->assertTrue($result); } /** * Reproduces a situation where a single node has lft= rght, and all other lft and rght fields follow sequentially * * @return void */ public function testDetectEqualLftsRghts() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(1, 3); $this->Tree->id = 1; $this->Tree->saveField('flag', 1); $this->Tree->id = 2; $this->Tree->saveField('flag', 1); $this->Tree->Behaviors->load('Tree', array('scope' => array('FlagTree.flag' => 1))); $result = $this->Tree->findByName('1.1'); $this->Tree->updateAll(array($rightField => $result[$modelClass][$leftField]), array('id' => $result[$modelClass]['id'])); $this->Tree->updateAll(array($leftField => $this->Tree->escapeField($leftField) . ' -1'), array($leftField . ' >' => $result[$modelClass][$leftField])); $this->Tree->updateAll(array($rightField => $this->Tree->escapeField($rightField) . ' -1'), array($rightField . ' >' => $result[$modelClass][$leftField])); $result = $this->Tree->verify(); $this->assertNotSame(true, $result); $result = $this->Tree->recover(); $this->assertTrue($result); $result = $this->Tree->verify(); $this->assertTrue($result); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Behavior/TreeBehaviorTest.php000066400000000000000000000027661265552240500251070ustar00rootroot00000000000000addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'Behavior' . DS . 'TreeBehaviorNumberTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'Behavior' . DS . 'TreeBehaviorScopedTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'Behavior' . DS . 'TreeBehaviorAfterTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'Behavior' . DS . 'TreeBehaviorUuidTest.php'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Behavior/TreeBehaviorUuidTest.php000066400000000000000000000226771265552240500257410ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model.Behavior * @since CakePHP(tm) v 1.2.0.5330 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Model', 'Model'); App::uses('AppModel', 'Model'); App::uses('CakeText', 'Utility'); require_once dirname(dirname(__FILE__)) . DS . 'models.php'; /** * TreeBehaviorUuidTest class * * @package Cake.Test.Case.Model.Behavior */ class TreeBehaviorUuidTest extends CakeTestCase { /** * Whether backup global state for each test method or not * * @var bool */ public $backupGlobals = false; /** * settings property * * @var array */ public $settings = array( 'modelClass' => 'UuidTree', 'leftField' => 'lft', 'rightField' => 'rght', 'parentField' => 'parent_id' ); /** * fixtures property * * @var array */ public $fixtures = array('core.uuid_tree'); /** * testAddWithPreSpecifiedId method * * @return void */ public function testAddWithPreSpecifiedId() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array( 'fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.1') )); $id = CakeText::uuid(); $this->Tree->create(); $result = $this->Tree->save(array($modelClass => array( 'id' => $id, 'name' => 'testAddMiddle', $parentField => $data[$modelClass]['id']) )); $expected = array_merge( array($modelClass => array('id' => $id, 'name' => 'testAddMiddle', $parentField => '2')), $result ); $this->assertSame($expected, $result); $this->assertTrue($this->Tree->verify()); } /** * testMovePromote method * * @return void */ public function testMovePromote() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 2); $this->Tree->id = null; $parent = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1. Root'))); $parentId = $parent[$modelClass]['id']; $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.1.1'))); $this->Tree->id = $data[$modelClass]['id']; $this->Tree->saveField($parentField, $parentId); $direct = $this->Tree->children($parentId, true, array('name', $leftField, $rightField)); $expected = array(array($modelClass => array('name' => '1.1', $leftField => 2, $rightField => 5)), array($modelClass => array('name' => '1.2', $leftField => 6, $rightField => 11)), array($modelClass => array('name' => '1.1.1', $leftField => 12, $rightField => 13))); $this->assertEquals($expected, $direct); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testMoveWithWhitelist method * * @return void */ public function testMoveWithWhitelist() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 2); $this->Tree->id = null; $parent = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1. Root'))); $parentId = $parent[$modelClass]['id']; $data = $this->Tree->find('first', array('fields' => array('id'), 'conditions' => array($modelClass . '.name' => '1.1.1'))); $this->Tree->id = $data[$modelClass]['id']; $this->Tree->whitelist = array($parentField, 'name', 'description'); $this->Tree->saveField($parentField, $parentId); $result = $this->Tree->children($parentId, true, array('name', $leftField, $rightField)); $expected = array(array($modelClass => array('name' => '1.1', $leftField => 2, $rightField => 5)), array($modelClass => array('name' => '1.2', $leftField => 6, $rightField => 11)), array($modelClass => array('name' => '1.1.1', $leftField => 12, $rightField => 13))); $this->assertEquals($expected, $result); $this->assertTrue($this->Tree->verify()); } /** * testRemoveNoChildren method * * @return void */ public function testRemoveNoChildren() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 2); $initialCount = $this->Tree->find('count'); $result = $this->Tree->findByName('1.1.1'); $this->Tree->removeFromTree($result[$modelClass]['id']); $laterCount = $this->Tree->find('count'); $this->assertEquals($initialCount, $laterCount); $nodes = $this->Tree->find('list', array('order' => $leftField)); $expected = array( '1. Root', '1.1', '1.1.2', '1.2', '1.2.1', '1.2.2', '1.1.1', ); $this->assertEquals($expected, array_values($nodes)); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testRemoveAndDeleteNoChildren method * * @return void */ public function testRemoveAndDeleteNoChildren() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 2); $initialCount = $this->Tree->find('count'); $result = $this->Tree->findByName('1.1.1'); $this->Tree->removeFromTree($result[$modelClass]['id'], true); $laterCount = $this->Tree->find('count'); $this->assertEquals($initialCount - 1, $laterCount); $nodes = $this->Tree->find('list', array('order' => $leftField)); $expected = array( '1. Root', '1.1', '1.1.2', '1.2', '1.2.1', '1.2.2', ); $this->assertEquals($expected, array_values($nodes)); $validTree = $this->Tree->verify(); $this->assertTrue($validTree); } /** * testChildren method * * @return void */ public function testChildren() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 2); $data = $this->Tree->find('first', array('conditions' => array($modelClass . '.name' => '1. Root'))); $this->Tree->id = $data[$modelClass]['id']; $direct = $this->Tree->children(null, true, array('name', $leftField, $rightField)); $expected = array(array($modelClass => array('name' => '1.1', $leftField => 2, $rightField => 7)), array($modelClass => array('name' => '1.2', $leftField => 8, $rightField => 13))); $this->assertEquals($expected, $direct); $total = $this->Tree->children(null, null, array('name', $leftField, $rightField)); $expected = array(array($modelClass => array('name' => '1.1', $leftField => 2, $rightField => 7)), array($modelClass => array('name' => '1.1.1', $leftField => 3, $rightField => 4)), array($modelClass => array('name' => '1.1.2', $leftField => 5, $rightField => 6)), array($modelClass => array('name' => '1.2', $leftField => 8, $rightField => 13)), array($modelClass => array('name' => '1.2.1', $leftField => 9, $rightField => 10)), array($modelClass => array('name' => '1.2.2', $leftField => 11, $rightField => 12))); $this->assertEquals($expected, $total); } /** * testNoAmbiguousColumn method * * @return void */ public function testNoAmbiguousColumn() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->initialize(2, 2); $this->Tree->bindModel(array('belongsTo' => array('Dummy' => array('className' => $modelClass, 'foreignKey' => $parentField, 'conditions' => array('Dummy.id' => null)))), false); $data = $this->Tree->find('first', array( 'conditions' => array($modelClass . '.name' => '1. Root'), 'recursive' => -1 )); $this->Tree->id = $data[$modelClass]['id']; $direct = $this->Tree->children(null, true, array('name', $leftField, $rightField)); $expected = array(array($modelClass => array('name' => '1.1', $leftField => 2, $rightField => 7)), array($modelClass => array('name' => '1.2', $leftField => 8, $rightField => 13))); $this->assertEquals($expected, $direct); $total = $this->Tree->children(null, null, array('name', $leftField, $rightField)); $expected = array( array($modelClass => array('name' => '1.1', $leftField => 2, $rightField => 7)), array($modelClass => array('name' => '1.1.1', $leftField => 3, $rightField => 4)), array($modelClass => array('name' => '1.1.2', $leftField => 5, $rightField => 6)), array($modelClass => array('name' => '1.2', $leftField => 8, $rightField => 13)), array($modelClass => array('name' => '1.2.1', $leftField => 9, $rightField => 10)), array($modelClass => array('name' => '1.2.2', $leftField => 11, $rightField => 12)) ); $this->assertEquals($expected, $total); } /** * testGenerateTreeListWithSelfJoin method * * @return void */ public function testGenerateTreeListWithSelfJoin() { extract($this->settings); $this->Tree = new $modelClass(); $this->Tree->order = null; $this->Tree->bindModel(array('belongsTo' => array('Dummy' => array('className' => $modelClass, 'foreignKey' => $parentField, 'conditions' => array('Dummy.id' => null)))), false); $this->Tree->initialize(2, 2); $result = $this->Tree->generateTreeList(); $expected = array('1. Root', '_1.1', '__1.1.1', '__1.1.2', '_1.2', '__1.2.1', '__1.2.2'); $this->assertSame($expected, array_values($result)); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/BehaviorCollectionTest.php000066400000000000000000001141621265552240500245360ustar00rootroot00000000000000 'testMethod', '/look for\s+(.+)/' => 'speakEnglish'); /** * setup method * * @param Model $model * @param array $config * @return void */ public function setup(Model $model, $config = array()) { parent::setup($model, $config); if (isset($config['mangle'])) { $config['mangle'] .= ' mangled'; } $this->settings[$model->alias] = array_merge(array('beforeFind' => 'on', 'afterFind' => 'off'), $config); } /** * beforeFind method * * @param Model $model * @param array $query * @return void */ public function beforeFind(Model $model, $query) { $settings = $this->settings[$model->alias]; if (!isset($settings['beforeFind']) || $settings['beforeFind'] === 'off') { return parent::beforeFind($model, $query); } switch ($settings['beforeFind']) { case 'on': return false; case 'test': return null; case 'modify': $query['fields'] = array($model->alias . '.id', $model->alias . '.name', $model->alias . '.mytime'); $query['recursive'] = -1; return $query; } } /** * afterFind method * * @param Model $model * @param array $results * @param bool $primary * @return void */ public function afterFind(Model $model, $results, $primary = false) { $settings = $this->settings[$model->alias]; if (!isset($settings['afterFind']) || $settings['afterFind'] === 'off') { return parent::afterFind($model, $results, $primary); } switch ($settings['afterFind']) { case 'on': return array(); case 'test': return true; case 'test2': return null; case 'modify': return Hash::extract($results, "{n}.{$model->alias}"); } } /** * beforeSave method * * @param Model $model Model using this behavior * @param array $options Options passed from Model::save(). * @return mixed False if the operation should abort. Any other result will continue. * @see Model::save() */ public function beforeSave(Model $model, $options = array()) { $settings = $this->settings[$model->alias]; if (!isset($settings['beforeSave']) || $settings['beforeSave'] === 'off') { return parent::beforeSave($model, $options); } switch ($settings['beforeSave']) { case 'on': return false; case 'test': return true; case 'modify': $model->data[$model->alias]['name'] .= ' modified before'; return true; } } /** * afterSave method * * @param Model $model * @param bool $created * @param array $options Options passed from Model::save(). * @return void */ public function afterSave(Model $model, $created, $options = array()) { $settings = $this->settings[$model->alias]; if (!isset($settings['afterSave']) || $settings['afterSave'] === 'off') { return parent::afterSave($model, $created, $options); } $string = 'modified after'; if ($created) { $string .= ' on create'; } switch ($settings['afterSave']) { case 'on': $model->data[$model->alias]['aftersave'] = $string; break; case 'test': unset($model->data[$model->alias]['name']); break; case 'test2': return false; case 'modify': $model->data[$model->alias]['name'] .= ' ' . $string; break; } } /** * beforeValidate Callback * * @param Model $Model Model invalidFields was called on. * @param array $options Options passed from Model::save(). * @return bool * @see Model::save() */ public function beforeValidate(Model $model, $options = array()) { $settings = $this->settings[$model->alias]; if (!isset($settings['validate']) || $settings['validate'] === 'off') { return parent::beforeValidate($model, $options); } switch ($settings['validate']) { case 'on': $model->invalidate('name'); return true; case 'test': return null; case 'whitelist': $this->_addToWhitelist($model, array('name')); return true; case 'stop': $model->invalidate('name'); return false; } } /** * afterValidate method * * @param Model $model * @param bool $cascade * @return void */ public function afterValidate(Model $model) { $settings = $this->settings[$model->alias]; if (!isset($settings['afterValidate']) || $settings['afterValidate'] === 'off') { return parent::afterValidate($model); } switch ($settings['afterValidate']) { case 'on': return false; case 'test': $model->data = array('foo'); return true; } } /** * beforeDelete method * * @param Model $model * @param bool $cascade * @return void */ public function beforeDelete(Model $model, $cascade = true) { $settings = $this->settings[$model->alias]; if (!isset($settings['beforeDelete']) || $settings['beforeDelete'] === 'off') { return parent::beforeDelete($model, $cascade); } switch ($settings['beforeDelete']) { case 'on': return false; case 'test': return null; case 'test2': echo 'beforeDelete success'; if ($cascade) { echo ' (cascading) '; } return true; } } /** * afterDelete method * * @param Model $model * @return void */ public function afterDelete(Model $model) { $settings = $this->settings[$model->alias]; if (!isset($settings['afterDelete']) || $settings['afterDelete'] === 'off') { return parent::afterDelete($model); } switch ($settings['afterDelete']) { case 'on': echo 'afterDelete success'; break; } } /** * onError method * * @param Model $model * @return void */ public function onError(Model $model, $error) { $settings = $this->settings[$model->alias]; if (!isset($settings['onError']) || $settings['onError'] === 'off') { return parent::onError($model, $error); } echo "onError trigger success"; } /** * beforeTest method * * @param Model $model * @return void */ public function beforeTest(Model $model) { if (!isset($model->beforeTestResult)) { $model->beforeTestResult = array(); } $model->beforeTestResult[] = strtolower(get_class($this)); return strtolower(get_class($this)); } /** * testMethod method * * @param Model $model * @param bool $param * @return void */ public function testMethod(Model $model, $param = true) { if ($param === true) { return 'working'; } } /** * testData method * * @param Model $model * @return void */ public function testData(Model $model) { if (!isset($model->data['Apple']['field'])) { return false; } $model->data['Apple']['field_2'] = true; return true; } /** * validateField method * * @param Model $model * @param string|array $field * @return void */ public function validateField(Model $model, $field) { return current($field) === 'Orange'; } /** * speakEnglish method * * @param Model $model * @param string $method * @param string $query * @return void */ public function speakEnglish(Model $model, $method, $query) { $method = preg_replace('/look for\s+/', 'Item.name = \'', $method); $query = preg_replace('/^in\s+/', 'Location.name = \'', $query); return $method . '\' AND ' . $query . '\''; } } /** * Test2Behavior class * * @package Cake.Test.Case.Model */ class Test2Behavior extends TestBehavior { public $mapMethods = array('/mappingRobot(\w+)/' => 'mapped'); public function resolveMethod(Model $model, $stuff) { } public function mapped(Model $model, $method, $query) { } } /** * Test3Behavior class * * @package Cake.Test.Case.Model */ class Test3Behavior extends TestBehavior { } /** * Test4Behavior class * * @package Cake.Test.Case.Model */ class Test4Behavior extends ModelBehavior { public function setup(Model $model, $config = null) { $model->bindModel( array('hasMany' => array('Comment')) ); } } /** * Test5Behavior class * * @package Cake.Test.Case.Model */ class Test5Behavior extends ModelBehavior { public function setup(Model $model, $config = null) { $model->bindModel( array('belongsTo' => array('User')) ); } } /** * Test6Behavior class * * @package Cake.Test.Case.Model */ class Test6Behavior extends ModelBehavior { public function setup(Model $model, $config = null) { $model->bindModel( array('hasAndBelongsToMany' => array('Tag')) ); } } /** * Test7Behavior class * * @package Cake.Test.Case.Model */ class Test7Behavior extends ModelBehavior { public function setup(Model $model, $config = null) { $model->bindModel( array('hasOne' => array('Attachment')) ); } } /** * Extended TestBehavior */ class TestAliasBehavior extends TestBehavior { } /** * FirstBehavior */ class FirstBehavior extends ModelBehavior { public function beforeFind(Model $model, $query = array()) { $model->called[] = get_class($this); return $query; } } /** * SecondBehavior */ class SecondBehavior extends FirstBehavior { } /** * ThirdBehavior */ class ThirdBehavior extends FirstBehavior { } /** * Orangutan Model */ class Orangutan extends Monkey { public $called = array(); } /** * BehaviorCollection class * * @package Cake.Test.Case.Model */ class BehaviorCollectionTest extends CakeTestCase { /** * fixtures property * * @var array */ public $fixtures = array( 'core.apple', 'core.sample', 'core.article', 'core.user', 'core.comment', 'core.attachment', 'core.tag', 'core.articles_tag', 'core.translate', 'core.device' ); /** * Test load() with enabled => false * * @return void */ public function testLoadDisabled() { $Apple = new Apple(); $this->assertSame(array(), $Apple->Behaviors->loaded()); $Apple->Behaviors->load('Translate', array('enabled' => false)); $this->assertTrue($Apple->Behaviors->loaded('Translate')); $this->assertFalse($Apple->Behaviors->enabled('Translate')); } /** * Tests loading aliased behaviors * * @return void */ public function testLoadAlias() { $Apple = new Apple(); $this->assertSame(array(), $Apple->Behaviors->loaded()); $Apple->Behaviors->load('Test', array('className' => 'TestAlias', 'somesetting' => true)); $this->assertSame(array('Test'), $Apple->Behaviors->loaded()); $this->assertInstanceOf('TestAliasBehavior', $Apple->Behaviors->Test); $this->assertTrue($Apple->Behaviors->Test->settings['Apple']['somesetting']); $this->assertEquals('working', $Apple->Behaviors->Test->testMethod($Apple, true)); $this->assertEquals('working', $Apple->testMethod(true)); $this->assertEquals('working', $Apple->Behaviors->dispatchMethod($Apple, 'testMethod')); App::build(array('Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS))); CakePlugin::load('TestPlugin'); $this->assertTrue($Apple->Behaviors->load('SomeOther', array('className' => 'TestPlugin.TestPluginPersisterOne'))); $this->assertInstanceOf('TestPluginPersisterOneBehavior', $Apple->Behaviors->SomeOther); $result = $Apple->Behaviors->loaded(); $this->assertEquals(array('Test', 'SomeOther'), $result, 'loaded() results are wrong.'); App::build(); CakePlugin::unload(); } /** * testBehaviorBinding method * * @return void */ public function testBehaviorBinding() { $Apple = new Apple(); $this->assertSame(array(), $Apple->Behaviors->loaded()); $Apple->Behaviors->load('Test', array('key' => 'value')); $this->assertSame(array('Test'), $Apple->Behaviors->loaded()); $this->assertEquals('testbehavior', strtolower(get_class($Apple->Behaviors->Test))); $expected = array('beforeFind' => 'on', 'afterFind' => 'off', 'key' => 'value'); $this->assertEquals($expected, $Apple->Behaviors->Test->settings['Apple']); $this->assertEquals(array('priority', 'Apple'), array_keys($Apple->Behaviors->Test->settings)); $this->assertSame($Apple->Sample->Behaviors->loaded(), array()); $Apple->Sample->Behaviors->load('Test', array('key2' => 'value2')); $this->assertSame($Apple->Sample->Behaviors->loaded(), array('Test')); $this->assertEquals(array('beforeFind' => 'on', 'afterFind' => 'off', 'key2' => 'value2'), $Apple->Sample->Behaviors->Test->settings['Sample']); $this->assertEquals(array('priority', 'Apple', 'Sample'), array_keys($Apple->Behaviors->Test->settings)); $this->assertSame( $Apple->Sample->Behaviors->Test->settings, $Apple->Behaviors->Test->settings ); $this->assertNotSame($Apple->Behaviors->Test->settings['Apple'], $Apple->Sample->Behaviors->Test->settings['Sample']); $Apple->Behaviors->load('Test', array('key2' => 'value2', 'key3' => 'value3', 'beforeFind' => 'off')); $Apple->Sample->Behaviors->load('Test', array('key' => 'value', 'key3' => 'value3', 'beforeFind' => 'off')); $this->assertEquals(array('beforeFind' => 'off', 'afterFind' => 'off', 'key' => 'value', 'key2' => 'value2', 'key3' => 'value3'), $Apple->Behaviors->Test->settings['Apple']); $this->assertEquals($Apple->Behaviors->Test->settings['Apple'], $Apple->Sample->Behaviors->Test->settings['Sample']); $this->assertFalse(isset($Apple->Child->Behaviors->Test)); $Apple->Child->Behaviors->load('Test', array('key' => 'value', 'key2' => 'value2', 'key3' => 'value3', 'beforeFind' => 'off')); $this->assertEquals($Apple->Child->Behaviors->Test->settings['Child'], $Apple->Sample->Behaviors->Test->settings['Sample']); $this->assertFalse(isset($Apple->Parent->Behaviors->Test)); $Apple->Parent->Behaviors->load('Test', array('key' => 'value', 'key2' => 'value2', 'key3' => 'value3', 'beforeFind' => 'off')); $this->assertEquals($Apple->Parent->Behaviors->Test->settings['Parent'], $Apple->Sample->Behaviors->Test->settings['Sample']); $Apple->Parent->Behaviors->load('Test', array('key' => 'value', 'key2' => 'value', 'key3' => 'value', 'beforeFind' => 'off')); $this->assertNotEquals($Apple->Parent->Behaviors->Test->settings['Parent'], $Apple->Sample->Behaviors->Test->settings['Sample']); $Apple->Behaviors->load('Plugin.Test', array('key' => 'new value')); $expected = array( 'beforeFind' => 'off', 'afterFind' => 'off', 'key' => 'new value', 'key2' => 'value2', 'key3' => 'value3' ); $this->assertEquals($expected, $Apple->Behaviors->Test->settings['Apple']); $current = $Apple->Behaviors->Test->settings['Apple']; $expected = array_merge($current, array('mangle' => 'trigger mangled')); $Apple->Behaviors->load('Test', array('mangle' => 'trigger')); $this->assertEquals($expected, $Apple->Behaviors->Test->settings['Apple']); $Apple->Behaviors->load('Test'); $expected = array_merge($current, array('mangle' => 'trigger mangled mangled')); $this->assertEquals($expected, $Apple->Behaviors->Test->settings['Apple']); $Apple->Behaviors->load('Test', array('mangle' => 'trigger')); $expected = array_merge($current, array('mangle' => 'trigger mangled')); $this->assertEquals($expected, $Apple->Behaviors->Test->settings['Apple']); } /** * test that attach()/detach() works with plugin.banana * * @return void */ public function testDetachWithPluginNames() { $Apple = new Apple(); $Apple->Behaviors->load('Plugin.Test'); $this->assertTrue(isset($Apple->Behaviors->Test), 'Missing behavior'); $this->assertEquals(array('Test'), $Apple->Behaviors->loaded()); $Apple->Behaviors->unload('Plugin.Test'); $this->assertEquals(array(), $Apple->Behaviors->loaded()); $Apple->Behaviors->load('Plugin.Test'); $this->assertTrue(isset($Apple->Behaviors->Test), 'Missing behavior'); $this->assertEquals(array('Test'), $Apple->Behaviors->loaded()); $Apple->Behaviors->unload('Test'); $this->assertEquals(array(), $Apple->Behaviors->loaded()); } /** * test that attaching a non existent Behavior triggers a cake error. * * @expectedException MissingBehaviorException * @return void */ public function testInvalidBehaviorCausingCakeError() { $Apple = new Apple(); $Apple->Behaviors->load('NoSuchBehavior'); } /** * testBehaviorToggling method * * @return void */ public function testBehaviorToggling() { $Apple = new Apple(); $this->assertSame($Apple->Behaviors->enabled(), array()); $Apple->Behaviors->init('Apple', array('Test' => array('key' => 'value'))); $this->assertSame($Apple->Behaviors->enabled(), array('Test')); $Apple->Behaviors->disable('Test'); $this->assertSame(array('Test'), $Apple->Behaviors->loaded()); $this->assertSame($Apple->Behaviors->enabled(), array()); $Apple->Sample->Behaviors->load('Test'); $this->assertTrue($Apple->Sample->Behaviors->enabled('Test')); $this->assertSame($Apple->Behaviors->enabled(), array()); $Apple->Behaviors->enable('Test'); $this->assertTrue($Apple->Behaviors->loaded('Test')); $this->assertSame($Apple->Behaviors->enabled(), array('Test')); $Apple->Behaviors->disable('Test'); $this->assertSame($Apple->Behaviors->enabled(), array()); $Apple->Behaviors->load('Test', array('enabled' => true)); $this->assertSame($Apple->Behaviors->enabled(), array('Test')); $Apple->Behaviors->load('Test', array('enabled' => false)); $this->assertSame($Apple->Behaviors->enabled(), array()); $Apple->Behaviors->unload('Test'); $this->assertSame($Apple->Behaviors->enabled(), array()); } /** * testBehaviorFindCallbacks method * * @return void */ public function testBehaviorFindCallbacks() { $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.'); $Apple = new Apple(); $expected = $Apple->find('all'); $Apple->Behaviors->load('Test'); $this->assertNull($Apple->find('all')); $Apple->Behaviors->load('Test', array('beforeFind' => 'off')); $this->assertSame($expected, $Apple->find('all')); $Apple->Behaviors->load('Test', array('beforeFind' => 'test')); $this->assertSame($expected, $Apple->find('all')); $Apple->Behaviors->load('Test', array('beforeFind' => 'modify')); $expected2 = array( array('Apple' => array('id' => '1', 'name' => 'Red Apple 1', 'mytime' => '22:57:17')), array('Apple' => array('id' => '2', 'name' => 'Bright Red Apple', 'mytime' => '22:57:17')), array('Apple' => array('id' => '3', 'name' => 'green blue', 'mytime' => '22:57:17')) ); $result = $Apple->find('all', array('conditions' => array('Apple.id <' => '4'))); $this->assertEquals($expected2, $result); $Apple->Behaviors->disable('Test'); $result = $Apple->find('all'); $this->assertEquals($expected, $result); $Apple->Behaviors->load('Test', array('beforeFind' => 'off', 'afterFind' => 'on')); $this->assertSame($Apple->find('all'), array()); $Apple->Behaviors->load('Test', array('afterFind' => 'off')); $this->assertEquals($expected, $Apple->find('all')); $Apple->Behaviors->load('Test', array('afterFind' => 'test')); $this->assertEquals($expected, $Apple->find('all')); $Apple->Behaviors->load('Test', array('afterFind' => 'test2')); $this->assertEquals($expected, $Apple->find('all')); $Apple->Behaviors->load('Test', array('afterFind' => 'modify')); $expected = array( array('id' => '1', 'apple_id' => '2', 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17'), array('id' => '2', 'apple_id' => '1', 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17'), array('id' => '3', 'apple_id' => '2', 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17'), array('id' => '4', 'apple_id' => '2', 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17'), array('id' => '5', 'apple_id' => '5', 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17'), array('id' => '6', 'apple_id' => '4', 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17'), array('id' => '7', 'apple_id' => '6', 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17') ); $this->assertEquals($expected, $Apple->find('all')); } /** * testBehaviorHasManyFindCallbacks method * * @return void */ public function testBehaviorHasManyFindCallbacks() { $Apple = new Apple(); $Apple->unbindModel(array('hasOne' => array('Sample'), 'belongsTo' => array('Parent')), false); $expected = $Apple->find('all'); $Apple->unbindModel(array('hasMany' => array('Child'))); $wellBehaved = $Apple->find('all'); $Apple->Child->Behaviors->load('Test', array('afterFind' => 'modify')); $Apple->unbindModel(array('hasMany' => array('Child'))); $this->assertSame($Apple->find('all'), $wellBehaved); $Apple->Child->Behaviors->load('Test', array('before' => 'off')); $this->assertSame($expected, $Apple->find('all')); $Apple->Child->Behaviors->load('Test', array('before' => 'test')); $this->assertSame($expected, $Apple->find('all')); $Apple->Child->Behaviors->load('Test', array('before' => 'modify')); $result = $Apple->find('all', array('fields' => array('Apple.id'), 'conditions' => array('Apple.id <' => '4'))); $Apple->Child->Behaviors->disable('Test'); $result = $Apple->find('all'); $this->assertEquals($expected, $result); $Apple->Child->Behaviors->load('Test', array('before' => 'off', 'after' => 'on')); $Apple->Child->Behaviors->load('Test', array('after' => 'off')); $this->assertEquals($expected, $Apple->find('all')); $Apple->Child->Behaviors->load('Test', array('after' => 'test')); $this->assertEquals($expected, $Apple->find('all')); $Apple->Child->Behaviors->load('Test', array('after' => 'test2')); $this->assertEquals($expected, $Apple->find('all')); } /** * testBehaviorHasOneFindCallbacks method * * @return void */ public function testBehaviorHasOneFindCallbacks() { $Apple = new Apple(); $Apple->unbindModel(array('hasMany' => array('Child'), 'belongsTo' => array('Parent')), false); $expected = $Apple->find('all'); $Apple->unbindModel(array('hasOne' => array('Sample'))); $wellBehaved = $Apple->find('all'); $Apple->Sample->Behaviors->load('Test'); $Apple->unbindModel(array('hasOne' => array('Sample'))); $this->assertSame($Apple->find('all'), $wellBehaved); $Apple->Sample->Behaviors->load('Test', array('before' => 'off')); $this->assertSame($expected, $Apple->find('all')); $Apple->Sample->Behaviors->load('Test', array('before' => 'test')); $this->assertSame($expected, $Apple->find('all')); $Apple->Sample->Behaviors->disable('Test'); $result = $Apple->find('all'); $this->assertEquals($expected, $result); $Apple->Sample->Behaviors->load('Test', array('after' => 'off')); $this->assertEquals($expected, $Apple->find('all')); $Apple->Sample->Behaviors->load('Test', array('after' => 'test')); $this->assertEquals($expected, $Apple->find('all')); $Apple->Sample->Behaviors->load('Test', array('after' => 'test2')); $this->assertEquals($expected, $Apple->find('all')); } /** * testBehaviorBelongsToFindCallbacks method * * @return void */ public function testBehaviorBelongsToFindCallbacks() { $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.'); $conditions = array('order' => 'Apple.id ASC'); $Apple = new Apple(); $Apple->unbindModel(array('hasMany' => array('Child'), 'hasOne' => array('Sample')), false); $expected = $Apple->find('all', $conditions); $Apple->unbindModel(array('belongsTo' => array('Parent'))); $wellBehaved = $Apple->find('all', $conditions); $Apple->Parent->Behaviors->load('Test'); $Apple->unbindModel(array('belongsTo' => array('Parent'))); $this->assertSame($Apple->find('all', $conditions), $wellBehaved); $Apple->Parent->Behaviors->load('Test', array('before' => 'off')); $this->assertSame($expected, $Apple->find('all', $conditions)); $Apple->Parent->Behaviors->load('Test', array('before' => 'test')); $this->assertSame($expected, $Apple->find('all', $conditions)); $Apple->Parent->Behaviors->load('Test', array('before' => 'modify')); $expected2 = array( array( 'Apple' => array('id' => 1), 'Parent' => array('id' => 2, 'name' => 'Bright Red Apple', 'mytime' => '22:57:17')), array( 'Apple' => array('id' => 2), 'Parent' => array('id' => 1, 'name' => 'Red Apple 1', 'mytime' => '22:57:17')), array( 'Apple' => array('id' => 3), 'Parent' => array('id' => 2, 'name' => 'Bright Red Apple', 'mytime' => '22:57:17')) ); $result2 = $Apple->find('all', array( 'fields' => array('Apple.id', 'Parent.id', 'Parent.name', 'Parent.mytime'), 'conditions' => array('Apple.id <' => '4'), 'order' => 'Apple.id ASC', )); $this->assertEquals($expected2, $result2); $Apple->Parent->Behaviors->disable('Test'); $result = $Apple->find('all', $conditions); $this->assertEquals($expected, $result); $Apple->Parent->Behaviors->load('Test', array('after' => 'off')); $this->assertEquals($expected, $Apple->find('all', $conditions)); $Apple->Parent->Behaviors->load('Test', array('after' => 'test')); $this->assertEquals($expected, $Apple->find('all', $conditions)); $Apple->Parent->Behaviors->load('Test', array('after' => 'test2')); $this->assertEquals($expected, $Apple->find('all', $conditions)); } /** * testBehaviorSaveCallbacks method * * @return void */ public function testBehaviorSaveCallbacks() { $Sample = new Sample(); $record = array('Sample' => array('apple_id' => 6, 'name' => 'sample99')); $Sample->Behaviors->load('Test', array('beforeSave' => 'on')); $Sample->create(); $this->assertSame(false, $Sample->save($record)); $Sample->Behaviors->load('Test', array('beforeSave' => 'off')); $Sample->create(); $result = $Sample->save($record); $expected = $record; $expected['Sample']['id'] = $Sample->id; $this->assertSame($expected, $result); $Sample->Behaviors->load('Test', array('beforeSave' => 'test')); $Sample->create(); $result = $Sample->save($record); $expected = $record; $expected['Sample']['id'] = $Sample->id; $this->assertSame($expected, $result); $Sample->Behaviors->load('Test', array('beforeSave' => 'modify')); $expected = Hash::insert($record, 'Sample.name', 'sample99 modified before'); $Sample->create(); $result = $Sample->save($record); $expected['Sample']['id'] = $Sample->id; $this->assertSame($expected, $result); $Sample->Behaviors->disable('Test'); $this->assertSame($record, $Sample->save($record)); $Sample->Behaviors->load('Test', array('beforeSave' => 'off', 'afterSave' => 'on')); $expected = Hash::merge($record, array('Sample' => array('aftersave' => 'modified after on create'))); $Sample->create(); $result = $Sample->save($record); $expected['Sample']['id'] = $Sample->id; $this->assertEquals($expected, $result); $Sample->Behaviors->load('Test', array('beforeSave' => 'modify', 'afterSave' => 'modify')); $expected = Hash::merge($record, array('Sample' => array('name' => 'sample99 modified before modified after on create'))); $Sample->create(); $result = $Sample->save($record); $expected['Sample']['id'] = $Sample->id; $this->assertSame($expected, $result); $Sample->Behaviors->load('Test', array('beforeSave' => 'off', 'afterSave' => 'test')); $Sample->create(); $expected = $record; unset($expected['Sample']['name']); $result = $Sample->save($record); $expected['Sample']['id'] = $Sample->id; $this->assertSame($expected, $result); $Sample->Behaviors->load('Test', array('afterSave' => 'test2')); $Sample->create(); $expected = $record; $result = $Sample->save($record); $expected['Sample']['id'] = $Sample->id; $this->assertSame($expected, $result); $Sample->Behaviors->load('Test', array('beforeFind' => 'off', 'afterFind' => 'off')); $Sample->recursive = -1; $record2 = $Sample->read(null, 1); $Sample->Behaviors->load('Test', array('afterSave' => 'on')); $expected = Hash::merge($record2, array('Sample' => array('aftersave' => 'modified after'))); $Sample->create(); $this->assertSame($expected, $Sample->save($record2)); $Sample->Behaviors->load('Test', array('afterSave' => 'modify')); $expected = Hash::merge($record2, array('Sample' => array('name' => 'sample1 modified after'))); $Sample->create(); $this->assertSame($expected, $Sample->save($record2)); } /** * testBehaviorDeleteCallbacks method * * @return void */ public function testBehaviorDeleteCallbacks() { $Apple = new Apple(); $Apple->Behaviors->load('Test', array('beforeFind' => 'off', 'beforeDelete' => 'off')); $this->assertTrue($Apple->delete(6)); $Apple->Behaviors->load('Test', array('beforeDelete' => 'on')); $this->assertFalse($Apple->delete(4)); $Apple->Behaviors->load('Test', array('beforeDelete' => 'test2')); ob_start(); $results = $Apple->delete(4); $this->assertSame(trim(ob_get_clean()), 'beforeDelete success (cascading)'); $this->assertTrue($results); ob_start(); $results = $Apple->delete(3, false); $this->assertSame(trim(ob_get_clean()), 'beforeDelete success'); $this->assertTrue($results); $Apple->Behaviors->load('Test', array('beforeDelete' => 'off', 'afterDelete' => 'on')); ob_start(); $results = $Apple->delete(2, false); $this->assertSame(trim(ob_get_clean()), 'afterDelete success'); $this->assertTrue($results); } /** * testBehaviorOnErrorCallback method * * @return void */ public function testBehaviorOnErrorCallback() { $Apple = new Apple(); $Apple->Behaviors->load('Test', array('beforeFind' => 'off', 'onError' => 'on')); ob_start(); $Apple->Behaviors->Test->onError($Apple, ''); $this->assertSame(trim(ob_get_clean()), 'onError trigger success'); } /** * testBehaviorValidateCallback method * * @return void */ public function testBehaviorValidateCallback() { $Apple = new Apple(); $Apple->Behaviors->load('Test'); $this->assertTrue($Apple->validates()); $Apple->Behaviors->load('Test', array('validate' => 'on')); $this->assertFalse($Apple->validates()); $this->assertSame($Apple->validationErrors, array('name' => array(true))); $Apple->Behaviors->load('Test', array('validate' => 'stop')); $this->assertFalse($Apple->validates()); $this->assertSame($Apple->validationErrors, array('name' => array(true, true))); $Apple->Behaviors->load('Test', array('validate' => 'whitelist')); $Apple->validates(); $this->assertSame($Apple->whitelist, array()); $Apple->whitelist = array('unknown'); $Apple->validates(); $this->assertSame($Apple->whitelist, array('unknown', 'name')); } /** * testBehaviorValidateAfterCallback method * * @return void */ public function testBehaviorValidateAfterCallback() { $Apple = new Apple(); $Apple->Behaviors->load('Test'); $this->assertTrue($Apple->validates()); $Apple->Behaviors->load('Test', array('afterValidate' => 'on')); $this->assertTrue($Apple->validates()); $this->assertSame($Apple->validationErrors, array()); $Apple->Behaviors->load('Test', array('afterValidate' => 'test')); $Apple->data = array('bar'); $Apple->validates(); $this->assertEquals(array('foo'), $Apple->data); } /** * testBehaviorValidateMethods method * * @return void */ public function testBehaviorValidateMethods() { $Apple = new Apple(); $Apple->Behaviors->load('Test'); $Apple->validate['color'] = 'validateField'; $result = $Apple->save(array('name' => 'Genetically Modified Apple', 'color' => 'Orange')); $this->assertEquals(array('name', 'color', 'modified', 'created', 'id'), array_keys($result['Apple'])); $Apple->create(); $result = $Apple->save(array('name' => 'Regular Apple', 'color' => 'Red')); $this->assertFalse($result); } /** * testBehaviorMethodDispatching method * * @return void */ public function testBehaviorMethodDispatching() { $Apple = new Apple(); $Apple->Behaviors->load('Test'); $expected = 'working'; $this->assertEquals($expected, $Apple->testMethod()); $this->assertEquals($expected, $Apple->Behaviors->dispatchMethod($Apple, 'testMethod')); $result = $Apple->Behaviors->dispatchMethod($Apple, 'wtf'); $this->assertEquals(array('unhandled'), $result); $result = $Apple->{'look for the remote'}('in the couch'); $expected = "Item.name = 'the remote' AND Location.name = 'the couch'"; $this->assertEquals($expected, $result); $result = $Apple->{'look for THE REMOTE'}('in the couch'); $expected = "Item.name = 'THE REMOTE' AND Location.name = 'the couch'"; $this->assertEquals($expected, $result, 'Mapped method was lowercased.'); } /** * testBehaviorMethodDispatchingWithData method * * @return void */ public function testBehaviorMethodDispatchingWithData() { $Apple = new Apple(); $Apple->Behaviors->load('Test'); $Apple->set('field', 'value'); $this->assertTrue($Apple->testData()); $this->assertTrue($Apple->data['Apple']['field_2']); $this->assertTrue($Apple->testData('one', 'two', 'three', 'four', 'five', 'six')); } /** * undocumented function * * @return void */ public function testBindModelCallsInBehaviors() { // hasMany $Article = new Article(); $Article->unbindModel(array('hasMany' => array('Comment'))); $result = $Article->find('first'); $this->assertFalse(array_key_exists('Comment', $result)); $Article->Behaviors->load('Test4'); $result = $Article->find('first'); $this->assertTrue(array_key_exists('Comment', $result)); // belongsTo $Article->unbindModel(array('belongsTo' => array('User'))); $result = $Article->find('first'); $this->assertFalse(array_key_exists('User', $result)); $Article->Behaviors->load('Test5'); $result = $Article->find('first'); $this->assertTrue(array_key_exists('User', $result)); // hasAndBelongsToMany $Article->unbindModel(array('hasAndBelongsToMany' => array('Tag'))); $result = $Article->find('first'); $this->assertFalse(array_key_exists('Tag', $result)); $Article->Behaviors->load('Test6'); $result = $Article->find('first'); $this->assertTrue(array_key_exists('Comment', $result)); // hasOne $Comment = new Comment(); $Comment->unbindModel(array('hasOne' => array('Attachment'))); $result = $Comment->find('first'); $this->assertFalse(array_key_exists('Attachment', $result)); $Comment->Behaviors->load('Test7'); $result = $Comment->find('first'); $this->assertTrue(array_key_exists('Attachment', $result)); } /** * Test attach and detaching * * @return void */ public function testBehaviorAttachAndDetach() { $Sample = new Sample(); $Sample->actsAs = array('Test3' => array('bar'), 'Test2' => array('foo', 'bar')); $Sample->Behaviors->init($Sample->alias, $Sample->actsAs); $Sample->Behaviors->load('Test2'); $Sample->Behaviors->unload('Test3'); $Sample->Behaviors->trigger('beforeTest', array(&$Sample)); } /** * test that hasMethod works with basic functions. * * @return void */ public function testHasMethodBasic() { new Sample(); $Collection = new BehaviorCollection(); $Collection->init('Sample', array('Test', 'Test2')); $this->assertTrue($Collection->hasMethod('testMethod')); $this->assertTrue($Collection->hasMethod('resolveMethod')); $this->assertFalse($Collection->hasMethod('No method')); } /** * test that hasMethod works with mapped methods. * * @return void */ public function testHasMethodMappedMethods() { new Sample(); $Collection = new BehaviorCollection(); $Collection->init('Sample', array('Test', 'Test2')); $this->assertTrue($Collection->hasMethod('look for the remote in the couch')); $this->assertTrue($Collection->hasMethod('mappingRobotOnTheRoof')); } /** * test hasMethod returning a 'callback' * * @return void */ public function testHasMethodAsCallback() { new Sample(); $Collection = new BehaviorCollection(); $Collection->init('Sample', array('Test', 'Test2')); $result = $Collection->hasMethod('testMethod', true); $expected = array('Test', 'testMethod'); $this->assertEquals($expected, $result); $result = $Collection->hasMethod('resolveMethod', true); $expected = array('Test2', 'resolveMethod'); $this->assertEquals($expected, $result); $result = $Collection->hasMethod('mappingRobotOnTheRoof', true); $expected = array('Test2', 'mapped', 'mappingRobotOnTheRoof'); $this->assertEquals($expected, $result); } /** * Test that behavior priority * * @return void */ public function testBehaviorOrderCallbacks() { $model = ClassRegistry::init('Orangutan'); $model->Behaviors->init('Orangutan', array( 'Second' => array('priority' => 9), 'Third', 'First' => array('priority' => 8), )); $this->assertEmpty($model->called); $model->find('first'); $expected = array( 'FirstBehavior', 'SecondBehavior', 'ThirdBehavior', ); $this->assertEquals($expected, $model->called); $model->called = array(); $model->Behaviors->load('Third', array('priority' => 1)); $model->find('first'); $expected = array( 'ThirdBehavior', 'FirstBehavior', 'SecondBehavior' ); $this->assertEquals($expected, $model->called); $model->called = array(); $model->Behaviors->load('First'); $model->find('first'); $expected = array( 'ThirdBehavior', 'SecondBehavior', 'FirstBehavior' ); $this->assertEquals($expected, $model->called); $model->called = array(); $model->Behaviors->unload('Third'); $model->find('first'); $expected = array( 'SecondBehavior', 'FirstBehavior' ); $this->assertEquals($expected, $model->called); $model->called = array(); $model->Behaviors->disable('Second'); $model->find('first'); $expected = array( 'FirstBehavior' ); $this->assertEquals($expected, $model->called); $model->called = array(); $model->Behaviors->enable('Second'); $model->find('first'); $expected = array( 'SecondBehavior', 'FirstBehavior' ); $this->assertEquals($expected, $model->called); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/CakeSchemaTest.php000066400000000000000000000707571265552240500227620ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model * @since CakePHP(tm) v 1.2.0.5550 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('CakeSchema', 'Model'); App::uses('CakeTestFixture', 'TestSuite/Fixture'); /** * Test for Schema database management * * @package Cake.Test.Case.Model */ class MyAppSchema extends CakeSchema { /** * connection property * * @var string */ public $connection = 'test'; /** * comments property * * @var array */ public $comments = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'user_id' => array('type' => 'integer', 'null' => false), 'title' => array('type' => 'string', 'null' => false, 'length' => 100), 'comment' => array('type' => 'text', 'null' => false, 'default' => null), 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1), 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)), ); /** * posts property * * @var array */ public $posts = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'author_id' => array('type' => 'integer', 'null' => true, 'default' => ''), 'title' => array('type' => 'string', 'null' => false, 'default' => 'Title'), 'body' => array('type' => 'text', 'null' => true, 'default' => null), 'summary' => array('type' => 'text', 'null' => true), 'published' => array('type' => 'string', 'null' => true, 'default' => 'Y', 'length' => 1), 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)), ); /** * _foo property * * @var array */ protected $_foo = array('bar'); /** * getVar method * * @param string $var Name of var * @return mixed */ public function getVar($var) { if (!isset($this->$var)) { return null; } return $this->$var; } } /** * TestAppSchema class * * @package Cake.Test.Case.Model */ class TestAppSchema extends CakeSchema { /** * name property * * @var string */ public $name = 'MyApp'; /** * comments property * * @var array */ public $comments = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'article_id' => array('type' => 'integer', 'null' => false), 'user_id' => array('type' => 'integer', 'null' => false), 'comment' => array('type' => 'text', 'null' => true, 'default' => null), 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1), 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)), 'tableParameters' => array(), ); /** * posts property * * @var array */ public $posts = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'author_id' => array('type' => 'integer', 'null' => false), 'title' => array('type' => 'string', 'null' => false), 'body' => array('type' => 'text', 'null' => true, 'default' => null), 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1), 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)), 'tableParameters' => array(), ); /** * posts_tags property * * @var array */ public $posts_tags = array( 'post_id' => array('type' => 'integer', 'null' => false, 'key' => 'primary'), 'tag_id' => array('type' => 'string', 'null' => false, 'key' => 'primary'), 'indexes' => array('posts_tag' => array('column' => array('tag_id', 'post_id'), 'unique' => 1)), 'tableParameters' => array() ); /** * tags property * * @var array */ public $tags = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'tag' => array('type' => 'string', 'null' => false), 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)), 'tableParameters' => array() ); /** * datatypes property * * @var array */ public $datatypes = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'float_field' => array('type' => 'float', 'null' => false, 'length' => '5,2', 'default' => ''), 'decimal_field' => array('type' => 'decimal', 'length' => '6,3', 'default' => '0.000'), 'huge_int' => array('type' => 'biginteger'), 'bool' => array('type' => 'boolean', 'null' => false, 'default' => false), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)), 'tableParameters' => array() ); /** * setup method * * @param mixed $version * @return void */ public function setup($version) { } /** * teardown method * * @param mixed $version * @return void */ public function teardown($version) { } } /** * SchemaPost class * * @package Cake.Test.Case.Model */ class SchemaPost extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'posts'; /** * hasMany property * * @var array */ public $hasMany = array('SchemaComment'); /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('SchemaTag'); } /** * SchemaComment class * * @package Cake.Test.Case.Model */ class SchemaComment extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'comments'; /** * belongsTo property * * @var array */ public $belongsTo = array('SchemaPost'); } /** * SchemaTag class * * @package Cake.Test.Case.Model */ class SchemaTag extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'tags'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('SchemaPost'); } /** * SchemaDatatype class * * @package Cake.Test.Case.Model */ class SchemaDatatype extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'datatypes'; } /** * Testdescribe class * * This class is defined purely to inherit the cacheSources variable otherwise * testSchemaCreateTable will fail if listSources has already been called and * its source cache populated - I.e. if the test is run within a group * * @uses CakeTestModel * @package Cake.Test.Case.Model */ class Testdescribe extends CakeTestModel { } /** * SchemaCrossDatabase class * * @package Cake.Test.Case.Model */ class SchemaCrossDatabase extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'cross_database'; /** * useDbConfig property * * @var string */ public $useDbConfig = 'test2'; } /** * SchemaCrossDatabaseFixture class * * @package Cake.Test.Case.Model */ class SchemaCrossDatabaseFixture extends CakeTestFixture { /** * name property * * @var string */ public $name = 'CrossDatabase'; /** * table property * * @var string */ public $table = 'cross_database'; /** * fields property * * @var array */ public $fields = array( 'id' => array('type' => 'integer', 'key' => 'primary'), 'name' => 'string' ); /** * records property * * @var array */ public $records = array( array('id' => 1, 'name' => 'First'), array('id' => 2, 'name' => 'Second'), ); } /** * SchemaPrefixAuthUser class * * @package Cake.Test.Case.Model */ class SchemaPrefixAuthUser extends CakeTestModel { /** * table prefix * * @var string */ public $tablePrefix = 'auth_'; /** * useTable * * @var string */ public $useTable = 'users'; } /** * CakeSchemaTest * * @package Cake.Test.Case.Model */ class CakeSchemaTest extends CakeTestCase { /** * fixtures property * * @var array */ public $fixtures = array( 'core.post', 'core.tag', 'core.posts_tag', 'core.test_plugin_comment', 'core.datatype', 'core.auth_user', 'core.author', 'core.test_plugin_article', 'core.user', 'core.comment', 'core.prefix_test' ); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); ConnectionManager::getDataSource('test')->cacheSources = false; $this->Schema = new TestAppSchema(); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); if (file_exists(TMP . 'tests' . DS . 'schema.php')) { unlink(TMP . 'tests' . DS . 'schema.php'); } unset($this->Schema); CakePlugin::unload(); } /** * testSchemaName method * * @return void */ public function testSchemaName() { $Schema = new CakeSchema(); $this->assertEquals('App', $Schema->name); } /** * testSchemaRead method * * @return void */ public function testSchemaRead() { $read = $this->Schema->read(array( 'connection' => 'test', 'name' => 'TestApp', 'models' => array('SchemaPost', 'SchemaComment', 'SchemaTag', 'SchemaDatatype') )); unset($read['tables']['missing']); $expected = array('comments', 'datatypes', 'posts', 'posts_tags', 'tags'); foreach ($expected as $table) { $this->assertTrue(isset($read['tables'][$table]), 'Missing table ' . $table); } foreach ($this->Schema->tables as $table => $fields) { $this->assertEquals(array_keys($fields), array_keys($read['tables'][$table])); } if (isset($read['tables']['datatypes']['float_field']['length'])) { $this->assertEquals( $read['tables']['datatypes']['float_field']['length'], $this->Schema->tables['datatypes']['float_field']['length'] ); } $this->assertEquals( $read['tables']['datatypes']['float_field']['type'], $this->Schema->tables['datatypes']['float_field']['type'] ); $this->assertEquals( $read['tables']['datatypes']['float_field']['null'], $this->Schema->tables['datatypes']['float_field']['null'] ); $db = ConnectionManager::getDataSource('test'); $config = $db->config; $config['prefix'] = 'schema_test_prefix_'; ConnectionManager::create('schema_prefix', $config); $read = $this->Schema->read(array('connection' => 'schema_prefix', 'models' => false)); $this->assertTrue(empty($read['tables'])); $read = $this->Schema->read(array( 'connection' => 'test', 'name' => 'TestApp', 'models' => array('SchemaComment', 'SchemaTag', 'SchemaPost') )); $this->assertFalse(isset($read['tables']['missing']['posts_tags']), 'Join table marked as missing'); } /** * testSchemaReadWithAppModel method * * @return void */ public function testSchemaReadWithAppModel() { $connections = ConnectionManager::enumConnectionObjects(); ConnectionManager::drop('default'); ConnectionManager::create('default', $connections['test']); try { $this->Schema->read(array( 'connection' => 'default', 'name' => 'TestApp', 'models' => array('AppModel') )); } catch(MissingTableException $mte) { ConnectionManager::drop('default'); $this->fail($mte->getMessage()); } ConnectionManager::drop('default'); } /** * testSchemaReadWithOddTablePrefix method * * @return void */ public function testSchemaReadWithOddTablePrefix() { $config = ConnectionManager::getDataSource('test')->config; $this->skipIf(!empty($config['prefix']), 'This test can not be executed with datasource prefix set.'); $SchemaPost = ClassRegistry::init('SchemaPost'); $SchemaPost->tablePrefix = 'po'; $SchemaPost->useTable = 'sts'; $read = $this->Schema->read(array( 'connection' => 'test', 'name' => 'TestApp', 'models' => array('SchemaPost') )); $this->assertFalse(isset($read['tables']['missing']['posts']), 'Posts table was not read from tablePrefix'); } /** * test read() with tablePrefix properties. * * @return void */ public function testSchemaReadWithTablePrefix() { $config = ConnectionManager::getDataSource('test')->config; $this->skipIf(!empty($config['prefix']), 'This test can not be executed with datasource prefix set.'); $Schema = new CakeSchema(); $read = $Schema->read(array( 'connection' => 'test', 'name' => 'TestApp', 'models' => array('SchemaPrefixAuthUser') )); unset($read['tables']['missing']); $this->assertTrue(isset($read['tables']['auth_users']), 'auth_users key missing %s'); } /** * test reading schema with config prefix. * * @return void */ public function testSchemaReadWithConfigPrefix() { $this->skipIf($this->db instanceof Sqlite, 'Cannot open 2 connections to Sqlite'); $db = ConnectionManager::getDataSource('test'); $config = $db->config; $this->skipIf(!empty($config['prefix']), 'This test can not be executed with datasource prefix set.'); $config['prefix'] = 'schema_test_prefix_'; ConnectionManager::create('schema_prefix', $config); $read = $this->Schema->read(array('connection' => 'schema_prefix', 'models' => false)); $this->assertTrue(empty($read['tables'])); $config['prefix'] = 'prefix_'; ConnectionManager::create('schema_prefix2', $config); $read = $this->Schema->read(array( 'connection' => 'schema_prefix2', 'name' => 'TestApp', 'models' => false)); $this->assertTrue(isset($read['tables']['prefix_tests'])); } /** * test reading schema from plugins. * * @return void */ public function testSchemaReadWithPlugins() { App::objects('model', null, false); App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); CakePlugin::load('TestPlugin'); $Schema = new CakeSchema(); $Schema->plugin = 'TestPlugin'; $read = $Schema->read(array( 'connection' => 'test', 'name' => 'TestApp', 'models' => true )); unset($read['tables']['missing']); $this->assertTrue(isset($read['tables']['auth_users'])); $this->assertTrue(isset($read['tables']['authors'])); $this->assertTrue(isset($read['tables']['test_plugin_comments'])); $this->assertTrue(isset($read['tables']['posts'])); $this->assertTrue(count($read['tables']) >= 4); App::build(); } /** * test reading schema with tables from another database. * * @return void */ public function testSchemaReadWithCrossDatabase() { $config = ConnectionManager::enumConnectionObjects(); $this->skipIf( !isset($config['test']) || !isset($config['test2']), 'Primary and secondary test databases not configured, ' . 'skipping cross-database join tests. ' . 'To run these tests, you must define $test and $test2 in your database configuration.' ); $db = ConnectionManager::getDataSource('test2'); $fixture = new SchemaCrossDatabaseFixture(); $fixture->create($db); $fixture->insert($db); $read = $this->Schema->read(array( 'connection' => 'test', 'name' => 'TestApp', 'models' => array('SchemaCrossDatabase', 'SchemaPost') )); $this->assertTrue(isset($read['tables']['posts'])); $this->assertFalse(isset($read['tables']['cross_database']), 'Cross database should not appear'); $this->assertFalse(isset($read['tables']['missing']['cross_database']), 'Cross database should not appear'); $read = $this->Schema->read(array( 'connection' => 'test2', 'name' => 'TestApp', 'models' => array('SchemaCrossDatabase', 'SchemaPost') )); $this->assertFalse(isset($read['tables']['posts']), 'Posts should not appear'); $this->assertFalse(isset($read['tables']['posts']), 'Posts should not appear'); $this->assertTrue(isset($read['tables']['cross_database'])); $fixture->drop($db); } /** * test that tables are generated correctly * * @return void */ public function testGenerateTable() { $posts = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'author_id' => array('type' => 'integer', 'null' => false), 'title' => array('type' => 'string', 'null' => false), 'body' => array('type' => 'text', 'null' => true, 'default' => null), 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1), 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => true)), ); $result = $this->Schema->generateTable('posts', $posts); $this->assertRegExp('/public \$posts/', $result); $posts = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'author_id' => array('type' => 'integer', 'null' => false), 'title' => array('type' => 'string', 'null' => false), 'body' => array('type' => 'text', 'null' => true, 'default' => null), 'published' => array('type' => 'string', 'null' => true, 'default' => 'N', 'length' => 1), 'created' => array('type' => 'datetime', 'null' => true, 'default' => null), 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => true), 'MyFtIndex' => array('column' => array('title', 'body'), 'type' => 'fulltext') ) ); $result = $this->Schema->generateTable('fields', $posts); $this->assertRegExp('/public \$fields/', $result); $this->assertRegExp('/\'type\' \=\> \'fulltext\'/', $result); } /** * testSchemaWrite method * * @return void */ public function testSchemaWrite() { $write = $this->Schema->write(array( 'name' => 'MyOtherApp', 'tables' => $this->Schema->tables, 'path' => TMP . 'tests' )); $file = file_get_contents(TMP . 'tests' . DS . 'schema.php'); $this->assertEquals($write, $file); require_once TMP . 'tests' . DS . 'schema.php'; $OtherSchema = new MyOtherAppSchema(); $this->assertEquals($this->Schema->tables, $OtherSchema->tables); } /** * testSchemaComparison method * * @return void */ public function testSchemaComparison() { $New = new MyAppSchema(); $compare = $New->compare($this->Schema); $expected = array( 'comments' => array( 'add' => array( 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'after' => 'id'), 'title' => array('type' => 'string', 'null' => false, 'length' => 100, 'after' => 'user_id'), ), 'drop' => array( 'article_id' => array('type' => 'integer', 'null' => false), 'tableParameters' => array(), ), 'change' => array( 'comment' => array('type' => 'text', 'null' => false, 'default' => null), ) ), 'posts' => array( 'add' => array( 'summary' => array('type' => 'text', 'null' => true, 'after' => 'body'), ), 'drop' => array( 'tableParameters' => array(), ), 'change' => array( 'author_id' => array('type' => 'integer', 'null' => true, 'default' => ''), 'title' => array('type' => 'string', 'null' => false, 'default' => 'Title'), 'published' => array('type' => 'string', 'null' => true, 'default' => 'Y', 'length' => 1) ) ), ); $this->assertEquals($expected, $compare); $this->assertNull($New->getVar('comments')); $this->assertEquals(array('bar'), $New->getVar('_foo')); $tables = array( 'missing' => array( 'categories' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'), 'created' => array('type' => 'datetime', 'null' => false, 'default' => null), 'modified' => array('type' => 'datetime', 'null' => false, 'default' => null), 'name' => array('type' => 'string', 'null' => false, 'default' => null, 'length' => 100), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)), 'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'MyISAM') ) ), 'ratings' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'), 'foreign_key' => array('type' => 'integer', 'null' => false, 'default' => null), 'model' => array('type' => 'varchar', 'null' => false, 'default' => null), 'value' => array('type' => 'float', 'null' => false, 'length' => '5,2', 'default' => null), 'created' => array('type' => 'datetime', 'null' => false, 'default' => null), 'modified' => array('type' => 'datetime', 'null' => false, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)), 'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'MyISAM') ) ); $compare = $New->compare($this->Schema, $tables); $expected = array( 'ratings' => array( 'create' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'), 'foreign_key' => array('type' => 'integer', 'null' => false, 'default' => null), 'model' => array('type' => 'varchar', 'null' => false, 'default' => null), 'value' => array('type' => 'float', 'null' => false, 'length' => '5,2', 'default' => null), 'created' => array('type' => 'datetime', 'null' => false, 'default' => null), 'modified' => array('type' => 'datetime', 'null' => false, 'default' => null), 'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)), 'tableParameters' => array('charset' => 'latin1', 'collate' => 'latin1_swedish_ci', 'engine' => 'MyISAM') ) ) ); $this->assertEquals($expected, $compare); } /** * test comparing '' and null and making sure they are different. * * @return void */ public function testCompareEmptyStringAndNull() { $One = new CakeSchema(array( 'posts' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'), 'name' => array('type' => 'string', 'null' => false, 'default' => '') ) )); $Two = new CakeSchema(array( 'posts' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary'), 'name' => array('type' => 'string', 'null' => false, 'default' => null) ) )); $compare = $One->compare($Two); $expected = array( 'posts' => array( 'change' => array( 'name' => array('type' => 'string', 'null' => false, 'default' => null) ) ) ); $this->assertEquals($expected, $compare); } /** * Test comparing tableParameters and indexes. * * @return void */ public function testTableParametersAndIndexComparison() { $old = array( 'posts' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'author_id' => array('type' => 'integer', 'null' => false), 'title' => array('type' => 'string', 'null' => false), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => true) ), 'tableParameters' => array( 'charset' => 'latin1', 'collate' => 'latin1_general_ci' ) ), 'comments' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'comment' => array('type' => 'text'), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => true), 'post_id' => array('column' => 'post_id'), ), 'tableParameters' => array( 'engine' => 'InnoDB', 'charset' => 'latin1', 'collate' => 'latin1_general_ci' ) ) ); $new = array( 'posts' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'author_id' => array('type' => 'integer', 'null' => false), 'title' => array('type' => 'string', 'null' => false), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => true), 'author_id' => array('column' => 'author_id'), ), 'tableParameters' => array( 'charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'MyISAM' ) ), 'comments' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'post_id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'comment' => array('type' => 'text'), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => true), ), 'tableParameters' => array( 'charset' => 'utf8', 'collate' => 'utf8_general_ci' ) ) ); $compare = $this->Schema->compare($old, $new); $expected = array( 'posts' => array( 'add' => array( 'indexes' => array('author_id' => array('column' => 'author_id')), ), 'change' => array( 'tableParameters' => array( 'charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'MyISAM' ) ) ), 'comments' => array( 'drop' => array( 'indexes' => array('post_id' => array('column' => 'post_id')), ), 'change' => array( 'tableParameters' => array( 'charset' => 'utf8', 'collate' => 'utf8_general_ci', ) ) ) ); $this->assertEquals($expected, $compare); } /** * Test comparing with field changed from VARCHAR to DATETIME * * @return void */ public function testCompareVarcharToDatetime() { $old = array( 'posts' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'author_id' => array('type' => 'integer', 'null' => false), 'title' => array('type' => 'string', 'null' => true, 'length' => 45), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => true) ), 'tableParameters' => array( 'charset' => 'latin1', 'collate' => 'latin1_general_ci' ) ), ); $new = array( 'posts' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0, 'key' => 'primary'), 'author_id' => array('type' => 'integer', 'null' => false), 'title' => array('type' => 'datetime', 'null' => false), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => true) ), 'tableParameters' => array( 'charset' => 'latin1', 'collate' => 'latin1_general_ci' ) ), ); $compare = $this->Schema->compare($old, $new); $expected = array( 'posts' => array( 'change' => array( 'title' => array( 'type' => 'datetime', 'null' => false, ) ) ), ); $this->assertEquals($expected, $compare, 'Invalid SQL, datetime does not have length'); } /** * testSchemaLoading method * * @return void */ public function testSchemaLoading() { $Other = $this->Schema->load(array('name' => 'MyOtherApp', 'path' => TMP . 'tests')); $this->assertEquals('MyOtherApp', $Other->name); $this->assertEquals($Other->tables, $this->Schema->tables); } /** * test loading schema files inside of plugins. * * @return void */ public function testSchemaLoadingFromPlugin() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); CakePlugin::load('TestPlugin'); $Other = $this->Schema->load(array('name' => 'TestPluginApp', 'plugin' => 'TestPlugin')); $this->assertEquals('TestPluginApp', $Other->name); $this->assertEquals(array('test_plugin_acos'), array_keys($Other->tables)); App::build(); } /** * testSchemaCreateTable method * * @return void */ public function testSchemaCreateTable() { $db = ConnectionManager::getDataSource('test'); $db->cacheSources = false; $Schema = new CakeSchema(array( 'connection' => 'test', 'testdescribes' => array( 'id' => array('type' => 'integer', 'key' => 'primary'), 'int_null' => array('type' => 'integer', 'null' => true), 'int_not_null' => array('type' => 'integer', 'null' => false), ), )); $sql = $db->createSchema($Schema); $col = $Schema->tables['testdescribes']['int_null']; $col['name'] = 'int_null'; $column = $this->db->buildColumn($col); $this->assertRegExp('/' . preg_quote($column, '/') . '/', $sql); $col = $Schema->tables['testdescribes']['int_not_null']; $col['name'] = 'int_not_null'; $column = $this->db->buildColumn($col); $this->assertRegExp('/' . preg_quote($column, '/') . '/', $sql); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/ConnectionManagerTest.php000066400000000000000000000252141265552240500243540ustar00rootroot00000000000000assertTrue(count($sources) >= 1); $connections = array('default', 'test', 'test'); $this->assertTrue(count(array_intersect(array_keys($sources), $connections)) >= 1); } /** * testGetDataSource method * * @return void */ public function testGetDataSource() { App::build(array( 'Model/Datasource' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS . 'Datasource' . DS ) )); $name = 'test_get_datasource'; $config = array('datasource' => 'Test2Source'); ConnectionManager::create($name, $config); $connections = ConnectionManager::enumConnectionObjects(); $this->assertTrue((bool)(count(array_keys($connections) >= 1))); $source = ConnectionManager::getDataSource('test_get_datasource'); $this->assertTrue(is_object($source)); ConnectionManager::drop('test_get_datasource'); } /** * testGetDataSourceException() method * * @return void * @expectedException MissingDatasourceConfigException */ public function testGetDataSourceException() { ConnectionManager::getDataSource('non_existent_source'); } /** * testGetPluginDataSource method * * @return void */ public function testGetPluginDataSource() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); $name = 'test_source'; $config = array('datasource' => 'TestPlugin.TestSource'); $connection = ConnectionManager::create($name, $config); $this->assertTrue(class_exists('TestSource')); $this->assertEquals($connection->configKeyName, $name); $this->assertEquals($connection->config, $config); ConnectionManager::drop($name); } /** * testGetPluginDataSourceAndPluginDriver method * * @return void */ public function testGetPluginDataSourceAndPluginDriver() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); $name = 'test_plugin_source_and_driver'; $config = array('datasource' => 'TestPlugin.Database/TestDriver'); $connection = ConnectionManager::create($name, $config); $this->assertTrue(class_exists('TestSource')); $this->assertTrue(class_exists('TestDriver')); $this->assertEquals($connection->configKeyName, $name); $this->assertEquals($connection->config, $config); ConnectionManager::drop($name); } /** * testGetLocalDataSourceAndPluginDriver method * * @return void */ public function testGetLocalDataSourceAndPluginDriver() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); CakePlugin::load('TestPlugin'); $name = 'test_local_source_and_plugin_driver'; $config = array('datasource' => 'TestPlugin.Database/DboDummy'); $connection = ConnectionManager::create($name, $config); $this->assertTrue(class_exists('DboSource')); $this->assertTrue(class_exists('DboDummy')); $this->assertEquals($connection->configKeyName, $name); ConnectionManager::drop($name); } /** * testGetPluginDataSourceAndLocalDriver method * * @return void */ public function testGetPluginDataSourceAndLocalDriver() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'Model/Datasource/Database' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS . 'Datasource' . DS . 'Database' . DS ) )); $name = 'test_plugin_source_and_local_driver'; $config = array('datasource' => 'Database/TestLocalDriver'); $connection = ConnectionManager::create($name, $config); $this->assertTrue(class_exists('TestSource')); $this->assertTrue(class_exists('TestLocalDriver')); $this->assertEquals($connection->configKeyName, $name); $this->assertEquals($connection->config, $config); ConnectionManager::drop($name); } /** * testSourceList method * * @return void */ public function testSourceList() { ConnectionManager::getDataSource('test'); $sources = ConnectionManager::sourceList(); $this->assertTrue(count($sources) >= 1); $this->assertTrue(in_array('test', array_keys($sources))); } /** * testGetSourceName method * * @return void */ public function testGetSourceName() { $source = ConnectionManager::getDataSource('test'); $result = ConnectionManager::getSourceName($source); $this->assertEquals('test', $result); $source = new StdClass(); $result = ConnectionManager::getSourceName($source); $this->assertNull($result); } /** * testLoadDataSource method * * @return void */ public function testLoadDataSource() { $connections = array( array('classname' => 'Mysql', 'filename' => 'Mysql', 'package' => 'Database'), array('classname' => 'Postgres', 'filename' => 'Postgres', 'package' => 'Database'), array('classname' => 'Sqlite', 'filename' => 'Sqlite', 'package' => 'Database'), ); foreach ($connections as $connection) { $exists = class_exists($connection['classname']); $loaded = ConnectionManager::loadDataSource($connection); $this->assertEquals($loaded, !$exists, "Failed loading the {$connection['classname']} datasource"); } } /** * testLoadDataSourceException() method * * @return void * @expectedException MissingDatasourceException */ public function testLoadDataSourceException() { $connection = array('classname' => 'NonExistentDataSource', 'filename' => 'non_existent'); ConnectionManager::loadDataSource($connection); } /** * testCreateDataSource method * * @return void */ public function testCreateDataSourceWithIntegrationTests() { $name = 'test_created_connection'; $connections = ConnectionManager::enumConnectionObjects(); $this->assertTrue((bool)(count(array_keys($connections) >= 1))); $source = ConnectionManager::getDataSource('test'); $this->assertTrue(is_object($source)); $config = $source->config; $connection = ConnectionManager::create($name, $config); $this->assertTrue(is_object($connection)); $this->assertEquals($name, $connection->configKeyName); $this->assertEquals($name, ConnectionManager::getSourceName($connection)); $source = ConnectionManager::create(null, array()); $this->assertEquals(null, $source); $source = ConnectionManager::create('another_test', array()); $this->assertEquals(null, $source); $config = array('classname' => 'DboMysql', 'filename' => 'dbo' . DS . 'dbo_mysql'); $source = ConnectionManager::create(null, $config); $this->assertEquals(null, $source); } /** * testConnectionData method * * @return void */ public function testConnectionData() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'Model/Datasource' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS . 'Datasource' . DS ) ), App::RESET); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); $expected = array( 'datasource' => 'Test2Source' ); ConnectionManager::create('connection1', array('datasource' => 'Test2Source')); $connections = ConnectionManager::enumConnectionObjects(); $this->assertEquals($expected, $connections['connection1']); ConnectionManager::drop('connection1'); ConnectionManager::create('connection2', array('datasource' => 'Test2Source')); $connections = ConnectionManager::enumConnectionObjects(); $this->assertEquals($expected, $connections['connection2']); ConnectionManager::drop('connection2'); ConnectionManager::create('connection3', array('datasource' => 'TestPlugin.TestSource')); $connections = ConnectionManager::enumConnectionObjects(); $expected['datasource'] = 'TestPlugin.TestSource'; $this->assertEquals($expected, $connections['connection3']); ConnectionManager::drop('connection3'); ConnectionManager::create('connection4', array('datasource' => 'TestPlugin.TestSource')); $connections = ConnectionManager::enumConnectionObjects(); $this->assertEquals($expected, $connections['connection4']); ConnectionManager::drop('connection4'); ConnectionManager::create('connection5', array('datasource' => 'Test2OtherSource')); $connections = ConnectionManager::enumConnectionObjects(); $expected['datasource'] = 'Test2OtherSource'; $this->assertEquals($expected, $connections['connection5']); ConnectionManager::drop('connection5'); ConnectionManager::create('connection6', array('datasource' => 'Test2OtherSource')); $connections = ConnectionManager::enumConnectionObjects(); $this->assertEquals($expected, $connections['connection6']); ConnectionManager::drop('connection6'); ConnectionManager::create('connection7', array('datasource' => 'TestPlugin.TestOtherSource')); $connections = ConnectionManager::enumConnectionObjects(); $expected['datasource'] = 'TestPlugin.TestOtherSource'; $this->assertEquals($expected, $connections['connection7']); ConnectionManager::drop('connection7'); ConnectionManager::create('connection8', array('datasource' => 'TestPlugin.TestOtherSource')); $connections = ConnectionManager::enumConnectionObjects(); $this->assertEquals($expected, $connections['connection8']); ConnectionManager::drop('connection8'); } /** * Tests that a connection configuration can be deleted in runtime * * @return void */ public function testDrop() { App::build(array( 'Model/Datasource' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS . 'Datasource' . DS ) )); ConnectionManager::create('droppable', array('datasource' => 'Test2Source')); $connections = ConnectionManager::enumConnectionObjects(); $this->assertEquals(array('datasource' => 'Test2Source'), $connections['droppable']); $this->assertTrue(ConnectionManager::drop('droppable')); $connections = ConnectionManager::enumConnectionObjects(); $this->assertFalse(isset($connections['droppable'])); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Datasource/000077500000000000000000000000001265552240500214775ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Model/Datasource/CakeSessionTest.php000066400000000000000000000556011265552240500252660ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model.Datasource * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('CakeSession', 'Model/Datasource'); App::uses('DatabaseSession', 'Model/Datasource/Session'); App::uses('CacheSession', 'Model/Datasource/Session'); /** * Class TestCakeSession * * @package Cake.Test.Case.Model.Datasource */ class TestCakeSession extends CakeSession { public static function setUserAgent($value) { static::$_userAgent = $value; } public static function setHost($host) { static::_setHost($host); } } /** * Class TestCacheSession * * @package Cake.Test.Case.Model.Datasource */ class TestCacheSession extends CacheSession { protected function _writeSession() { return true; } } /** * Class TestDatabaseSession * * @package Cake.Test.Case.Model.Datasource */ class TestDatabaseSession extends DatabaseSession { protected function _writeSession() { return true; } } /** * CakeSessionTest class * * @package Cake.Test.Case.Model.Datasource */ class CakeSessionTest extends CakeTestCase { protected static $_gcDivisor; /** * Fixtures used in the SessionTest * * @var array */ public $fixtures = array('core.session'); /** * setup before class. * * @return void */ public static function setupBeforeClass() { // Make sure garbage colector will be called static::$_gcDivisor = ini_get('session.gc_divisor'); ini_set('session.gc_divisor', '1'); } /** * teardown after class * * @return void */ public static function teardownAfterClass() { // Revert to the default setting ini_set('session.gc_divisor', static::$_gcDivisor); } /** * setUp method * * @return void */ public function setUp() { parent::setUp(); Configure::write('Session', array( 'defaults' => 'php', 'cookie' => 'cakephp', 'timeout' => 120, 'cookieTimeout' => 120, 'ini' => array(), )); } /** * tearDown method * * @return void */ public function tearDown() { if (TestCakeSession::started()) { session_write_close(); } unset($_SESSION); parent::tearDown(); } /** * test setting ini properties with Session configuration. * * @return void */ public function testSessionConfigIniSetting() { $_SESSION = null; Configure::write('Session', array( 'cookie' => 'test', 'checkAgent' => false, 'timeout' => 86400, 'ini' => array( 'session.referer_check' => 'example.com', 'session.use_trans_sid' => false ) )); TestCakeSession::start(); $this->assertEquals('', ini_get('session.use_trans_sid'), 'Ini value is incorrect'); $this->assertEquals('example.com', ini_get('session.referer_check'), 'Ini value is incorrect'); $this->assertEquals('test', ini_get('session.name'), 'Ini value is incorrect'); } /** * testSessionPath * * @return void */ public function testSessionPath() { TestCakeSession::init('/index.php'); $this->assertEquals('/', TestCakeSession::$path); TestCakeSession::init('/sub_dir/index.php'); $this->assertEquals('/sub_dir/', TestCakeSession::$path); } /** * testCakeSessionPathEmpty * * @return void */ public function testCakeSessionPathEmpty() { TestCakeSession::init(''); $this->assertEquals('/', TestCakeSession::$path, 'Session path is empty, with "" as $base needs to be /'); } /** * testCakeSessionPathContainsParams * * @return void */ public function testCakeSessionPathContainsQuestion() { TestCakeSession::init('/index.php?'); $this->assertEquals('/', TestCakeSession::$path); } /** * testSetHost * * @return void */ public function testSetHost() { TestCakeSession::init(); TestCakeSession::setHost('cakephp.org'); $this->assertEquals('cakephp.org', TestCakeSession::$host); } /** * testSetHostWithPort * * @return void */ public function testSetHostWithPort() { TestCakeSession::init(); TestCakeSession::setHost('cakephp.org:443'); $this->assertEquals('cakephp.org', TestCakeSession::$host); } /** * test valid with bogus user agent. * * @return void */ public function testValidBogusUserAgent() { Configure::write('Session.checkAgent', true); TestCakeSession::start(); $this->assertTrue(TestCakeSession::valid(), 'Newly started session should be valid'); TestCakeSession::userAgent('bogus!'); $this->assertFalse(TestCakeSession::valid(), 'user agent mismatch should fail.'); } /** * test valid with bogus user agent. * * @return void */ public function testValidTimeExpiry() { Configure::write('Session.checkAgent', true); TestCakeSession::start(); $this->assertTrue(TestCakeSession::valid(), 'Newly started session should be valid'); TestCakeSession::$time = strtotime('next year'); $this->assertFalse(TestCakeSession::valid(), 'time should cause failure.'); } /** * testCheck method * * @return void */ public function testCheck() { TestCakeSession::write('SessionTestCase', 'value'); $this->assertTrue(TestCakeSession::check('SessionTestCase')); $this->assertFalse(TestCakeSession::check('NotExistingSessionTestCase')); } /** * testSimpleRead method * * @return void */ public function testSimpleRead() { TestCakeSession::write('testing', '1,2,3'); $result = TestCakeSession::read('testing'); $this->assertEquals('1,2,3', $result); TestCakeSession::write('testing', array('1' => 'one', '2' => 'two', '3' => 'three')); $result = TestCakeSession::read('testing.1'); $this->assertEquals('one', $result); $result = TestCakeSession::read('testing'); $this->assertEquals(array('1' => 'one', '2' => 'two', '3' => 'three'), $result); $result = TestCakeSession::read(); $this->assertTrue(isset($result['testing'])); $this->assertTrue(isset($result['Config'])); $this->assertTrue(isset($result['Config']['userAgent'])); TestCakeSession::write('This.is.a.deep.array.my.friend', 'value'); $result = TestCakeSession::read('This.is.a.deep.array.my.friend'); $this->assertEquals('value', $result); } /** * testReadyEmpty * * @return void */ public function testReadyEmpty() { $this->assertNull(TestCakeSession::read('')); } /** * test writing a hash of values/ * * @return void */ public function testWriteArray() { $result = TestCakeSession::write(array( 'one' => 1, 'two' => 2, 'three' => array('something'), 'null' => null )); $this->assertTrue($result); $this->assertEquals(1, TestCakeSession::read('one')); $this->assertEquals(array('something'), TestCakeSession::read('three')); $this->assertEquals(null, TestCakeSession::read('null')); } /** * testWriteEmptyKey * * @return void */ public function testWriteEmptyKey() { $this->assertFalse(TestCakeSession::write('', 'graham')); $this->assertFalse(TestCakeSession::write('', '')); $this->assertFalse(TestCakeSession::write('')); } /** * Test overwriting a string value as if it were an array. * * @return void */ public function testWriteOverwriteStringValue() { TestCakeSession::write('Some.string', 'value'); $this->assertEquals('value', TestCakeSession::read('Some.string')); TestCakeSession::write('Some.string.array', array('values')); $this->assertEquals( array('values'), TestCakeSession::read('Some.string.array') ); } /** * Test consuming session data. * * @return void */ public function testConsume() { TestCakeSession::write('Some.string', 'value'); TestCakeSession::write('Some.array', array('key1' => 'value1', 'key2' => 'value2')); $this->assertEquals('value', TestCakeSession::read('Some.string')); $value = TestCakeSession::consume('Some.string'); $this->assertEquals('value', $value); $this->assertFalse(TestCakeSession::check('Some.string')); $value = TestCakeSession::consume(''); $this->assertNull($value); $value = TestCakeSession::consume(null); $this->assertNull($value); $value = TestCakeSession::consume('Some.array'); $expected = array('key1' => 'value1', 'key2' => 'value2'); $this->assertEquals($expected, $value); $this->assertFalse(TestCakeSession::check('Some.array')); } /** * testId method * * @return void */ public function testId() { TestCakeSession::destroy(); $result = TestCakeSession::id(); $expected = session_id(); $this->assertEquals($expected, $result); TestCakeSession::id('MySessionId'); $result = TestCakeSession::id(); $this->assertEquals('MySessionId', $result); } /** * testStarted method * * @return void */ public function testStarted() { unset($_SESSION); $_SESSION = null; $this->assertFalse(TestCakeSession::started()); $this->assertTrue(TestCakeSession::start()); $this->assertTrue(TestCakeSession::started()); } /** * testDel method * * @return void */ public function testDelete() { $this->assertTrue(TestCakeSession::write('Delete.me', 'Clearing out')); $this->assertTrue(TestCakeSession::delete('Delete.me')); $this->assertFalse(TestCakeSession::check('Delete.me')); $this->assertTrue(TestCakeSession::check('Delete')); $this->assertTrue(TestCakeSession::write('Clearing.sale', 'everything must go')); $this->assertFalse(TestCakeSession::delete('')); $this->assertTrue(TestCakeSession::check('Clearing.sale')); $this->assertFalse(TestCakeSession::delete(null)); $this->assertTrue(TestCakeSession::check('Clearing.sale')); $this->assertTrue(TestCakeSession::delete('Clearing')); $this->assertFalse(TestCakeSession::check('Clearing.sale')); $this->assertFalse(TestCakeSession::check('Clearing')); } /** * testClear method * * @return void */ public function testClear() { $this->assertTrue(TestCakeSession::write('Delete.me', 'Clearing out')); TestCakeSession::clear(false); $this->assertFalse(TestCakeSession::check('Delete.me')); $this->assertFalse(TestCakeSession::check('Delete')); TestCakeSession::write('Some.string', 'value'); TestCakeSession::clear(false); $this->assertNull(TestCakeSession::read('Some')); TestCakeSession::write('Some.string.array', array('values')); TestCakeSession::clear(false); $this->assertFalse(TestCakeSession::read()); } /** * testDestroy method * * @return void */ public function testDestroy() { TestCakeSession::write('bulletProof', 'invincible'); $id = TestCakeSession::id(); TestCakeSession::destroy(); $this->assertFalse(TestCakeSession::check('bulletProof')); $this->assertNotEquals(TestCakeSession::id(), $id); } /** * testCheckingSavedEmpty method * * @return void */ public function testCheckingSavedEmpty() { $this->assertTrue(TestCakeSession::write('SessionTestCase', 0)); $this->assertTrue(TestCakeSession::check('SessionTestCase')); $this->assertTrue(TestCakeSession::write('SessionTestCase', '0')); $this->assertTrue(TestCakeSession::check('SessionTestCase')); $this->assertTrue(TestCakeSession::write('SessionTestCase', false)); $this->assertTrue(TestCakeSession::check('SessionTestCase')); $this->assertTrue(TestCakeSession::write('SessionTestCase', null)); $this->assertFalse(TestCakeSession::check('SessionTestCase')); } /** * testCheckKeyWithSpaces method * * @return void */ public function testCheckKeyWithSpaces() { $this->assertTrue(TestCakeSession::write('Session Test', "test")); $this->assertTrue(TestCakeSession::check('Session Test')); TestCakeSession::delete('Session Test'); $this->assertTrue(TestCakeSession::write('Session Test.Test Case', "test")); $this->assertTrue(TestCakeSession::check('Session Test.Test Case')); } /** * testCheckEmpty * * @return void */ public function testCheckEmpty() { $this->assertFalse(TestCakeSession::check('')); $this->assertFalse(TestCakeSession::check(null)); } /** * test key exploitation * * @return void */ public function testKeyExploit() { $key = "a'] = 1; phpinfo(); \$_SESSION['a"; $result = TestCakeSession::write($key, 'haxored'); $this->assertFalse($result); $result = TestCakeSession::read($key); $this->assertNull($result); } /** * testReadingSavedEmpty method * * @return void */ public function testReadingSavedEmpty() { TestCakeSession::write('SessionTestCase', 0); $this->assertEquals(0, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', '0'); $this->assertEquals('0', TestCakeSession::read('SessionTestCase')); $this->assertFalse(TestCakeSession::read('SessionTestCase') === 0); TestCakeSession::write('SessionTestCase', false); $this->assertFalse(TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', null); $this->assertEquals(null, TestCakeSession::read('SessionTestCase')); } /** * Test te cacheLimiter settings. * * @return void */ public function testCacheLimiter() { Configure::write('Session.cacheLimiter', 'public'); TestCakeSession::start(); $this->assertSame('public', session_cache_limiter()); Configure::write('Session.cacheLimiter', 'private'); TestCakeSession::destroy(); TestCakeSession::start(); $this->assertSame('private', session_cache_limiter()); } /** * testCheckUserAgentFalse method * * @return void */ public function testCheckUserAgentFalse() { Configure::write('Session.checkAgent', false); TestCakeSession::setUserAgent(md5('http://randomdomainname.com' . Configure::read('Security.salt'))); $this->assertTrue(TestCakeSession::valid()); } /** * testCheckUserAgentTrue method * * @return void */ public function testCheckUserAgentTrue() { Configure::write('Session.checkAgent', true); TestCakeSession::$error = false; $agent = md5('http://randomdomainname.com' . Configure::read('Security.salt')); TestCakeSession::write('Config.userAgent', md5('Hacking you!')); TestCakeSession::setUserAgent($agent); $this->assertFalse(TestCakeSession::valid()); } /** * testReadAndWriteWithCakeStorage method * * @return void */ public function testReadAndWriteWithCakeStorage() { Configure::write('Session.defaults', 'cake'); TestCakeSession::init(); TestCakeSession::start(); TestCakeSession::write('SessionTestCase', 0); $this->assertEquals(0, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', '0'); $this->assertEquals('0', TestCakeSession::read('SessionTestCase')); $this->assertFalse(TestCakeSession::read('SessionTestCase') === 0); TestCakeSession::write('SessionTestCase', false); $this->assertFalse(TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', null); $this->assertEquals(null, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', 'This is a Test'); $this->assertEquals('This is a Test', TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', 'This is a Test'); TestCakeSession::write('SessionTestCase', 'This was updated'); $this->assertEquals('This was updated', TestCakeSession::read('SessionTestCase')); TestCakeSession::destroy(); $this->assertNull(TestCakeSession::read('SessionTestCase')); } /** * test using a handler from app/Model/Datasource/Session. * * @return void */ public function testUsingAppLibsHandler() { App::build(array( 'Model/Datasource/Session' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS . 'Datasource' . DS . 'Session' . DS ), 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); Configure::write('Session', array( 'defaults' => 'cake', 'handler' => array( 'engine' => 'TestAppLibSession' ) )); TestCakeSession::start(); $this->assertTrue(TestCakeSession::started()); TestCakeSession::destroy(); $this->assertFalse(TestCakeSession::started()); App::build(); } /** * test using a handler from a plugin. * * @return void */ public function testUsingPluginHandler() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); Configure::write('Session', array( 'defaults' => 'cake', 'handler' => array( 'engine' => 'TestPlugin.TestPluginSession' ) )); TestCakeSession::start(); $this->assertTrue(TestCakeSession::started()); TestCakeSession::destroy(); $this->assertFalse(TestCakeSession::started()); App::build(); } /** * testReadAndWriteWithCacheStorage method * * @return void */ public function testReadAndWriteWithCacheStorage() { Configure::write('Session.defaults', 'cache'); Configure::write('Session.handler.engine', 'TestCacheSession'); TestCakeSession::init(); TestCakeSession::destroy(); TestCakeSession::write('SessionTestCase', 0); $this->assertEquals(0, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', '0'); $this->assertEquals('0', TestCakeSession::read('SessionTestCase')); $this->assertFalse(TestCakeSession::read('SessionTestCase') === 0); TestCakeSession::write('SessionTestCase', false); $this->assertFalse(TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', null); $this->assertEquals(null, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', 'This is a Test'); $this->assertEquals('This is a Test', TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', 'This is a Test'); TestCakeSession::write('SessionTestCase', 'This was updated'); $this->assertEquals('This was updated', TestCakeSession::read('SessionTestCase')); TestCakeSession::destroy(); $this->assertNull(TestCakeSession::read('SessionTestCase')); } /** * test that changing the config name of the cache config works. * * @return void */ public function testReadAndWriteWithCustomCacheConfig() { Configure::write('Session.defaults', 'cache'); Configure::write('Session.handler.engine', 'TestCacheSession'); Configure::write('Session.handler.config', 'session_test'); Cache::config('session_test', array( 'engine' => 'File', 'prefix' => 'session_test_', )); TestCakeSession::init(); TestCakeSession::start(); TestCakeSession::write('SessionTestCase', 'Some value'); $this->assertEquals('Some value', TestCakeSession::read('SessionTestCase')); $id = TestCakeSession::id(); Cache::delete($id, 'session_test'); } /** * testReadAndWriteWithDatabaseStorage method * * @return void */ public function testReadAndWriteWithDatabaseStorage() { Configure::write('Session.defaults', 'database'); Configure::write('Session.handler.engine', 'TestDatabaseSession'); Configure::write('Session.handler.table', 'sessions'); Configure::write('Session.handler.model', 'Session'); Configure::write('Session.handler.database', 'test'); TestCakeSession::init(); $this->assertNull(TestCakeSession::id()); TestCakeSession::start(); $expected = session_id(); $this->assertEquals($expected, TestCakeSession::id()); TestCakeSession::renew(); $this->assertFalse($expected === TestCakeSession::id()); $expected = session_id(); $this->assertEquals($expected, TestCakeSession::id()); TestCakeSession::write('SessionTestCase', 0); $this->assertEquals(0, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', '0'); $this->assertEquals('0', TestCakeSession::read('SessionTestCase')); $this->assertFalse(TestCakeSession::read('SessionTestCase') === 0); TestCakeSession::write('SessionTestCase', false); $this->assertFalse(TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', null); $this->assertEquals(null, TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', 'This is a Test'); $this->assertEquals('This is a Test', TestCakeSession::read('SessionTestCase')); TestCakeSession::write('SessionTestCase', 'Some additional data'); $this->assertEquals('Some additional data', TestCakeSession::read('SessionTestCase')); TestCakeSession::destroy(); $this->assertNull(TestCakeSession::read('SessionTestCase')); Configure::write('Session', array( 'defaults' => 'php' )); TestCakeSession::init(); } /** * testSessionTimeout method * * @return void */ public function testSessionTimeout() { Configure::write('debug', 2); Configure::write('Session.defaults', 'cake'); Configure::write('Session.autoRegenerate', false); $timeoutSeconds = Configure::read('Session.timeout') * 60; TestCakeSession::destroy(); TestCakeSession::write('Test', 'some value'); $this->assertWithinMargin(time() + $timeoutSeconds, CakeSession::$sessionTime, 1); $this->assertEquals(10, $_SESSION['Config']['countdown']); $this->assertWithinMargin(CakeSession::$sessionTime, $_SESSION['Config']['time'], 1); $this->assertWithinMargin(time(), CakeSession::$time, 1); $this->assertWithinMargin(time() + $timeoutSeconds, $_SESSION['Config']['time'], 1); Configure::write('Session.harden', true); TestCakeSession::destroy(); TestCakeSession::write('Test', 'some value'); $this->assertWithinMargin(time() + $timeoutSeconds, CakeSession::$sessionTime, 1); $this->assertEquals(10, $_SESSION['Config']['countdown']); $this->assertWithinMargin(CakeSession::$sessionTime, $_SESSION['Config']['time'], 1); $this->assertWithinMargin(time(), CakeSession::$time, 1); $this->assertWithinMargin(CakeSession::$time + $timeoutSeconds, $_SESSION['Config']['time'], 1); } /** * Test that cookieTimeout matches timeout when unspecified. * * @return void */ public function testCookieTimeoutFallback() { $_SESSION = null; Configure::write('Session', array( 'defaults' => 'cake', 'timeout' => 400, )); TestCakeSession::start(); $this->assertEquals(400, Configure::read('Session.cookieTimeout')); $this->assertEquals(400, Configure::read('Session.timeout')); $this->assertEquals(400 * 60, ini_get('session.cookie_lifetime')); $this->assertEquals(400 * 60, ini_get('session.gc_maxlifetime')); $_SESSION = null; Configure::write('Session', array( 'defaults' => 'cake', 'timeout' => 400, 'cookieTimeout' => 600 )); TestCakeSession::start(); $this->assertEquals(600, Configure::read('Session.cookieTimeout')); $this->assertEquals(400, Configure::read('Session.timeout')); } /** * Proves that invalid sessions will be destroyed and re-created * if invalid * * @return void */ public function testInvalidSessionRenew() { TestCakeSession::start(); $this->assertNotEmpty($_SESSION['Config']); $data = $_SESSION; session_write_close(); $_SESSION = null; TestCakeSession::start(); $this->assertEquals($data, $_SESSION); TestCakeSession::write('Foo', 'Bar'); session_write_close(); $_SESSION = null; TestCakeSession::userAgent('bogus!'); TestCakeSession::start(); $this->assertNotEquals($data, $_SESSION); $this->assertEquals('bogus!', $_SESSION['Config']['userAgent']); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Datasource/DataSourceTest.php000066400000000000000000000121741265552240500251070ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model.Datasource * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Model', 'Model'); App::uses('DataSource', 'Model/Datasource'); /** * TestSource * * @package Cake.Test.Case.Model.Datasource */ class TestSource extends DataSource { /** * _schema * @var type */ protected $_schema = array( 'id' => array( 'type' => 'integer', 'null' => false, 'key' => 'primary', 'length' => 11, ), 'text' => array( 'type' => 'string', 'null' => true, 'length' => 140, ), 'status' => array( 'type' => 'string', 'null' => true, 'length' => 140, ), 'customField' => array( 'type' => 'string', 'null' => true, 'length' => 255, ), ); /** * listSources * * @return bool */ public function listSources() { return null; } /** * Returns the schema for the datasource to enable create/update * * @param object $Model * @return array */ public function describe(Model $Model) { return $this->_schema; } /** * Just return $func to pass to read() to figure out the COUNT * Required for delete/update to work * * @param Model $Model * @param type $func * @param type $params * @return array */ public function calculate(Model $Model, $func, $params = array()) { return $func; } } /** * DataSourceTest class * * @package Cake.Test.Case.Model.Datasource */ class DataSourceTest extends CakeTestCase { /** * Name of test source * * @var string */ public $sourceName = 'myapitest'; /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->Source = $this->getMock( 'TestSource', array('create', 'read', 'update', 'delete') ); ConnectionManager::create($this->sourceName, array( 'datasource' => get_class($this->Source), 'apiKey' => '1234abcd', )); $this->Model = $this->getMock( 'Model', array('getDataSource'), array(array('ds' => $this->sourceName)) ); $this->Model->expects($this->any()) ->method('getDataSource') ->will($this->returnValue($this->Source)); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Model, $this->Source); ConnectionManager::drop($this->sourceName); } /** * testCreate * * @return void */ public function testCreate() { $data = array( $this->Model->alias => array( 'text' => 'This is a test', 'status' => 'Test status', 'customField' => array( 'array', 'field', 'type', 'for', 'custom', 'datasources', ), ), ); $this->Source->expects($this->once()) ->method('create') ->with( $this->equalTo($this->Model), $this->equalTo(array_keys($data[$this->Model->alias])), $this->equalTo(array_values($data[$this->Model->alias])) ); $this->Model->save($data); } /** * testRead * * @return void */ public function testRead() { $expected = array( 'conditions' => array('status' => 'test'), 'fields' => null, 'joins' => array(), 'limit' => 10, 'offset' => null, 'order' => array(array('status')), 'page' => 1, 'group' => null, 'callbacks' => true, ); $this->Source->expects($this->once()) ->method('read') ->with( $this->anything(), $this->equalTo($expected) ); $this->Model->find('all', array( 'conditions' => array('status' => 'test'), 'limit' => 10, 'order' => array('status'), )); } /** * testUpdate * * @return void */ public function testUpdate() { $data = array( $this->Model->alias => array( 'id' => 1, 'text' => 'This is a test', 'status' => 'Test status', 'customField' => array( 'array', 'field', 'type', 'for', 'custom', 'datasources', ), ), ); $this->Source->expects($this->any()) ->method('read') ->will($this->returnValue(array( array($this->Model->alias => array('count' => 1)) ))); $this->Source->expects($this->once()) ->method('update') ->with( $this->equalTo($this->Model), $this->equalTo(array_keys($data[$this->Model->alias])), $this->equalTo(array_values($data[$this->Model->alias])) ); $this->Model->save($data); } /** * testDelete * * @return void */ public function testDelete() { $this->Source->expects($this->any()) ->method('read') ->will($this->returnValue(array( array($this->Model->alias => array('count' => 1)) ))); $this->Source->expects($this->once()) ->method('delete') ->with( $this->equalTo($this->Model), $this->equalTo(array($this->Model->alias . '.id' => 1)) ); $this->Model->delete(1); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Datasource/Database/000077500000000000000000000000001265552240500232035ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php000066400000000000000000004701471265552240500256760ustar00rootroot00000000000000Dbo = ConnectionManager::getDataSource('test'); if (!($this->Dbo instanceof Mysql)) { $this->markTestSkipped('The MySQL extension is not available.'); } $this->_debug = Configure::read('debug'); Configure::write('debug', 1); $this->model = ClassRegistry::init('MysqlTestModel'); } /** * Sets up a Dbo class instance for testing * * @return void */ public function tearDown() { parent::tearDown(); unset($this->model); ClassRegistry::flush(); Configure::write('debug', $this->_debug); } /** * Test Dbo value method * * @group quoting * @return void */ public function testQuoting() { $result = $this->Dbo->fields($this->model); $expected = array( '`MysqlTestModel`.`id`', '`MysqlTestModel`.`client_id`', '`MysqlTestModel`.`name`', '`MysqlTestModel`.`login`', '`MysqlTestModel`.`passwd`', '`MysqlTestModel`.`addr_1`', '`MysqlTestModel`.`addr_2`', '`MysqlTestModel`.`zip_code`', '`MysqlTestModel`.`city`', '`MysqlTestModel`.`country`', '`MysqlTestModel`.`phone`', '`MysqlTestModel`.`fax`', '`MysqlTestModel`.`url`', '`MysqlTestModel`.`email`', '`MysqlTestModel`.`comments`', '`MysqlTestModel`.`last_login`', '`MysqlTestModel`.`created`', '`MysqlTestModel`.`updated`' ); $this->assertEquals($expected, $result); $expected = 1.2; $result = $this->Dbo->value(1.2, 'float'); $this->assertEquals($expected, $result); $expected = "'1,2'"; $result = $this->Dbo->value('1,2', 'float'); $this->assertEquals($expected, $result); $expected = "'4713e29446'"; $result = $this->Dbo->value('4713e29446'); $this->assertEquals($expected, $result); $expected = 'NULL'; $result = $this->Dbo->value('', 'integer'); $this->assertEquals($expected, $result); $expected = "'0'"; $result = $this->Dbo->value('', 'boolean'); $this->assertEquals($expected, $result); $expected = 10010001; $result = $this->Dbo->value(10010001); $this->assertEquals($expected, $result); $expected = "'00010010001'"; $result = $this->Dbo->value('00010010001'); $this->assertEquals($expected, $result); } /** * test that localized floats don't cause trouble. * * @group quoting * @return void */ public function testLocalizedFloats() { $this->skipIf(DS === '\\', 'The locale is not supported in Windows and affect the others tests.'); $restore = setlocale(LC_NUMERIC, 0); $this->skipIf(setlocale(LC_NUMERIC, 'de_DE') === false, "The German locale isn't available."); $result = $this->Dbo->value(3.141593); $this->assertEquals('3.141593', $result); $result = $this->db->value(3.141593, 'float'); $this->assertEquals('3.141593', $result); $result = $this->db->value(1234567.11, 'float'); $this->assertEquals('1234567.11', $result); $result = $this->db->value(123456.45464748, 'float'); $this->assertContains('123456.454647', $result); $result = $this->db->value(0.987654321, 'float'); $this->assertEquals('0.987654321', (string)$result); $result = $this->db->value(2.2E-54, 'float'); $this->assertEquals('2.2E-54', (string)$result); $result = $this->db->value(2.2E-54); $this->assertEquals('2.2E-54', (string)$result); setlocale(LC_NUMERIC, $restore); } /** * test that scientific notations are working correctly * * @return void */ public function testScientificNotation() { $result = $this->db->value(2.2E-54, 'float'); $this->assertEquals('2.2E-54', (string)$result); $result = $this->db->value(2.2E-54); $this->assertEquals('2.2E-54', (string)$result); } /** * testTinyintCasting method * * @return void */ public function testTinyintCasting() { $this->Dbo->cacheSources = false; $tableName = 'tinyint_' . uniqid(); $this->Dbo->rawQuery('CREATE TABLE ' . $this->Dbo->fullTableName($tableName) . ' (id int(11) AUTO_INCREMENT, bool tinyint(1), small_int tinyint(2), primary key(id));'); $this->model = new CakeTestModel(array( 'name' => 'Tinyint', 'table' => $tableName, 'ds' => 'test' )); $result = $this->model->schema(); $this->assertEquals('boolean', $result['bool']['type']); $this->assertEquals('integer', $result['small_int']['type']); $this->assertTrue((bool)$this->model->save(array('bool' => 5, 'small_int' => 5))); $result = $this->model->find('first'); $this->assertTrue($result['Tinyint']['bool']); $this->assertSame($result['Tinyint']['small_int'], '5'); $this->model->deleteAll(true); $this->assertTrue((bool)$this->model->save(array('bool' => 0, 'small_int' => 100))); $result = $this->model->find('first'); $this->assertFalse($result['Tinyint']['bool']); $this->assertSame($result['Tinyint']['small_int'], '100'); $this->model->deleteAll(true); $this->assertTrue((bool)$this->model->save(array('bool' => true, 'small_int' => 0))); $result = $this->model->find('first'); $this->assertTrue($result['Tinyint']['bool']); $this->assertSame($result['Tinyint']['small_int'], '0'); $this->model->deleteAll(true); $this->Dbo->rawQuery('DROP TABLE ' . $this->Dbo->fullTableName($tableName)); } /** * testLastAffected method * * @return void */ public function testLastAffected() { $this->Dbo->cacheSources = false; $tableName = 'tinyint_' . uniqid(); $this->Dbo->rawQuery('CREATE TABLE ' . $this->Dbo->fullTableName($tableName) . ' (id int(11) AUTO_INCREMENT, bool tinyint(1), small_int tinyint(2), primary key(id));'); $this->model = new CakeTestModel(array( 'name' => 'Tinyint', 'table' => $tableName, 'ds' => 'test' )); $this->assertTrue((bool)$this->model->save(array('bool' => 5, 'small_int' => 5))); $this->assertEquals(1, $this->model->find('count')); $this->model->deleteAll(true); $result = $this->Dbo->lastAffected(); $this->assertEquals(1, $result); $this->assertEquals(0, $this->model->find('count')); $this->Dbo->rawQuery('DROP TABLE ' . $this->Dbo->fullTableName($tableName)); } /** * testIndexDetection method * * @group indices * @return void */ public function testIndexDetection() { $this->Dbo->cacheSources = false; $name = $this->Dbo->fullTableName('simple'); $this->Dbo->rawQuery('CREATE TABLE ' . $name . ' (id int(11) AUTO_INCREMENT, bool tinyint(1), small_int tinyint(2), primary key(id));'); $expected = array('PRIMARY' => array('column' => 'id', 'unique' => 1)); $result = $this->Dbo->index('simple', false); $this->Dbo->rawQuery('DROP TABLE ' . $name); $this->assertEquals($expected, $result); $name = $this->Dbo->fullTableName('bigint'); $this->Dbo->rawQuery('CREATE TABLE ' . $name . ' (id bigint(20) AUTO_INCREMENT, bool tinyint(1), small_int tinyint(2), primary key(id));'); $expected = array('PRIMARY' => array('column' => 'id', 'unique' => 1)); $result = $this->Dbo->index('bigint', false); $this->Dbo->rawQuery('DROP TABLE ' . $name); $this->assertEquals($expected, $result); $name = $this->Dbo->fullTableName('with_a_key'); $this->Dbo->rawQuery('CREATE TABLE ' . $name . ' (id int(11) AUTO_INCREMENT, bool tinyint(1), small_int tinyint(2), primary key(id), KEY `pointless_bool` ( `bool` ));'); $expected = array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'pointless_bool' => array('column' => 'bool', 'unique' => 0), ); $result = $this->Dbo->index('with_a_key', false); $this->Dbo->rawQuery('DROP TABLE ' . $name); $this->assertEquals($expected, $result); $name = $this->Dbo->fullTableName('with_two_keys'); $this->Dbo->rawQuery('CREATE TABLE ' . $name . ' (id int(11) AUTO_INCREMENT, bool tinyint(1), small_int tinyint(2), primary key(id), KEY `pointless_bool` ( `bool` ), KEY `pointless_small_int` ( `small_int` ));'); $expected = array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'pointless_bool' => array('column' => 'bool', 'unique' => 0), 'pointless_small_int' => array('column' => 'small_int', 'unique' => 0), ); $result = $this->Dbo->index('with_two_keys', false); $this->Dbo->rawQuery('DROP TABLE ' . $name); $this->assertEquals($expected, $result); $name = $this->Dbo->fullTableName('with_compound_keys'); $this->Dbo->rawQuery('CREATE TABLE ' . $name . ' (id int(11) AUTO_INCREMENT, bool tinyint(1), small_int tinyint(2), primary key(id), KEY `pointless_bool` ( `bool` ), KEY `pointless_small_int` ( `small_int` ), KEY `one_way` ( `bool`, `small_int` ));'); $expected = array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'pointless_bool' => array('column' => 'bool', 'unique' => 0), 'pointless_small_int' => array('column' => 'small_int', 'unique' => 0), 'one_way' => array('column' => array('bool', 'small_int'), 'unique' => 0), ); $result = $this->Dbo->index('with_compound_keys', false); $this->Dbo->rawQuery('DROP TABLE ' . $name); $this->assertEquals($expected, $result); $name = $this->Dbo->fullTableName('with_multiple_compound_keys'); $this->Dbo->rawQuery('CREATE TABLE ' . $name . ' (id int(11) AUTO_INCREMENT, bool tinyint(1), small_int tinyint(2), primary key(id), KEY `pointless_bool` ( `bool` ), KEY `pointless_small_int` ( `small_int` ), KEY `one_way` ( `bool`, `small_int` ), KEY `other_way` ( `small_int`, `bool` ));'); $expected = array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'pointless_bool' => array('column' => 'bool', 'unique' => 0), 'pointless_small_int' => array('column' => 'small_int', 'unique' => 0), 'one_way' => array('column' => array('bool', 'small_int'), 'unique' => 0), 'other_way' => array('column' => array('small_int', 'bool'), 'unique' => 0), ); $result = $this->Dbo->index('with_multiple_compound_keys', false); $this->Dbo->rawQuery('DROP TABLE ' . $name); $this->assertEquals($expected, $result); $name = $this->Dbo->fullTableName('with_fulltext'); $this->Dbo->rawQuery('CREATE TABLE ' . $name . ' (id int(11) AUTO_INCREMENT, name varchar(255), description text, primary key(id), FULLTEXT KEY `MyFtIndex` ( `name`, `description` )) ENGINE=MyISAM;'); $expected = array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'MyFtIndex' => array('column' => array('name', 'description'), 'type' => 'fulltext') ); $result = $this->Dbo->index('with_fulltext', false); $this->Dbo->rawQuery('DROP TABLE ' . $name); $this->assertEquals($expected, $result); $name = $this->Dbo->fullTableName('with_text_index'); $this->Dbo->rawQuery('CREATE TABLE ' . $name . ' (id int(11) AUTO_INCREMENT, text_field text, primary key(id), KEY `text_index` ( `text_field`(20) ));'); $expected = array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'text_index' => array('column' => 'text_field', 'unique' => 0, 'length' => array('text_field' => 20)), ); $result = $this->Dbo->index('with_text_index', false); $this->Dbo->rawQuery('DROP TABLE ' . $name); $this->assertEquals($expected, $result); $name = $this->Dbo->fullTableName('with_compound_text_index'); $this->Dbo->rawQuery('CREATE TABLE ' . $name . ' (id int(11) AUTO_INCREMENT, text_field1 text, text_field2 text, primary key(id), KEY `text_index` ( `text_field1`(20), `text_field2`(20) ));'); $expected = array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'text_index' => array('column' => array('text_field1', 'text_field2'), 'unique' => 0, 'length' => array('text_field1' => 20, 'text_field2' => 20)), ); $result = $this->Dbo->index('with_compound_text_index', false); $this->Dbo->rawQuery('DROP TABLE ' . $name); $this->assertEquals($expected, $result); } /** * testBuildColumn method * * @return void */ public function testBuildColumn() { $restore = $this->Dbo->columns; $this->Dbo->columns = array('varchar(255)' => 1); $data = array( 'name' => 'testName', 'type' => 'varchar(255)', 'default', 'null' => true, 'key', 'comment' => 'test' ); $result = $this->Dbo->buildColumn($data); $expected = '`testName` DEFAULT NULL COMMENT \'test\''; $this->assertEquals($expected, $result); $data = array( 'name' => 'testName', 'type' => 'varchar(255)', 'default', 'null' => true, 'key', 'charset' => 'utf8', 'collate' => 'utf8_unicode_ci' ); $result = $this->Dbo->buildColumn($data); $expected = '`testName` CHARACTER SET utf8 COLLATE utf8_unicode_ci DEFAULT NULL'; $this->assertEquals($expected, $result); $this->Dbo->columns = $restore; } /** * MySQL 4.x returns index data in a different format, * Using a mock ensure that MySQL 4.x output is properly parsed. * * @group indices * @return void */ public function testIndexOnMySQL4Output() { $name = $this->Dbo->fullTableName('simple'); $mockDbo = $this->getMock('Mysql', array('connect', '_execute', 'getVersion')); $columnData = array( array('0' => array( 'Table' => 'with_compound_keys', 'Non_unique' => '0', 'Key_name' => 'PRIMARY', 'Seq_in_index' => '1', 'Column_name' => 'id', 'Collation' => 'A', 'Cardinality' => '0', 'Sub_part' => null, 'Packed' => null, 'Null' => '', 'Index_type' => 'BTREE', 'Comment' => '' )), array('0' => array( 'Table' => 'with_compound_keys', 'Non_unique' => '1', 'Key_name' => 'pointless_bool', 'Seq_in_index' => '1', 'Column_name' => 'bool', 'Collation' => 'A', 'Cardinality' => null, 'Sub_part' => null, 'Packed' => null, 'Null' => 'YES', 'Index_type' => 'BTREE', 'Comment' => '' )), array('0' => array( 'Table' => 'with_compound_keys', 'Non_unique' => '1', 'Key_name' => 'pointless_small_int', 'Seq_in_index' => '1', 'Column_name' => 'small_int', 'Collation' => 'A', 'Cardinality' => null, 'Sub_part' => null, 'Packed' => null, 'Null' => 'YES', 'Index_type' => 'BTREE', 'Comment' => '' )), array('0' => array( 'Table' => 'with_compound_keys', 'Non_unique' => '1', 'Key_name' => 'one_way', 'Seq_in_index' => '1', 'Column_name' => 'bool', 'Collation' => 'A', 'Cardinality' => null, 'Sub_part' => null, 'Packed' => null, 'Null' => 'YES', 'Index_type' => 'BTREE', 'Comment' => '' )), array('0' => array( 'Table' => 'with_compound_keys', 'Non_unique' => '1', 'Key_name' => 'one_way', 'Seq_in_index' => '2', 'Column_name' => 'small_int', 'Collation' => 'A', 'Cardinality' => null, 'Sub_part' => null, 'Packed' => null, 'Null' => 'YES', 'Index_type' => 'BTREE', 'Comment' => '' )) ); $mockDbo->expects($this->once())->method('getVersion')->will($this->returnValue('4.1')); $resultMock = $this->getMock('PDOStatement', array('fetch')); $mockDbo->expects($this->once()) ->method('_execute') ->with('SHOW INDEX FROM ' . $name) ->will($this->returnValue($resultMock)); foreach ($columnData as $i => $data) { $resultMock->expects($this->at($i))->method('fetch')->will($this->returnValue((object)$data)); } $result = $mockDbo->index($name, false); $expected = array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'pointless_bool' => array('column' => 'bool', 'unique' => 0), 'pointless_small_int' => array('column' => 'small_int', 'unique' => 0), 'one_way' => array('column' => array('bool', 'small_int'), 'unique' => 0), ); $this->assertEquals($expected, $result); } /** * testColumn method * * @return void */ public function testColumn() { $result = $this->Dbo->column('varchar(50)'); $expected = 'string'; $this->assertEquals($expected, $result); $result = $this->Dbo->column('text'); $expected = 'text'; $this->assertEquals($expected, $result); $result = $this->Dbo->column('int(11)'); $expected = 'integer'; $this->assertEquals($expected, $result); $result = $this->Dbo->column('int(11) unsigned'); $expected = 'integer'; $this->assertEquals($expected, $result); $result = $this->Dbo->column('bigint(20)'); $expected = 'biginteger'; $this->assertEquals($expected, $result); $result = $this->Dbo->column('tinyint(1)'); $expected = 'boolean'; $this->assertEquals($expected, $result); $result = $this->Dbo->column('boolean'); $expected = 'boolean'; $this->assertEquals($expected, $result); $result = $this->Dbo->column('float'); $expected = 'float'; $this->assertEquals($expected, $result); $result = $this->Dbo->column('float unsigned'); $expected = 'float'; $this->assertEquals($expected, $result); $result = $this->Dbo->column('double unsigned'); $expected = 'float'; $this->assertEquals($expected, $result); $result = $this->Dbo->column('decimal'); $expected = 'decimal'; $this->assertEquals($expected, $result); $result = $this->Dbo->column('numeric'); $expected = 'decimal'; $this->assertEquals($expected, $result); $result = $this->Dbo->column('decimal(14,7) unsigned'); $expected = 'decimal'; $this->assertEquals($expected, $result); $result = $this->Dbo->column("set('a','b','c')"); $expected = "set('a','b','c')"; $this->assertEquals($expected, $result); } /** * testAlterSchemaIndexes method * * @group indices * @return void */ public function testAlterSchemaIndexes() { $this->Dbo->cacheSources = $this->Dbo->testing = false; $table = $this->Dbo->fullTableName('altertest'); $schemaA = new CakeSchema(array( 'name' => 'AlterTest1', 'connection' => 'test', 'altertest' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'name' => array('type' => 'string', 'null' => false, 'length' => 50), 'group1' => array('type' => 'integer', 'null' => true), 'group2' => array('type' => 'integer', 'null' => true) ))); $result = $this->Dbo->createSchema($schemaA); $this->assertContains('`id` int(11) DEFAULT 0 NOT NULL,', $result); $this->assertContains('`name` varchar(50) NOT NULL,', $result); $this->assertContains('`group1` int(11) DEFAULT NULL', $result); $this->assertContains('`group2` int(11) DEFAULT NULL', $result); //Test that the string is syntactically correct $query = $this->Dbo->getConnection()->prepare($result); $this->assertEquals($query->queryString, $result); $schemaB = new CakeSchema(array( 'name' => 'AlterTest2', 'connection' => 'test', 'altertest' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'name' => array('type' => 'string', 'null' => false, 'length' => 50), 'group1' => array('type' => 'integer', 'null' => true), 'group2' => array('type' => 'integer', 'null' => true), 'indexes' => array( 'name_idx' => array('column' => 'name', 'unique' => 0), 'group_idx' => array('column' => 'group1', 'unique' => 0), 'compound_idx' => array('column' => array('group1', 'group2'), 'unique' => 0), 'PRIMARY' => array('column' => 'id', 'unique' => 1)) ))); $result = $this->Dbo->alterSchema($schemaB->compare($schemaA)); $this->assertContains("ALTER TABLE $table", $result); $this->assertContains('ADD KEY `name_idx` (`name`),', $result); $this->assertContains('ADD KEY `group_idx` (`group1`),', $result); $this->assertContains('ADD KEY `compound_idx` (`group1`, `group2`),', $result); $this->assertContains('ADD PRIMARY KEY (`id`);', $result); //Test that the string is syntactically correct $query = $this->Dbo->getConnection()->prepare($result); $this->assertEquals($query->queryString, $result); // Change three indexes, delete one and add another one $schemaC = new CakeSchema(array( 'name' => 'AlterTest3', 'connection' => 'test', 'altertest' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'name' => array('type' => 'string', 'null' => false, 'length' => 50), 'group1' => array('type' => 'integer', 'null' => true), 'group2' => array('type' => 'integer', 'null' => true), 'indexes' => array( 'name_idx' => array('column' => 'name', 'unique' => 1), 'group_idx' => array('column' => 'group2', 'unique' => 0), 'compound_idx' => array('column' => array('group2', 'group1'), 'unique' => 0), 'id_name_idx' => array('column' => array('id', 'name'), 'unique' => 0)) ))); $result = $this->Dbo->alterSchema($schemaC->compare($schemaB)); $this->assertContains("ALTER TABLE $table", $result); $this->assertContains('DROP PRIMARY KEY,', $result); $this->assertContains('DROP KEY `name_idx`,', $result); $this->assertContains('DROP KEY `group_idx`,', $result); $this->assertContains('DROP KEY `compound_idx`,', $result); $this->assertContains('ADD KEY `id_name_idx` (`id`, `name`),', $result); $this->assertContains('ADD UNIQUE KEY `name_idx` (`name`),', $result); $this->assertContains('ADD KEY `group_idx` (`group2`),', $result); $this->assertContains('ADD KEY `compound_idx` (`group2`, `group1`);', $result); $query = $this->Dbo->getConnection()->prepare($result); $this->assertEquals($query->queryString, $result); // Compare us to ourself. $this->assertEquals(array(), $schemaC->compare($schemaC)); // Drop the indexes $result = $this->Dbo->alterSchema($schemaA->compare($schemaC)); $this->assertContains("ALTER TABLE $table", $result); $this->assertContains('DROP KEY `name_idx`,', $result); $this->assertContains('DROP KEY `group_idx`,', $result); $this->assertContains('DROP KEY `compound_idx`,', $result); $this->assertContains('DROP KEY `id_name_idx`;', $result); $query = $this->Dbo->getConnection()->prepare($result); $this->assertEquals($query->queryString, $result); } /** * test saving and retrieval of blobs * * @return void */ public function testBlobSaving() { $this->loadFixtures('BinaryTest'); $this->Dbo->cacheSources = false; $data = file_get_contents(CAKE . 'Test' . DS . 'test_app' . DS . 'webroot' . DS . 'img' . DS . 'cake.power.gif'); $model = new CakeTestModel(array('name' => 'BinaryTest', 'ds' => 'test')); $model->save(compact('data')); $result = $model->find('first'); $this->assertEquals($data, $result['BinaryTest']['data']); } /** * test altering the table settings with schema. * * @return void */ public function testAlteringTableParameters() { $this->Dbo->cacheSources = $this->Dbo->testing = false; $schemaA = new CakeSchema(array( 'name' => 'AlterTest1', 'connection' => 'test', 'altertest' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'name' => array('type' => 'string', 'null' => false, 'length' => 50), 'tableParameters' => array( 'charset' => 'latin1', 'collate' => 'latin1_general_ci', 'engine' => 'MyISAM' ) ) )); $this->Dbo->rawQuery($this->Dbo->createSchema($schemaA)); $schemaB = new CakeSchema(array( 'name' => 'AlterTest1', 'connection' => 'test', 'altertest' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'name' => array('type' => 'string', 'null' => false, 'length' => 50), 'tableParameters' => array( 'charset' => 'utf8', 'collate' => 'utf8_general_ci', 'engine' => 'InnoDB', 'comment' => 'Newly table added comment.', ) ) )); $result = $this->Dbo->alterSchema($schemaB->compare($schemaA)); $this->assertContains('DEFAULT CHARSET=utf8', $result); $this->assertContains('ENGINE=InnoDB', $result); $this->assertContains('COLLATE=utf8_general_ci', $result); $this->assertContains('COMMENT=\'Newly table added comment.\'', $result); $this->Dbo->rawQuery($result); $result = $this->Dbo->listDetailedSources($this->Dbo->fullTableName('altertest', false, false)); $this->assertEquals('utf8_general_ci', $result['Collation']); $this->assertEquals('InnoDB', $result['Engine']); $this->assertEquals('utf8', $result['charset']); $this->Dbo->rawQuery($this->Dbo->dropSchema($schemaA)); } /** * test alterSchema on two tables. * * @return void */ public function testAlteringTwoTables() { $schema1 = new CakeSchema(array( 'name' => 'AlterTest1', 'connection' => 'test', 'altertest' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'name' => array('type' => 'string', 'null' => false, 'length' => 50), ), 'other_table' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'name' => array('type' => 'string', 'null' => false, 'length' => 50), ) )); $schema2 = new CakeSchema(array( 'name' => 'AlterTest1', 'connection' => 'test', 'altertest' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'field_two' => array('type' => 'string', 'null' => false, 'length' => 50), ), 'other_table' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'field_two' => array('type' => 'string', 'null' => false, 'length' => 50), ) )); $result = $this->Dbo->alterSchema($schema2->compare($schema1)); $this->assertEquals(2, substr_count($result, 'field_two'), 'Too many fields'); } /** * testReadTableParameters method * * @return void */ public function testReadTableParameters() { $this->Dbo->cacheSources = $this->Dbo->testing = false; $tableName = 'tinyint_' . uniqid(); $table = $this->Dbo->fullTableName($tableName); $this->Dbo->rawQuery('CREATE TABLE ' . $table . ' (id int(11) AUTO_INCREMENT, bool tinyint(1), small_int tinyint(2), primary key(id)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;'); $result = $this->Dbo->readTableParameters($this->Dbo->fullTableName($tableName, false, false)); $this->Dbo->rawQuery('DROP TABLE ' . $table); $expected = array( 'charset' => 'utf8', 'collate' => 'utf8_unicode_ci', 'engine' => 'InnoDB'); $this->assertEquals($expected, $result); $table = $this->Dbo->fullTableName($tableName); $this->Dbo->rawQuery('CREATE TABLE ' . $table . ' (id int(11) AUTO_INCREMENT, bool tinyint(1), small_int tinyint(2), primary key(id)) ENGINE=MyISAM DEFAULT CHARSET=cp1250 COLLATE=cp1250_general_ci COMMENT=\'Table\'\'s comment\';'); $result = $this->Dbo->readTableParameters($this->Dbo->fullTableName($tableName, false, false)); $this->Dbo->rawQuery('DROP TABLE ' . $table); $expected = array( 'charset' => 'cp1250', 'collate' => 'cp1250_general_ci', 'engine' => 'MyISAM', 'comment' => 'Table\'s comment', ); $this->assertEquals($expected, $result); } /** * testBuildTableParameters method * * @return void */ public function testBuildTableParameters() { $this->Dbo->cacheSources = $this->Dbo->testing = false; $data = array( 'charset' => 'utf8', 'collate' => 'utf8_unicode_ci', 'engine' => 'InnoDB'); $result = $this->Dbo->buildTableParameters($data); $expected = array( 'DEFAULT CHARSET=utf8', 'COLLATE=utf8_unicode_ci', 'ENGINE=InnoDB'); $this->assertEquals($expected, $result); } /** * testGetCharsetName method * * @return void */ public function testGetCharsetName() { $this->Dbo->cacheSources = $this->Dbo->testing = false; $result = $this->Dbo->getCharsetName('utf8_unicode_ci'); $this->assertEquals('utf8', $result); $result = $this->Dbo->getCharsetName('cp1250_general_ci'); $this->assertEquals('cp1250', $result); } /** * testGetCharsetNameCaching method * * @return void */ public function testGetCharsetNameCaching() { $db = $this->getMock('Mysql', array('connect', '_execute', 'getVersion')); $queryResult = $this->getMock('PDOStatement'); $db->expects($this->exactly(2))->method('getVersion')->will($this->returnValue('5.1')); $db->expects($this->exactly(1)) ->method('_execute') ->with('SELECT CHARACTER_SET_NAME FROM INFORMATION_SCHEMA.COLLATIONS WHERE COLLATION_NAME = ?', array('utf8_unicode_ci')) ->will($this->returnValue($queryResult)); $queryResult->expects($this->once()) ->method('fetch') ->with(PDO::FETCH_ASSOC) ->will($this->returnValue(array('CHARACTER_SET_NAME' => 'utf8'))); $result = $db->getCharsetName('utf8_unicode_ci'); $this->assertEquals('utf8', $result); $result = $db->getCharsetName('utf8_unicode_ci'); $this->assertEquals('utf8', $result); } /** * test that changing the virtualFieldSeparator allows for __ fields. * * @return void */ public function testVirtualFieldSeparators() { $this->loadFixtures('BinaryTest'); $model = new CakeTestModel(array('table' => 'binary_tests', 'ds' => 'test', 'name' => 'BinaryTest')); $model->virtualFields = array( 'other__field' => 'SUM(id)' ); $this->Dbo->virtualFieldSeparator = '_$_'; $result = $this->Dbo->fields($model, null, array('data', 'other__field')); $expected = array('`BinaryTest`.`data`', '(SUM(id)) AS `BinaryTest_$_other__field`'); $this->assertEquals($expected, $result); } /** * Test describe() on a fixture. * * @return void */ public function testDescribe() { $this->loadFixtures('Apple'); $model = new Apple(); $result = $this->Dbo->describe($model); $this->assertTrue(isset($result['id'])); $this->assertTrue(isset($result['color'])); $result = $this->Dbo->describe($model->useTable); $this->assertTrue(isset($result['id'])); $this->assertTrue(isset($result['color'])); } /** * Test that describe() ignores `default current_timestamp` in timestamp columns. * * @return void */ public function testDescribeHandleCurrentTimestamp() { $name = $this->Dbo->fullTableName('timestamp_default_values'); $sql = <<Dbo->execute($sql); $model = new Model(array( 'table' => 'timestamp_default_values', 'ds' => 'test', 'alias' => 'TimestampDefaultValue' )); $result = $this->Dbo->describe($model); $this->Dbo->execute('DROP TABLE ' . $name); $this->assertNull($result['limit_date']['default']); $schema = new CakeSchema(array( 'connection' => 'test', 'testdescribes' => $result )); $result = $this->Dbo->createSchema($schema); $this->assertContains('`limit_date` timestamp NOT NULL,', $result); } /** * Test that describe() ignores `default current_timestamp` in datetime columns. * This is for MySQL >= 5.6. * * @return void */ public function testDescribeHandleCurrentTimestampDatetime() { $mysqlVersion = $this->Dbo->query('SELECT VERSION() as version', array('log' => false)); $this->skipIf(version_compare($mysqlVersion[0][0]['version'], '5.6.0', '<')); $name = $this->Dbo->fullTableName('timestamp_default_values'); $sql = <<Dbo->execute($sql); $model = new Model(array( 'table' => 'timestamp_default_values', 'ds' => 'test', 'alias' => 'TimestampDefaultValue' )); $result = $this->Dbo->describe($model); $this->Dbo->execute('DROP TABLE ' . $name); $this->assertNull($result['limit_date']['default']); $schema = new CakeSchema(array( 'connection' => 'test', 'testdescribes' => $result )); $result = $this->Dbo->createSchema($schema); $this->assertContains('`limit_date` datetime NOT NULL,', $result); } /** * test that a describe() gets additional fieldParameters * * @return void */ public function testDescribeGettingFieldParameters() { $schema = new CakeSchema(array( 'connection' => 'test', 'testdescribes' => array( 'id' => array('type' => 'integer', 'key' => 'primary'), 'stringy' => array( 'type' => 'string', 'null' => true, 'charset' => 'cp1250', 'collate' => 'cp1250_general_ci', ), 'other_col' => array( 'type' => 'string', 'null' => false, 'charset' => 'latin1', 'comment' => 'Test Comment' ) ) )); $this->Dbo->execute($this->Dbo->createSchema($schema)); $model = new CakeTestModel(array('table' => 'testdescribes', 'name' => 'Testdescribes')); $result = $model->getDataSource()->describe($model); $this->Dbo->execute($this->Dbo->dropSchema($schema)); $this->assertEquals('cp1250_general_ci', $result['stringy']['collate']); $this->assertEquals('cp1250', $result['stringy']['charset']); $this->assertEquals('Test Comment', $result['other_col']['comment']); } /** * Test that two columns with key => primary doesn't create invalid sql. * * @return void */ public function testTwoColumnsWithPrimaryKey() { $schema = new CakeSchema(array( 'connection' => 'test', 'roles_users' => array( 'role_id' => array( 'type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary' ), 'user_id' => array( 'type' => 'integer', 'null' => false, 'default' => null, 'key' => 'primary' ), 'indexes' => array( 'user_role_index' => array( 'column' => array('role_id', 'user_id'), 'unique' => 1 ), 'user_index' => array( 'column' => 'user_id', 'unique' => 0 ) ), ) )); $result = $this->Dbo->createSchema($schema); $this->assertContains('`role_id` int(11) NOT NULL,', $result); $this->assertContains('`user_id` int(11) NOT NULL,', $result); } /** * Test that the primary flag is handled correctly. * * @return void */ public function testCreateSchemaAutoPrimaryKey() { $schema = new CakeSchema(); $schema->tables = array( 'no_indexes' => array( 'id' => array('type' => 'integer', 'null' => false, 'key' => 'primary'), 'data' => array('type' => 'integer', 'null' => false), 'indexes' => array(), ) ); $result = $this->Dbo->createSchema($schema, 'no_indexes'); $this->assertContains('PRIMARY KEY (`id`)', $result); $this->assertNotContains('UNIQUE KEY', $result); $schema->tables = array( 'primary_index' => array( 'id' => array('type' => 'integer', 'null' => false), 'data' => array('type' => 'integer', 'null' => false), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'some_index' => array('column' => 'data', 'unique' => 1) ), ) ); $result = $this->Dbo->createSchema($schema, 'primary_index'); $this->assertContains('PRIMARY KEY (`id`)', $result); $this->assertContains('UNIQUE KEY `some_index` (`data`)', $result); $schema->tables = array( 'primary_flag_has_index' => array( 'id' => array('type' => 'integer', 'null' => false, 'key' => 'primary'), 'data' => array('type' => 'integer', 'null' => false), 'indexes' => array( 'some_index' => array('column' => 'data', 'unique' => 1) ), ) ); $result = $this->Dbo->createSchema($schema, 'primary_flag_has_index'); $this->assertContains('PRIMARY KEY (`id`)', $result); $this->assertContains('UNIQUE KEY `some_index` (`data`)', $result); } /** * Tests that listSources method sends the correct query and parses the result accordingly * @return void */ public function testListSources() { $db = $this->getMock('Mysql', array('connect', '_execute')); $queryResult = $this->getMock('PDOStatement'); $db->expects($this->once()) ->method('_execute') ->with('SHOW TABLES FROM `cake`') ->will($this->returnValue($queryResult)); $queryResult->expects($this->at(0)) ->method('fetch') ->will($this->returnValue(array('cake_table'))); $queryResult->expects($this->at(1)) ->method('fetch') ->will($this->returnValue(array('another_table'))); $queryResult->expects($this->at(2)) ->method('fetch') ->will($this->returnValue(null)); $tables = $db->listSources(); $this->assertEquals(array('cake_table', 'another_table'), $tables); } /** * test that listDetailedSources with a named table that doesn't exist. * * @return void */ public function testListDetailedSourcesNamed() { $this->loadFixtures('Apple'); $result = $this->Dbo->listDetailedSources('imaginary'); $this->assertEquals(array(), $result, 'Should be empty when table does not exist.'); $result = $this->Dbo->listDetailedSources(); $tableName = $this->Dbo->fullTableName('apples', false, false); $this->assertTrue(isset($result[$tableName]), 'Key should exist'); } /** * Tests that getVersion method sends the correct query for getting the mysql version * @return void */ public function testGetVersion() { $version = $this->Dbo->getVersion(); $this->assertTrue(is_string($version)); } /** * Tests that getVersion method sends the correct query for getting the client encoding * @return void */ public function testGetEncoding() { $db = $this->getMock('Mysql', array('connect', '_execute')); $queryResult = $this->getMock('PDOStatement'); $db->expects($this->once()) ->method('_execute') ->with('SHOW VARIABLES LIKE ?', array('character_set_client')) ->will($this->returnValue($queryResult)); $result = new StdClass; $result->Value = 'utf-8'; $queryResult->expects($this->once()) ->method('fetchObject') ->will($this->returnValue($result)); $encoding = $db->getEncoding(); $this->assertEquals('utf-8', $encoding); } /** * testFieldDoubleEscaping method * * @return void */ public function testFieldDoubleEscaping() { $db = $this->Dbo->config['database']; $test = $this->getMock('Mysql', array('connect', '_execute', 'execute')); $test->config['database'] = $db; $this->Model = $this->getMock('Article2', array('getDataSource')); $this->Model->alias = 'Article'; $this->Model->expects($this->any()) ->method('getDataSource') ->will($this->returnValue($test)); $this->assertEquals('`Article`.`id`', $this->Model->escapeField()); $result = $test->fields($this->Model, null, $this->Model->escapeField()); $this->assertEquals(array('`Article`.`id`'), $result); $test->expects($this->at(0))->method('execute') ->with('SELECT `Article`.`id` FROM ' . $test->fullTableName('articles') . ' AS `Article` WHERE 1 = 1'); $result = $test->read($this->Model, array( 'fields' => $this->Model->escapeField(), 'conditions' => null, 'recursive' => -1 )); $test->startQuote = '['; $test->endQuote = ']'; $this->assertEquals('[Article].[id]', $this->Model->escapeField()); $result = $test->fields($this->Model, null, $this->Model->escapeField()); $this->assertEquals(array('[Article].[id]'), $result); $test->expects($this->at(0))->method('execute') ->with('SELECT [Article].[id] FROM ' . $test->fullTableName('articles') . ' AS [Article] WHERE 1 = 1'); $result = $test->read($this->Model, array( 'fields' => $this->Model->escapeField(), 'conditions' => null, 'recursive' => -1 )); } /** * testGenerateAssociationQuerySelfJoin method * * @return void */ public function testGenerateAssociationQuerySelfJoin() { $this->Dbo = $this->getMock('Mysql', array('connect', '_execute', 'execute')); $this->startTime = microtime(true); $this->Model = new Article2(); $this->_buildRelatedModels($this->Model); $this->_buildRelatedModels($this->Model->Category2); $this->Model->Category2->ChildCat = new Category2(); $this->Model->Category2->ParentCat = new Category2(); $queryData = array(); foreach ($this->Model->Category2->associations() as $type) { foreach ($this->Model->Category2->{$type} as $assoc => $assocData) { $linkModel = $this->Model->Category2->{$assoc}; $external = isset($assocData['external']); if ($this->Model->Category2->alias === $linkModel->alias && $type !== 'hasAndBelongsToMany' && $type !== 'hasMany' ) { $result = $this->Dbo->generateAssociationQuery($this->Model->Category2, $linkModel, $type, $assoc, $assocData, $queryData, $external); $this->assertFalse(empty($result)); } else { if ($this->Model->Category2->useDbConfig === $linkModel->useDbConfig) { $result = $this->Dbo->generateAssociationQuery($this->Model->Category2, $linkModel, $type, $assoc, $assocData, $queryData, $external); $this->assertFalse(empty($result)); } } } } $query = $this->Dbo->buildAssociationQuery($this->Model->Category2, $queryData); $this->assertRegExp('/^SELECT\s+(.+)FROM(.+)`Category2`\.`group_id`\s+=\s+`Group`\.`id`\)\s+LEFT JOIN(.+)WHERE\s+1 = 1\s*$/', $query); $this->Model = new TestModel4(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'belongsTo', 'model' => 'TestModel4Parent'); $queryData = array(); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $_queryData = $queryData; $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertTrue($result); $expected = array( 'conditions' => array(), 'fields' => array( '`TestModel4`.`id`', '`TestModel4`.`name`', '`TestModel4`.`created`', '`TestModel4`.`updated`', '`TestModel4Parent`.`id`', '`TestModel4Parent`.`name`', '`TestModel4Parent`.`created`', '`TestModel4Parent`.`updated`' ), 'joins' => array( array( 'table' => $this->Dbo->fullTableName($this->Model), 'alias' => 'TestModel4Parent', 'type' => 'LEFT', 'conditions' => '`TestModel4`.`parent_id` = `TestModel4Parent`.`id`' ) ), 'order' => array(), 'limit' => array(), 'offset' => array(), 'group' => array(), 'callbacks' => null ); $queryData['joins'][0]['table'] = $this->Dbo->fullTableName($queryData['joins'][0]['table']); $this->assertEquals($expected, $queryData); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`, `TestModel4Parent`\.`id`, `TestModel4Parent`\.`name`, `TestModel4Parent`\.`created`, `TestModel4Parent`\.`updated`\s+/', $result); $this->assertRegExp('/FROM\s+\S+`test_model4` AS `TestModel4`\s+LEFT JOIN\s+\S+`test_model4` AS `TestModel4Parent`/', $result); $this->assertRegExp('/\s+ON\s+\(`TestModel4`.`parent_id` = `TestModel4Parent`.`id`\)\s+WHERE/', $result); $this->assertRegExp('/\s+WHERE\s+1 = 1$/', $result); $params['assocData']['type'] = 'INNER'; $this->Model->belongsTo['TestModel4Parent']['type'] = 'INNER'; $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $_queryData, $params['external']); $this->assertTrue($result); $this->assertEquals('INNER', $_queryData['joins'][0]['type']); } /** * buildRelatedModels method * * @param Model $model * @return void */ protected function _buildRelatedModels(Model $model) { foreach ($model->associations() as $type) { foreach ($model->{$type} as $assocData) { if (is_string($assocData)) { $className = $assocData; } elseif (isset($assocData['className'])) { $className = $assocData['className']; } $model->$className = new $className(); $model->$className->schema(); } } } /** * &_prepareAssociationQuery method * * @param Model $model * @param array $queryData * @param array $binding * @return array The prepared association query */ protected function &_prepareAssociationQuery(Model $model, &$queryData, $binding) { $type = $binding['type']; $assoc = $binding['model']; $assocData = $model->{$type}[$assoc]; $className = $assocData['className']; $linkModel = $model->{$className}; $external = isset($assocData['external']); $queryData = $this->_scrubQueryData($queryData); $result = array_merge(array('linkModel' => &$linkModel), compact('type', 'assoc', 'assocData', 'external')); return $result; } /** * Helper method copied from DboSource::_scrubQueryData() * * @param array $data * @return array */ protected function _scrubQueryData($data) { static $base = null; if ($base === null) { $base = array_fill_keys(array('conditions', 'fields', 'joins', 'order', 'limit', 'offset', 'group'), array()); $base['callbacks'] = null; } return (array)$data + $base; } /** * test that read() places provided joins after the generated ones. * * @return void */ public function testReadCustomJoinsAfterGeneratedJoins() { $db = $this->Dbo->config['database']; $test = $this->getMock('Mysql', array('connect', '_execute', 'execute')); $test->config['database'] = $db; $this->Model = $this->getMock('TestModel9', array('getDataSource')); $this->Model->expects($this->any()) ->method('getDataSource') ->will($this->returnValue($test)); $this->Model->TestModel8 = $this->getMock('TestModel8', array('getDataSource')); $this->Model->TestModel8->expects($this->any()) ->method('getDataSource') ->will($this->returnValue($test)); $model8Table = $test->fullTableName($this->Model->TestModel8); $usersTable = $test->fullTableName('users'); $search = "LEFT JOIN $model8Table AS `TestModel8` ON " . "(`TestModel8`.`name` != 'larry' AND `TestModel9`.`test_model8_id` = `TestModel8`.`id`) " . "LEFT JOIN $usersTable AS `User` ON (`TestModel9`.`id` = `User`.`test_id`)"; $test->expects($this->at(0))->method('execute') ->with($this->stringContains($search)); $test->read($this->Model, array( 'joins' => array( array( 'table' => 'users', 'alias' => 'User', 'type' => 'LEFT', 'conditions' => array('TestModel9.id = User.test_id') ) ), 'recursive' => 1 )); } /** * testGenerateInnerJoinAssociationQuery method * * @return void */ public function testGenerateInnerJoinAssociationQuery() { $db = $this->Dbo->config['database']; $test = $this->getMock('Mysql', array('connect', '_execute', 'execute')); $test->config['database'] = $db; $this->Model = $this->getMock('TestModel9', array('getDataSource')); $this->Model->expects($this->any()) ->method('getDataSource') ->will($this->returnValue($test)); $this->Model->TestModel8 = $this->getMock('TestModel8', array('getDataSource')); $this->Model->TestModel8->expects($this->any()) ->method('getDataSource') ->will($this->returnValue($test)); $testModel8Table = $this->Model->TestModel8->getDataSource()->fullTableName($this->Model->TestModel8); $test->expects($this->at(0))->method('execute') ->with($this->stringContains('`TestModel9` LEFT JOIN ' . $testModel8Table)); $test->expects($this->at(1))->method('execute') ->with($this->stringContains('TestModel9` INNER JOIN ' . $testModel8Table)); $test->read($this->Model, array('recursive' => 1)); $this->Model->belongsTo['TestModel8']['type'] = 'INNER'; $test->read($this->Model, array('recursive' => 1)); } /** * testGenerateAssociationQuerySelfJoinWithConditionsInHasOneBinding method * * @return void */ public function testGenerateAssociationQuerySelfJoinWithConditionsInHasOneBinding() { $this->Model = new TestModel8(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'hasOne', 'model' => 'TestModel9'); $queryData = array(); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertTrue($result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel8`\.`id`, `TestModel8`\.`test_model9_id`, `TestModel8`\.`name`, `TestModel8`\.`created`, `TestModel8`\.`updated`, `TestModel9`\.`id`, `TestModel9`\.`test_model8_id`, `TestModel9`\.`name`, `TestModel9`\.`created`, `TestModel9`\.`updated`\s+/', $result); $this->assertRegExp('/FROM\s+\S+`test_model8` AS `TestModel8`\s+LEFT JOIN\s+\S+`test_model9` AS `TestModel9`/', $result); $this->assertRegExp('/\s+ON\s+\(`TestModel9`\.`name` != \'mariano\'\s+AND\s+`TestModel9`.`test_model8_id` = `TestModel8`.`id`\)\s+WHERE/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); } /** * testGenerateAssociationQuerySelfJoinWithConditionsInBelongsToBinding method * * @return void */ public function testGenerateAssociationQuerySelfJoinWithConditionsInBelongsToBinding() { $this->Model = new TestModel9(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'belongsTo', 'model' => 'TestModel8'); $queryData = array(); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertTrue($result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel9`\.`id`, `TestModel9`\.`test_model8_id`, `TestModel9`\.`name`, `TestModel9`\.`created`, `TestModel9`\.`updated`, `TestModel8`\.`id`, `TestModel8`\.`test_model9_id`, `TestModel8`\.`name`, `TestModel8`\.`created`, `TestModel8`\.`updated`\s+/', $result); $this->assertRegExp('/FROM\s+\S+`test_model9` AS `TestModel9`\s+LEFT JOIN\s+\S+`test_model8` AS `TestModel8`/', $result); $this->assertRegExp('/\s+ON\s+\(`TestModel8`\.`name` != \'larry\'\s+AND\s+`TestModel9`.`test_model8_id` = `TestModel8`.`id`\)\s+WHERE/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); } /** * testGenerateAssociationQuerySelfJoinWithConditions method * * @return void */ public function testGenerateAssociationQuerySelfJoinWithConditions() { $this->Model = new TestModel4(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'belongsTo', 'model' => 'TestModel4Parent'); $queryData = array('conditions' => array('TestModel4Parent.name !=' => 'mariano')); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertTrue($result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`, `TestModel4Parent`\.`id`, `TestModel4Parent`\.`name`, `TestModel4Parent`\.`created`, `TestModel4Parent`\.`updated`\s+/', $result); $this->assertRegExp('/FROM\s+\S+`test_model4` AS `TestModel4`\s+LEFT JOIN\s+\S+`test_model4` AS `TestModel4Parent`/', $result); $this->assertRegExp('/\s+ON\s+\(`TestModel4`.`parent_id` = `TestModel4Parent`.`id`\)\s+WHERE/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?`TestModel4Parent`.`name`\s+!=\s+\'mariano\'(?:\))?\s*$/', $result); $this->Featured2 = new Featured2(); $this->Featured2->schema(); $this->Featured2->bindModel(array( 'belongsTo' => array( 'ArticleFeatured2' => array( 'conditions' => 'ArticleFeatured2.published = \'Y\'', 'fields' => 'id, title, user_id, published' ) ) )); $this->_buildRelatedModels($this->Featured2); $binding = array('type' => 'belongsTo', 'model' => 'ArticleFeatured2'); $queryData = array('conditions' => array()); $params = &$this->_prepareAssociationQuery($this->Featured2, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Featured2, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertTrue($result); $result = $this->Dbo->buildAssociationQuery($this->Featured2, $queryData); $this->assertRegExp( '/^SELECT\s+`Featured2`\.`id`, `Featured2`\.`article_id`, `Featured2`\.`category_id`, `Featured2`\.`name`,\s+' . '`ArticleFeatured2`\.`id`, `ArticleFeatured2`\.`title`, `ArticleFeatured2`\.`user_id`, `ArticleFeatured2`\.`published`\s+' . 'FROM\s+\S+`featured2` AS `Featured2`\s+LEFT JOIN\s+\S+`article_featured` AS `ArticleFeatured2`' . '\s+ON\s+\(`ArticleFeatured2`.`published` = \'Y\'\s+AND\s+`Featured2`\.`article_featured2_id` = `ArticleFeatured2`\.`id`\)' . '\s+WHERE\s+1\s+=\s+1\s*$/', $result ); } /** * testGenerateAssociationQueryHasOne method * * @return void */ public function testGenerateAssociationQueryHasOne() { $this->Model = new TestModel4(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'hasOne', 'model' => 'TestModel5'); $queryData = array(); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertTrue($result); $testModel5Table = $this->Dbo->fullTableName($this->Model->TestModel5); $result = $this->Dbo->buildJoinStatement($queryData['joins'][0]); $expected = ' LEFT JOIN ' . $testModel5Table . ' AS `TestModel5` ON (`TestModel5`.`test_model4_id` = `TestModel4`.`id`)'; $this->assertEquals(trim($expected), trim($result)); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`, `TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model4` AS `TestModel4`\s+LEFT JOIN\s+/', $result); $this->assertRegExp('/`test_model5` AS `TestModel5`\s+ON\s+\(`TestModel5`.`test_model4_id` = `TestModel4`.`id`\)\s+WHERE/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?\s*1 = 1\s*(?:\))?\s*$/', $result); } /** * testGenerateAssociationQueryHasOneWithConditions method * * @return void */ public function testGenerateAssociationQueryHasOneWithConditions() { $this->Model = new TestModel4(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'hasOne', 'model' => 'TestModel5'); $queryData = array('conditions' => array('TestModel5.name !=' => 'mariano')); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertTrue($result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`, `TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model4` AS `TestModel4`\s+LEFT JOIN\s+\S+`test_model5` AS `TestModel5`/', $result); $this->assertRegExp('/\s+ON\s+\(`TestModel5`.`test_model4_id`\s+=\s+`TestModel4`.`id`\)\s+WHERE/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?\s*`TestModel5`.`name`\s+!=\s+\'mariano\'\s*(?:\))?\s*$/', $result); } /** * testGenerateAssociationQueryBelongsTo method * * @return void */ public function testGenerateAssociationQueryBelongsTo() { $this->Model = new TestModel5(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'belongsTo', 'model' => 'TestModel4'); $queryData = array(); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertTrue($result); $testModel4Table = $this->Dbo->fullTableName($this->Model->TestModel4, true, true); $result = $this->Dbo->buildJoinStatement($queryData['joins'][0]); $expected = ' LEFT JOIN ' . $testModel4Table . ' AS `TestModel4` ON (`TestModel5`.`test_model4_id` = `TestModel4`.`id`)'; $this->assertEquals(trim($expected), trim($result)); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`, `TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model5` AS `TestModel5`\s+LEFT JOIN\s+\S+`test_model4` AS `TestModel4`/', $result); $this->assertRegExp('/\s+ON\s+\(`TestModel5`.`test_model4_id` = `TestModel4`.`id`\)\s+WHERE\s+/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?\s*1 = 1\s*(?:\))?\s*$/', $result); } /** * testGenerateAssociationQueryBelongsToWithConditions method * * @return void */ public function testGenerateAssociationQueryBelongsToWithConditions() { $this->Model = new TestModel5(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'belongsTo', 'model' => 'TestModel4'); $queryData = array('conditions' => array('TestModel5.name !=' => 'mariano')); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertTrue($result); $testModel4Table = $this->Dbo->fullTableName($this->Model->TestModel4, true, true); $result = $this->Dbo->buildJoinStatement($queryData['joins'][0]); $expected = ' LEFT JOIN ' . $testModel4Table . ' AS `TestModel4` ON (`TestModel5`.`test_model4_id` = `TestModel4`.`id`)'; $this->assertEquals(trim($expected), trim($result)); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`, `TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model5` AS `TestModel5`\s+LEFT JOIN\s+\S+`test_model4` AS `TestModel4`/', $result); $this->assertRegExp('/\s+ON\s+\(`TestModel5`.`test_model4_id` = `TestModel4`.`id`\)\s+WHERE\s+/', $result); $this->assertRegExp('/\s+WHERE\s+`TestModel5`.`name` != \'mariano\'\s*$/', $result); } /** * testGenerateAssociationQueryHasMany method * * @return void */ public function testGenerateAssociationQueryHasMany() { $this->Model = new TestModel5(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $queryData = array(); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp('/^SELECT\s+`TestModel6`\.`id`, `TestModel6`\.`test_model5_id`, `TestModel6`\.`name`, `TestModel6`\.`created`, `TestModel6`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model6` AS `TestModel6`\s+WHERE/', $result); $this->assertRegExp('/\s+WHERE\s+`TestModel6`.`test_model5_id`\s+=\s+\({\$__cakeID__\$}\)/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model5` AS `TestModel5`\s+WHERE\s+/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?\s*1 = 1\s*(?:\))?\s*$/', $result); } /** * testGenerateAssociationQueryHasManyWithLimit method * * @return void */ public function testGenerateAssociationQueryHasManyWithLimit() { $this->Model = new TestModel5(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $this->Model->hasMany['TestModel6']['limit'] = 2; $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $queryData = array(); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp( '/^SELECT\s+' . '`TestModel6`\.`id`, `TestModel6`\.`test_model5_id`, `TestModel6`\.`name`, `TestModel6`\.`created`, `TestModel6`\.`updated`\s+' . 'FROM\s+\S+`test_model6` AS `TestModel6`\s+WHERE\s+' . '`TestModel6`.`test_model5_id`\s+=\s+\({\$__cakeID__\$}\)\s*' . 'LIMIT \d*' . '\s*$/', $result ); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp( '/^SELECT\s+' . '`TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`\s+' . 'FROM\s+\S+`test_model5` AS `TestModel5`\s+WHERE\s+' . '(?:\()?\s*1 = 1\s*(?:\))?' . '\s*$/', $result ); } /** * testGenerateAssociationQueryHasManyWithConditions method * * @return void */ public function testGenerateAssociationQueryHasManyWithConditions() { $this->Model = new TestModel5(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $queryData = array('conditions' => array('TestModel5.name !=' => 'mariano')); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp('/^SELECT\s+`TestModel6`\.`id`, `TestModel6`\.`test_model5_id`, `TestModel6`\.`name`, `TestModel6`\.`created`, `TestModel6`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model6` AS `TestModel6`\s+WHERE\s+/', $result); $this->assertRegExp('/WHERE\s+(?:\()?`TestModel6`\.`test_model5_id`\s+=\s+\({\$__cakeID__\$}\)(?:\))?/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model5` AS `TestModel5`\s+WHERE\s+/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?`TestModel5`.`name`\s+!=\s+\'mariano\'(?:\))?\s*$/', $result); } /** * testGenerateAssociationQueryHasManyWithOffsetAndLimit method * * @return void */ public function testGenerateAssociationQueryHasManyWithOffsetAndLimit() { $this->Model = new TestModel5(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $backup = $this->Model->hasMany['TestModel6']; $this->Model->hasMany['TestModel6']['offset'] = 2; $this->Model->hasMany['TestModel6']['limit'] = 5; $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $queryData = array(); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp('/^SELECT\s+`TestModel6`\.`id`, `TestModel6`\.`test_model5_id`, `TestModel6`\.`name`, `TestModel6`\.`created`, `TestModel6`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model6` AS `TestModel6`\s+WHERE\s+/', $result); $this->assertRegExp('/WHERE\s+(?:\()?`TestModel6`\.`test_model5_id`\s+=\s+\({\$__cakeID__\$}\)(?:\))?/', $result); $this->assertRegExp('/\s+LIMIT 2,\s*5\s*$/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model5` AS `TestModel5`\s+WHERE\s+/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); $this->Model->hasMany['TestModel6'] = $backup; } /** * testGenerateAssociationQueryHasManyWithPageAndLimit method * * @return void */ public function testGenerateAssociationQueryHasManyWithPageAndLimit() { $this->Model = new TestModel5(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $backup = $this->Model->hasMany['TestModel6']; $this->Model->hasMany['TestModel6']['page'] = 2; $this->Model->hasMany['TestModel6']['limit'] = 5; $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp('/^SELECT\s+`TestModel6`\.`id`, `TestModel6`\.`test_model5_id`, `TestModel6`\.`name`, `TestModel6`\.`created`, `TestModel6`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model6` AS `TestModel6`\s+WHERE\s+/', $result); $this->assertRegExp('/WHERE\s+(?:\()?`TestModel6`\.`test_model5_id`\s+=\s+\({\$__cakeID__\$}\)(?:\))?/', $result); $this->assertRegExp('/\s+LIMIT 5,\s*5\s*$/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`test_model4_id`, `TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model5` AS `TestModel5`\s+WHERE\s+/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); $this->Model->hasMany['TestModel6'] = $backup; } /** * testGenerateAssociationQueryHasManyWithFields method * * @return void */ public function testGenerateAssociationQueryHasManyWithFields() { $this->Model = new TestModel5(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $queryData = array('fields' => array('`TestModel5`.`name`')); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp('/^SELECT\s+`TestModel6`\.`id`, `TestModel6`\.`test_model5_id`, `TestModel6`\.`name`, `TestModel6`\.`created`, `TestModel6`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model6` AS `TestModel6`\s+WHERE\s+/', $result); $this->assertRegExp('/WHERE\s+(?:\()?`TestModel6`\.`test_model5_id`\s+=\s+\({\$__cakeID__\$}\)(?:\))?/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel5`\.`name`, `TestModel5`\.`id`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model5` AS `TestModel5`\s+WHERE\s+/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $queryData = array('fields' => array('`TestModel5`.`id`, `TestModel5`.`name`')); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp('/^SELECT\s+`TestModel6`\.`id`, `TestModel6`\.`test_model5_id`, `TestModel6`\.`name`, `TestModel6`\.`created`, `TestModel6`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model6` AS `TestModel6`\s+WHERE\s+/', $result); $this->assertRegExp('/WHERE\s+(?:\()?`TestModel6`\.`test_model5_id`\s+=\s+\({\$__cakeID__\$}\)(?:\))?/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`name`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model5` AS `TestModel5`\s+WHERE\s+/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $queryData = array('fields' => array('`TestModel5`.`name`', '`TestModel5`.`created`')); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp('/^SELECT\s+`TestModel6`\.`id`, `TestModel6`\.`test_model5_id`, `TestModel6`\.`name`, `TestModel6`\.`created`, `TestModel6`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model6` AS `TestModel6`\s+WHERE\s+/', $result); $this->assertRegExp('/WHERE\s+(?:\()?`TestModel6`\.`test_model5_id`\s+=\s+\({\$__cakeID__\$}\)(?:\))?/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel5`\.`name`, `TestModel5`\.`created`, `TestModel5`\.`id`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model5` AS `TestModel5`\s+WHERE\s+/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); $this->Model->hasMany['TestModel6']['fields'] = array('name'); $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $queryData = array('fields' => array('`TestModel5`.`id`', '`TestModel5`.`name`')); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp('/^SELECT\s+`TestModel6`\.`name`, `TestModel6`\.`test_model5_id`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model6` AS `TestModel6`\s+WHERE\s+/', $result); $this->assertRegExp('/WHERE\s+(?:\()?`TestModel6`\.`test_model5_id`\s+=\s+\({\$__cakeID__\$}\)(?:\))?/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`name`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model5` AS `TestModel5`\s+WHERE\s+/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); unset($this->Model->hasMany['TestModel6']['fields']); $this->Model->hasMany['TestModel6']['fields'] = array('id', 'name'); $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $queryData = array('fields' => array('`TestModel5`.`id`', '`TestModel5`.`name`')); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp('/^SELECT\s+`TestModel6`\.`id`, `TestModel6`\.`name`, `TestModel6`\.`test_model5_id`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model6` AS `TestModel6`\s+WHERE\s+/', $result); $this->assertRegExp('/WHERE\s+(?:\()?`TestModel6`\.`test_model5_id`\s+=\s+\({\$__cakeID__\$}\)(?:\))?/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`name`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model5` AS `TestModel5`\s+WHERE\s+/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); unset($this->Model->hasMany['TestModel6']['fields']); $this->Model->hasMany['TestModel6']['fields'] = array('test_model5_id', 'name'); $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $queryData = array('fields' => array('`TestModel5`.`id`', '`TestModel5`.`name`')); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp('/^SELECT\s+`TestModel6`\.`test_model5_id`, `TestModel6`\.`name`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model6` AS `TestModel6`\s+WHERE\s+/', $result); $this->assertRegExp('/WHERE\s+(?:\()?`TestModel6`\.`test_model5_id`\s+=\s+\({\$__cakeID__\$}\)(?:\))?/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel5`\.`id`, `TestModel5`\.`name`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model5` AS `TestModel5`\s+WHERE\s+/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); unset($this->Model->hasMany['TestModel6']['fields']); } /** * test generateAssociationQuery with a hasMany and an aggregate function. * * @return void */ public function testGenerateAssociationQueryHasManyAndAggregateFunction() { $this->Model = new TestModel5(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'hasMany', 'model' => 'TestModel6'); $queryData = array('fields' => array('MIN(`TestModel5`.`test_model4_id`)')); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $this->Model->recursive = 0; $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+MIN\(`TestModel5`\.`test_model4_id`\)\s+FROM/', $result); } /** * testGenerateAssociationQueryHasAndBelongsToMany method * * @return void */ public function testGenerateAssociationQueryHasAndBelongsToMany() { $this->Model = new TestModel4(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'hasAndBelongsToMany', 'model' => 'TestModel7'); $queryData = array(); $params = $this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $assocTable = $this->Dbo->fullTableName($this->Model->TestModel4TestModel7, true, true); $this->assertRegExp('/^SELECT\s+`TestModel7`\.`id`, `TestModel7`\.`name`, `TestModel7`\.`created`, `TestModel7`\.`updated`, `TestModel4TestModel7`\.`test_model4_id`, `TestModel4TestModel7`\.`test_model7_id`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model7` AS `TestModel7`\s+JOIN\s+' . $assocTable . '/', $result); $this->assertRegExp('/\s+ON\s+\(`TestModel4TestModel7`\.`test_model4_id`\s+=\s+{\$__cakeID__\$}\s+AND/', $result); $this->assertRegExp('/\s+AND\s+`TestModel4TestModel7`\.`test_model7_id`\s+=\s+`TestModel7`\.`id`\)/', $result); $this->assertRegExp('/WHERE\s+(?:\()?1 = 1(?:\))?\s*$/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model4` AS `TestModel4`\s+WHERE/', $result); $this->assertRegExp('/\s+WHERE\s+(?:\()?1 = 1(?:\))?\s*$/', $result); } /** * testGenerateAssociationQueryHasAndBelongsToManyWithConditions method * * @return void */ public function testGenerateAssociationQueryHasAndBelongsToManyWithConditions() { $this->Model = new TestModel4(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $binding = array('type' => 'hasAndBelongsToMany', 'model' => 'TestModel7'); $queryData = array('conditions' => array('TestModel4.name !=' => 'mariano')); $params = $this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp('/^SELECT\s+`TestModel7`\.`id`, `TestModel7`\.`name`, `TestModel7`\.`created`, `TestModel7`\.`updated`, `TestModel4TestModel7`\.`test_model4_id`, `TestModel4TestModel7`\.`test_model7_id`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model7`\s+AS\s+`TestModel7`\s+JOIN\s+\S+`test_model4_test_model7`\s+AS\s+`TestModel4TestModel7`/', $result); $this->assertRegExp('/\s+ON\s+\(`TestModel4TestModel7`\.`test_model4_id`\s+=\s+{\$__cakeID__\$}/', $result); $this->assertRegExp('/\s+AND\s+`TestModel4TestModel7`\.`test_model7_id`\s+=\s+`TestModel7`\.`id`\)\s+WHERE\s+/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model4` AS `TestModel4`\s+WHERE\s+(?:\()?`TestModel4`.`name`\s+!=\s+\'mariano\'(?:\))?\s*$/', $result); } /** * testGenerateAssociationQueryHasAndBelongsToManyWithOffsetAndLimit method * * @return void */ public function testGenerateAssociationQueryHasAndBelongsToManyWithOffsetAndLimit() { $this->Model = new TestModel4(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $backup = $this->Model->hasAndBelongsToMany['TestModel7']; $this->Model->hasAndBelongsToMany['TestModel7']['offset'] = 2; $this->Model->hasAndBelongsToMany['TestModel7']['limit'] = 5; $binding = array('type' => 'hasAndBelongsToMany', 'model' => 'TestModel7'); $queryData = array(); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp('/^SELECT\s+`TestModel7`\.`id`, `TestModel7`\.`name`, `TestModel7`\.`created`, `TestModel7`\.`updated`, `TestModel4TestModel7`\.`test_model4_id`, `TestModel4TestModel7`\.`test_model7_id`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model7`\s+AS\s+`TestModel7`\s+JOIN\s+\S+`test_model4_test_model7`\s+AS\s+`TestModel4TestModel7`/', $result); $this->assertRegExp('/\s+ON\s+\(`TestModel4TestModel7`\.`test_model4_id`\s+=\s+{\$__cakeID__\$}\s+/', $result); $this->assertRegExp('/\s+AND\s+`TestModel4TestModel7`\.`test_model7_id`\s+=\s+`TestModel7`\.`id`\)\s+WHERE\s+/', $result); $this->assertRegExp('/\s+(?:\()?1\s+=\s+1(?:\))?\s*\s+LIMIT 2,\s*5\s*$/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model4` AS `TestModel4`\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); $this->Model->hasAndBelongsToMany['TestModel7'] = $backup; } /** * testGenerateAssociationQueryHasAndBelongsToManyWithPageAndLimit method * * @return void */ public function testGenerateAssociationQueryHasAndBelongsToManyWithPageAndLimit() { $this->Model = new TestModel4(); $this->Model->schema(); $this->_buildRelatedModels($this->Model); $backup = $this->Model->hasAndBelongsToMany['TestModel7']; $this->Model->hasAndBelongsToMany['TestModel7']['page'] = 2; $this->Model->hasAndBelongsToMany['TestModel7']['limit'] = 5; $binding = array('type' => 'hasAndBelongsToMany', 'model' => 'TestModel7'); $queryData = array(); $params = &$this->_prepareAssociationQuery($this->Model, $queryData, $binding); $result = $this->Dbo->generateAssociationQuery($this->Model, $params['linkModel'], $params['type'], $params['assoc'], $params['assocData'], $queryData, $params['external']); $this->assertRegExp('/^SELECT\s+`TestModel7`\.`id`, `TestModel7`\.`name`, `TestModel7`\.`created`, `TestModel7`\.`updated`, `TestModel4TestModel7`\.`test_model4_id`, `TestModel4TestModel7`\.`test_model7_id`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model7`\s+AS\s+`TestModel7`\s+JOIN\s+\S+`test_model4_test_model7`\s+AS\s+`TestModel4TestModel7`/', $result); $this->assertRegExp('/\s+ON\s+\(`TestModel4TestModel7`\.`test_model4_id`\s+=\s+{\$__cakeID__\$}/', $result); $this->assertRegExp('/\s+AND\s+`TestModel4TestModel7`\.`test_model7_id`\s+=\s+`TestModel7`\.`id`\)\s+WHERE\s+/', $result); $this->assertRegExp('/\s+(?:\()?1\s+=\s+1(?:\))?\s*\s+LIMIT 5,\s*5\s*$/', $result); $result = $this->Dbo->buildAssociationQuery($this->Model, $queryData); $this->assertRegExp('/^SELECT\s+`TestModel4`\.`id`, `TestModel4`\.`name`, `TestModel4`\.`created`, `TestModel4`\.`updated`\s+/', $result); $this->assertRegExp('/\s+FROM\s+\S+`test_model4` AS `TestModel4`\s+WHERE\s+(?:\()?1\s+=\s+1(?:\))?\s*$/', $result); $this->Model->hasAndBelongsToMany['TestModel7'] = $backup; } /** * testSelectDistict method * * @return void */ public function testSelectDistict() { $this->Model = new TestModel4(); $result = $this->Dbo->fields($this->Model, 'Vendor', "DISTINCT Vendor.id, Vendor.name"); $expected = array('DISTINCT `Vendor`.`id`', '`Vendor`.`name`'); $this->assertEquals($expected, $result); } /** * testStringConditionsParsing method * * @return void */ public function testStringConditionsParsing() { $result = $this->Dbo->conditions("ProjectBid.project_id = Project.id"); $expected = " WHERE `ProjectBid`.`project_id` = `Project`.`id`"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions("Candy.name LIKE 'a' AND HardCandy.name LIKE 'c'"); $expected = " WHERE `Candy`.`name` LIKE 'a' AND `HardCandy`.`name` LIKE 'c'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions("HardCandy.name LIKE 'a' AND Candy.name LIKE 'c'"); $expected = " WHERE `HardCandy`.`name` LIKE 'a' AND `Candy`.`name` LIKE 'c'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions("Post.title = '1.1'"); $expected = " WHERE `Post`.`title` = '1.1'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions("User.id != 0 AND User.user LIKE '%arr%'"); $expected = " WHERE `User`.`id` != 0 AND `User`.`user` LIKE '%arr%'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions("SUM(Post.comments_count) > 500"); $expected = " WHERE SUM(`Post`.`comments_count`) > 500"; $this->assertEquals($expected, $result); $date = date('Y-m-d H:i'); $result = $this->Dbo->conditions("(Post.created < '" . $date . "') GROUP BY YEAR(Post.created), MONTH(Post.created)"); $expected = " WHERE (`Post`.`created` < '" . $date . "') GROUP BY YEAR(`Post`.`created`), MONTH(`Post`.`created`)"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions("score BETWEEN 90.1 AND 95.7"); $expected = " WHERE score BETWEEN 90.1 AND 95.7"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('score' => array(2 => 1, 2, 10))); $expected = " WHERE `score` IN (1, 2, 10)"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions("Aro.rght = Aro.lft + 1.1"); $expected = " WHERE `Aro`.`rght` = `Aro`.`lft` + 1.1"; $this->assertEquals($expected, $result); $date = date('Y-m-d H:i:s'); $result = $this->Dbo->conditions("(Post.created < '" . $date . "') GROUP BY YEAR(Post.created), MONTH(Post.created)"); $expected = " WHERE (`Post`.`created` < '" . $date . "') GROUP BY YEAR(`Post`.`created`), MONTH(`Post`.`created`)"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions('Sportstaette.sportstaette LIKE "%ru%" AND Sportstaette.sportstaettenart_id = 2'); $expected = ' WHERE `Sportstaette`.`sportstaette` LIKE "%ru%" AND `Sportstaette`.`sportstaettenart_id` = 2'; $this->assertRegExp('/\s*WHERE\s+`Sportstaette`\.`sportstaette`\s+LIKE\s+"%ru%"\s+AND\s+`Sports/', $result); $this->assertEquals($expected, $result); $result = $this->Dbo->conditions('Sportstaette.sportstaettenart_id = 2 AND Sportstaette.sportstaette LIKE "%ru%"'); $expected = ' WHERE `Sportstaette`.`sportstaettenart_id` = 2 AND `Sportstaette`.`sportstaette` LIKE "%ru%"'; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions('SUM(Post.comments_count) > 500 AND NOT Post.title IS NULL AND NOT Post.extended_title IS NULL'); $expected = ' WHERE SUM(`Post`.`comments_count`) > 500 AND NOT `Post`.`title` IS NULL AND NOT `Post`.`extended_title` IS NULL'; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions('NOT Post.title IS NULL AND NOT Post.extended_title IS NULL AND SUM(Post.comments_count) > 500'); $expected = ' WHERE NOT `Post`.`title` IS NULL AND NOT `Post`.`extended_title` IS NULL AND SUM(`Post`.`comments_count`) > 500'; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions('NOT Post.extended_title IS NULL AND NOT Post.title IS NULL AND Post.title != "" AND SPOON(SUM(Post.comments_count) + 1.1) > 500'); $expected = ' WHERE NOT `Post`.`extended_title` IS NULL AND NOT `Post`.`title` IS NULL AND `Post`.`title` != "" AND SPOON(SUM(`Post`.`comments_count`) + 1.1) > 500'; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions('NOT Post.title_extended IS NULL AND NOT Post.title IS NULL AND Post.title_extended != Post.title'); $expected = ' WHERE NOT `Post`.`title_extended` IS NULL AND NOT `Post`.`title` IS NULL AND `Post`.`title_extended` != `Post`.`title`'; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions("Comment.id = 'a'"); $expected = " WHERE `Comment`.`id` = 'a'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions("lower(Article.title) LIKE 'a%'"); $expected = " WHERE lower(`Article`.`title`) LIKE 'a%'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions('((MATCH(Video.title) AGAINST(\'My Search*\' IN BOOLEAN MODE) * 2) + (MATCH(Video.description) AGAINST(\'My Search*\' IN BOOLEAN MODE) * 0.4) + (MATCH(Video.tags) AGAINST(\'My Search*\' IN BOOLEAN MODE) * 1.5))'); $expected = ' WHERE ((MATCH(`Video`.`title`) AGAINST(\'My Search*\' IN BOOLEAN MODE) * 2) + (MATCH(`Video`.`description`) AGAINST(\'My Search*\' IN BOOLEAN MODE) * 0.4) + (MATCH(`Video`.`tags`) AGAINST(\'My Search*\' IN BOOLEAN MODE) * 1.5))'; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions('DATEDIFF(NOW(),Article.published) < 1 && Article.live=1'); $expected = " WHERE DATEDIFF(NOW(),`Article`.`published`) < 1 && `Article`.`live`=1"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions('file = "index.html"'); $expected = ' WHERE file = "index.html"'; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions("file = 'index.html'"); $expected = " WHERE file = 'index.html'"; $this->assertEquals($expected, $result); $letter = $letter = 'd.a'; $conditions = array('Company.name like ' => $letter . '%'); $result = $this->Dbo->conditions($conditions); $expected = " WHERE `Company`.`name` like 'd.a%'"; $this->assertEquals($expected, $result); $conditions = array('Artist.name' => 'JUDY and MARY'); $result = $this->Dbo->conditions($conditions); $expected = " WHERE `Artist`.`name` = 'JUDY and MARY'"; $this->assertEquals($expected, $result); $conditions = array('Artist.name' => 'JUDY AND MARY'); $result = $this->Dbo->conditions($conditions); $expected = " WHERE `Artist`.`name` = 'JUDY AND MARY'"; $this->assertEquals($expected, $result); $conditions = array('Company.name similar to ' => 'a word'); $result = $this->Dbo->conditions($conditions); $expected = " WHERE `Company`.`name` similar to 'a word'"; $this->assertEquals($expected, $result); } /** * testQuotesInStringConditions method * * @return void */ public function testQuotesInStringConditions() { $result = $this->Dbo->conditions('Member.email = \'mariano@cricava.com\''); $expected = ' WHERE `Member`.`email` = \'mariano@cricava.com\''; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions('Member.email = "mariano@cricava.com"'); $expected = ' WHERE `Member`.`email` = "mariano@cricava.com"'; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions('Member.email = \'mariano@cricava.com\' AND Member.user LIKE \'mariano.iglesias%\''); $expected = ' WHERE `Member`.`email` = \'mariano@cricava.com\' AND `Member`.`user` LIKE \'mariano.iglesias%\''; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions('Member.email = "mariano@cricava.com" AND Member.user LIKE "mariano.iglesias%"'); $expected = ' WHERE `Member`.`email` = "mariano@cricava.com" AND `Member`.`user` LIKE "mariano.iglesias%"'; $this->assertEquals($expected, $result); } /** * test that - in conditions and field names works * * @return void */ public function testHypenInStringConditionsAndFieldNames() { $result = $this->Dbo->conditions('I18n__title_pt-br.content = "test"'); $this->assertEquals(' WHERE `I18n__title_pt-br`.`content` = "test"', $result); $result = $this->Dbo->conditions('Model.field=NOW()-3600'); $this->assertEquals(' WHERE `Model`.`field`=NOW()-3600', $result); $result = $this->Dbo->conditions('NOW() - Model.created < 7200'); $this->assertEquals(' WHERE NOW() - `Model`.`created` < 7200', $result); $result = $this->Dbo->conditions('NOW()-Model.created < 7200'); $this->assertEquals(' WHERE NOW()-`Model`.`created` < 7200', $result); } /** * testParenthesisInStringConditions method * * @return void */ public function testParenthesisInStringConditions() { $result = $this->Dbo->conditions('Member.name = \'(lu\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(lu\'$/', $result); $result = $this->Dbo->conditions('Member.name = \')lu\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\)lu\'$/', $result); $result = $this->Dbo->conditions('Member.name = \'va(lu\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'va\(lu\'$/', $result); $result = $this->Dbo->conditions('Member.name = \'va)lu\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'va\)lu\'$/', $result); $result = $this->Dbo->conditions('Member.name = \'va(lu)\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'va\(lu\)\'$/', $result); $result = $this->Dbo->conditions('Member.name = \'va(lu)e\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'va\(lu\)e\'$/', $result); $result = $this->Dbo->conditions('Member.name = \'(mariano)\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(mariano\)\'$/', $result); $result = $this->Dbo->conditions('Member.name = \'(mariano)iglesias\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(mariano\)iglesias\'$/', $result); $result = $this->Dbo->conditions('Member.name = \'(mariano) iglesias\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(mariano\) iglesias\'$/', $result); $result = $this->Dbo->conditions('Member.name = \'(mariano word) iglesias\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(mariano word\) iglesias\'$/', $result); $result = $this->Dbo->conditions('Member.name = \'(mariano.iglesias)\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(mariano.iglesias\)\'$/', $result); $result = $this->Dbo->conditions('Member.name = \'Mariano Iglesias (mariano.iglesias)\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'Mariano Iglesias \(mariano.iglesias\)\'$/', $result); $result = $this->Dbo->conditions('Member.name = \'Mariano Iglesias (mariano.iglesias) CakePHP\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'Mariano Iglesias \(mariano.iglesias\) CakePHP\'$/', $result); $result = $this->Dbo->conditions('Member.name = \'(mariano.iglesias) CakePHP\''); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(mariano.iglesias\) CakePHP\'$/', $result); } /** * testParenthesisInArrayConditions method * * @return void */ public function testParenthesisInArrayConditions() { $result = $this->Dbo->conditions(array('Member.name' => '(lu')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(lu\'$/', $result); $result = $this->Dbo->conditions(array('Member.name' => ')lu')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\)lu\'$/', $result); $result = $this->Dbo->conditions(array('Member.name' => 'va(lu')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'va\(lu\'$/', $result); $result = $this->Dbo->conditions(array('Member.name' => 'va)lu')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'va\)lu\'$/', $result); $result = $this->Dbo->conditions(array('Member.name' => 'va(lu)')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'va\(lu\)\'$/', $result); $result = $this->Dbo->conditions(array('Member.name' => 'va(lu)e')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'va\(lu\)e\'$/', $result); $result = $this->Dbo->conditions(array('Member.name' => '(mariano)')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(mariano\)\'$/', $result); $result = $this->Dbo->conditions(array('Member.name' => '(mariano)iglesias')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(mariano\)iglesias\'$/', $result); $result = $this->Dbo->conditions(array('Member.name' => '(mariano) iglesias')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(mariano\) iglesias\'$/', $result); $result = $this->Dbo->conditions(array('Member.name' => '(mariano word) iglesias')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(mariano word\) iglesias\'$/', $result); $result = $this->Dbo->conditions(array('Member.name' => '(mariano.iglesias)')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(mariano.iglesias\)\'$/', $result); $result = $this->Dbo->conditions(array('Member.name' => 'Mariano Iglesias (mariano.iglesias)')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'Mariano Iglesias \(mariano.iglesias\)\'$/', $result); $result = $this->Dbo->conditions(array('Member.name' => 'Mariano Iglesias (mariano.iglesias) CakePHP')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'Mariano Iglesias \(mariano.iglesias\) CakePHP\'$/', $result); $result = $this->Dbo->conditions(array('Member.name' => '(mariano.iglesias) CakePHP')); $this->assertRegExp('/^\s+WHERE\s+`Member`.`name`\s+=\s+\'\(mariano.iglesias\) CakePHP\'$/', $result); } /** * testArrayConditionsParsing method * * @return void */ public function testArrayConditionsParsing() { $this->loadFixtures('Post', 'Author'); $result = $this->Dbo->conditions(array('Stereo.type' => 'in dash speakers')); $this->assertRegExp("/^\s+WHERE\s+`Stereo`.`type`\s+=\s+'in dash speakers'/", $result); $result = $this->Dbo->conditions(array('Candy.name LIKE' => 'a', 'HardCandy.name LIKE' => 'c')); $this->assertRegExp("/^\s+WHERE\s+`Candy`.`name` LIKE\s+'a'\s+AND\s+`HardCandy`.`name`\s+LIKE\s+'c'/", $result); $result = $this->Dbo->conditions(array('HardCandy.name LIKE' => 'a', 'Candy.name LIKE' => 'c')); $expected = " WHERE `HardCandy`.`name` LIKE 'a' AND `Candy`.`name` LIKE 'c'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('HardCandy.name LIKE' => 'a%', 'Candy.name LIKE' => '%c%')); $expected = " WHERE `HardCandy`.`name` LIKE 'a%' AND `Candy`.`name` LIKE '%c%'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('HardCandy.name LIKE' => 'to be or%', 'Candy.name LIKE' => '%not to be%')); $expected = " WHERE `HardCandy`.`name` LIKE 'to be or%' AND `Candy`.`name` LIKE '%not to be%'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array( "Person.name || ' ' || Person.surname ILIKE" => '%mark%' )); $expected = " WHERE `Person`.`name` || ' ' || `Person`.`surname` ILIKE '%mark%'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('score BETWEEN ? AND ?' => array(90.1, 95.7))); $expected = " WHERE `score` BETWEEN 90.1 AND 95.7"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('Post.title' => 1.1)); $expected = " WHERE `Post`.`title` = 1.1"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('Post.title' => 1.1), true, true, new Post()); $expected = " WHERE `Post`.`title` = '1.1'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('SUM(Post.comments_count) >' => '500')); $expected = " WHERE SUM(`Post`.`comments_count`) > '500'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('MAX(Post.rating) >' => '50')); $expected = " WHERE MAX(`Post`.`rating`) > '50'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('lower(Article.title)' => 'secrets')); $expected = " WHERE lower(`Article`.`title`) = 'secrets'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('title LIKE' => '%hello')); $expected = " WHERE `title` LIKE '%hello'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('Post.name' => 'mad(g)ik')); $expected = " WHERE `Post`.`name` = 'mad(g)ik'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('score' => array(1, 2, 10))); $expected = " WHERE `score` IN (1, 2, 10)"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('score' => array())); $expected = " WHERE `score` IS NULL"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('score !=' => array())); $expected = " WHERE `score` IS NOT NULL"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('score !=' => '20')); $expected = " WHERE `score` != '20'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('score >' => '20')); $expected = " WHERE `score` > '20'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('client_id >' => '20'), true, true, new TestModel()); $expected = " WHERE `client_id` > 20"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('OR' => array( array('User.user' => 'mariano'), array('User.user' => 'nate') ))); $expected = " WHERE ((`User`.`user` = 'mariano') OR (`User`.`user` = 'nate'))"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('User.user RLIKE' => 'mariano|nate')); $expected = " WHERE `User`.`user` RLIKE 'mariano|nate'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('or' => array( 'score BETWEEN ? AND ?' => array('4', '5'), 'rating >' => '20' ))); $expected = " WHERE ((`score` BETWEEN '4' AND '5') OR (`rating` > '20'))"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('or' => array( 'score BETWEEN ? AND ?' => array('4', '5'), array('score >' => '20') ))); $expected = " WHERE ((`score` BETWEEN '4' AND '5') OR (`score` > '20'))"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('and' => array( 'score BETWEEN ? AND ?' => array('4', '5'), array('score >' => '20') ))); $expected = " WHERE ((`score` BETWEEN '4' AND '5') AND (`score` > '20'))"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array( 'published' => 1, 'or' => array('score >' => '2', array('score >' => '20')) )); $expected = " WHERE `published` = 1 AND ((`score` > '2') OR (`score` > '20'))"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array(array('Project.removed' => false))); $expected = " WHERE `Project`.`removed` = '0'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array(array('Project.removed' => true))); $expected = " WHERE `Project`.`removed` = '1'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array(array('Project.removed' => null))); $expected = " WHERE `Project`.`removed` IS NULL"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array(array('Project.removed !=' => null))); $expected = " WHERE `Project`.`removed` IS NOT NULL"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('(Usergroup.permissions) & 4' => 4)); $expected = " WHERE (`Usergroup`.`permissions`) & 4 = 4"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('((Usergroup.permissions) & 4)' => 4)); $expected = " WHERE ((`Usergroup`.`permissions`) & 4) = 4"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('Post.modified >=' => 'DATE_SUB(NOW(), INTERVAL 7 DAY)')); $expected = " WHERE `Post`.`modified` >= 'DATE_SUB(NOW(), INTERVAL 7 DAY)'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('Post.modified >= DATE_SUB(NOW(), INTERVAL 7 DAY)')); $expected = " WHERE `Post`.`modified` >= DATE_SUB(NOW(), INTERVAL 7 DAY)"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array( 'NOT' => array('Course.id' => null, 'Course.vet' => 'N', 'level_of_education_id' => array(912, 999)), 'Enrollment.yearcompleted >' => '0') ); $this->assertRegExp('/^\s*WHERE\s+\(NOT\s+\(`Course`\.`id` IS NULL\)\s+AND NOT\s+\(`Course`\.`vet`\s+=\s+\'N\'\)\s+AND NOT\s+\(`level_of_education_id` IN \(912, 999\)\)\)\s+AND\s+`Enrollment`\.`yearcompleted`\s+>\s+\'0\'\s*$/', $result); $result = $this->Dbo->conditions(array('id <>' => '8')); $this->assertRegExp('/^\s*WHERE\s+`id`\s+<>\s+\'8\'\s*$/', $result); $result = $this->Dbo->conditions(array('TestModel.field =' => 'gribe$@()lu')); $expected = " WHERE `TestModel`.`field` = 'gribe$@()lu'"; $this->assertEquals($expected, $result); $conditions['NOT'] = array('Listing.expiration BETWEEN ? AND ?' => array("1", "100")); $conditions[0]['OR'] = array( "Listing.title LIKE" => "%term%", "Listing.description LIKE" => "%term%" ); $conditions[1]['OR'] = array( "Listing.title LIKE" => "%term_2%", "Listing.description LIKE" => "%term_2%" ); $result = $this->Dbo->conditions($conditions); $expected = " WHERE NOT (`Listing`.`expiration` BETWEEN '1' AND '100') AND" . " ((`Listing`.`title` LIKE '%term%') OR (`Listing`.`description` LIKE '%term%')) AND" . " ((`Listing`.`title` LIKE '%term_2%') OR (`Listing`.`description` LIKE '%term_2%'))"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('MD5(CONCAT(Reg.email,Reg.id))' => 'blah')); $expected = " WHERE MD5(CONCAT(`Reg`.`email`,`Reg`.`id`)) = 'blah'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array( 'MD5(CONCAT(Reg.email,Reg.id))' => array('blah', 'blahblah') )); $expected = " WHERE MD5(CONCAT(`Reg`.`email`,`Reg`.`id`)) IN ('blah', 'blahblah')"; $this->assertEquals($expected, $result); $conditions = array('id' => array(2, 5, 6, 9, 12, 45, 78, 43, 76)); $result = $this->Dbo->conditions($conditions); $expected = " WHERE `id` IN (2, 5, 6, 9, 12, 45, 78, 43, 76)"; $this->assertEquals($expected, $result); $conditions = array('`Correction`.`source` collate utf8_bin' => array('kiwi', 'pear')); $result = $this->Dbo->conditions($conditions); $expected = " WHERE `Correction`.`source` collate utf8_bin IN ('kiwi', 'pear')"; $this->assertEquals($expected, $result); $conditions = array('title' => 'user(s)'); $result = $this->Dbo->conditions($conditions); $expected = " WHERE `title` = 'user(s)'"; $this->assertEquals($expected, $result); $conditions = array('title' => 'user(s) data'); $result = $this->Dbo->conditions($conditions); $expected = " WHERE `title` = 'user(s) data'"; $this->assertEquals($expected, $result); $conditions = array('title' => 'user(s,arg) data'); $result = $this->Dbo->conditions($conditions); $expected = " WHERE `title` = 'user(s,arg) data'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array("Book.book_name" => 'Java(TM)')); $expected = " WHERE `Book`.`book_name` = 'Java(TM)'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array("Book.book_name" => 'Java(TM) ')); $expected = " WHERE `Book`.`book_name` = 'Java(TM) '"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array("Book.id" => 0)); $expected = " WHERE `Book`.`id` = 0"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array("Book.id" => null)); $expected = " WHERE `Book`.`id` IS NULL"; $this->assertEquals($expected, $result); $conditions = array('MysqlModel.id' => ''); $result = $this->Dbo->conditions($conditions, true, true, $this->model); $expected = " WHERE `MysqlModel`.`id` IS NULL"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('Listing.beds >=' => 0)); $expected = " WHERE `Listing`.`beds` >= 0"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array( 'ASCII(SUBSTRING(keyword, 1, 1)) BETWEEN ? AND ?' => array(65, 90) )); $expected = ' WHERE ASCII(SUBSTRING(keyword, 1, 1)) BETWEEN 65 AND 90'; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('or' => array( '? BETWEEN Model.field1 AND Model.field2' => '2009-03-04' ))); $expected = " WHERE '2009-03-04' BETWEEN Model.field1 AND Model.field2"; $this->assertEquals($expected, $result); } /** * test conditions() with replacements. * * @return void */ public function testConditionsWithReplacements() { $result = $this->Dbo->conditions(array( 'score BETWEEN :0 AND :1' => array(90.1, 95.7) )); $expected = " WHERE `score` BETWEEN 90.1 AND 95.7"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array( 'score BETWEEN ? AND ?' => array(90.1, 95.7) )); $expected = " WHERE `score` BETWEEN 90.1 AND 95.7"; $this->assertEquals($expected, $result); } /** * Test that array conditions with only one element work. * * @return void */ public function testArrayConditionsOneElement() { $conditions = array('id' => array(1)); $result = $this->Dbo->conditions($conditions); $expected = " WHERE id = (1)"; $this->assertEquals($expected, $result); $conditions = array('id NOT' => array(1)); $result = $this->Dbo->conditions($conditions); $expected = " WHERE NOT (id = (1))"; $this->assertEquals($expected, $result); } /** * testArrayConditionsParsingComplexKeys method * * @return void */ public function testArrayConditionsParsingComplexKeys() { $result = $this->Dbo->conditions(array( 'CAST(Book.created AS DATE)' => '2008-08-02' )); $expected = " WHERE CAST(`Book`.`created` AS DATE) = '2008-08-02'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array( 'CAST(Book.created AS DATE) <=' => '2008-08-02' )); $expected = " WHERE CAST(`Book`.`created` AS DATE) <= '2008-08-02'"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array( '(Stats.clicks * 100) / Stats.views >' => 50 )); $expected = " WHERE (`Stats`.`clicks` * 100) / `Stats`.`views` > 50"; $this->assertEquals($expected, $result); } /** * testMixedConditionsParsing method * * @return void */ public function testMixedConditionsParsing() { $conditions[] = 'User.first_name = \'Firstname\''; $conditions[] = array('User.last_name' => 'Lastname'); $result = $this->Dbo->conditions($conditions); $expected = " WHERE `User`.`first_name` = 'Firstname' AND `User`.`last_name` = 'Lastname'"; $this->assertEquals($expected, $result); $conditions = array( 'Thread.project_id' => 5, 'Thread.buyer_id' => 14, '1=1 GROUP BY Thread.project_id' ); $result = $this->Dbo->conditions($conditions); $this->assertRegExp('/^\s*WHERE\s+`Thread`.`project_id`\s*=\s*5\s+AND\s+`Thread`.`buyer_id`\s*=\s*14\s+AND\s+1\s*=\s*1\s+GROUP BY `Thread`.`project_id`$/', $result); } /** * testConditionsOptionalArguments method * * @return void */ public function testConditionsOptionalArguments() { $result = $this->Dbo->conditions(array('Member.name' => 'Mariano'), true, false); $this->assertRegExp('/^\s*`Member`.`name`\s*=\s*\'Mariano\'\s*$/', $result); $result = $this->Dbo->conditions(array(), true, false); $this->assertRegExp('/^\s*1\s*=\s*1\s*$/', $result); } /** * testConditionsWithModel * * @return void */ public function testConditionsWithModel() { $this->Model = new Article2(); $result = $this->Dbo->conditions(array('Article2.viewed >=' => 0), true, true, $this->Model); $expected = " WHERE `Article2`.`viewed` >= 0"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('Article2.viewed >=' => '0'), true, true, $this->Model); $expected = " WHERE `Article2`.`viewed` >= 0"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('Article2.viewed >=' => '1'), true, true, $this->Model); $expected = " WHERE `Article2`.`viewed` >= 1"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('Article2.rate_sum BETWEEN ? AND ?' => array(0, 10)), true, true, $this->Model); $expected = " WHERE `Article2`.`rate_sum` BETWEEN 0 AND 10"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('Article2.rate_sum BETWEEN ? AND ?' => array('0', '10')), true, true, $this->Model); $expected = " WHERE `Article2`.`rate_sum` BETWEEN 0 AND 10"; $this->assertEquals($expected, $result); $result = $this->Dbo->conditions(array('Article2.rate_sum BETWEEN ? AND ?' => array('1', '10')), true, true, $this->Model); $expected = " WHERE `Article2`.`rate_sum` BETWEEN 1 AND 10"; $this->assertEquals($expected, $result); } /** * testFieldParsing method * * @return void */ public function testFieldParsing() { $this->Model = new TestModel(); $result = $this->Dbo->fields($this->Model, 'Vendor', "Vendor.id, COUNT(Model.vendor_id) AS `Vendor`.`count`"); $expected = array('`Vendor`.`id`', 'COUNT(`Model`.`vendor_id`) AS `Vendor`.`count`'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, 'Vendor', "`Vendor`.`id`, COUNT(`Model`.`vendor_id`) AS `Vendor`.`count`"); $expected = array('`Vendor`.`id`', 'COUNT(`Model`.`vendor_id`) AS `Vendor`.`count`'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, 'Post', "CONCAT(REPEAT(' ', COUNT(Parent.name) - 1), Node.name) AS name, Node.created"); $expected = array("CONCAT(REPEAT(' ', COUNT(`Parent`.`name`) - 1), Node.name) AS name", "`Node`.`created`"); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, null, 'round( (3.55441 * fooField), 3 ) AS test'); $this->assertEquals(array('round( (3.55441 * fooField), 3 ) AS test'), $result); $result = $this->Dbo->fields($this->Model, null, 'ROUND(`Rating`.`rate_total` / `Rating`.`rate_count`,2) AS rating'); $this->assertEquals(array('ROUND(`Rating`.`rate_total` / `Rating`.`rate_count`,2) AS rating'), $result); $result = $this->Dbo->fields($this->Model, null, 'ROUND(Rating.rate_total / Rating.rate_count,2) AS rating'); $this->assertEquals(array('ROUND(Rating.rate_total / Rating.rate_count,2) AS rating'), $result); $result = $this->Dbo->fields($this->Model, 'Post', "Node.created, CONCAT(REPEAT(' ', COUNT(Parent.name) - 1), Node.name) AS name"); $expected = array("`Node`.`created`", "CONCAT(REPEAT(' ', COUNT(`Parent`.`name`) - 1), Node.name) AS name"); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, 'Post', "2.2,COUNT(*), SUM(Something.else) as sum, Node.created, CONCAT(REPEAT(' ', COUNT(Parent.name) - 1), Node.name) AS name,Post.title,Post.1,1.1"); $expected = array( '2.2', 'COUNT(*)', 'SUM(`Something`.`else`) as sum', '`Node`.`created`', "CONCAT(REPEAT(' ', COUNT(`Parent`.`name`) - 1), Node.name) AS name", '`Post`.`title`', '`Post`.`1`', '1.1' ); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, null, "(`Provider`.`star_total` / `Provider`.`total_ratings`) as `rating`"); $expected = array("(`Provider`.`star_total` / `Provider`.`total_ratings`) as `rating`"); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, 'Post'); $expected = array( '`Post`.`id`', '`Post`.`client_id`', '`Post`.`name`', '`Post`.`login`', '`Post`.`passwd`', '`Post`.`addr_1`', '`Post`.`addr_2`', '`Post`.`zip_code`', '`Post`.`city`', '`Post`.`country`', '`Post`.`phone`', '`Post`.`fax`', '`Post`.`url`', '`Post`.`email`', '`Post`.`comments`', '`Post`.`last_login`', '`Post`.`created`', '`Post`.`updated`' ); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, 'Other'); $expected = array( '`Other`.`id`', '`Other`.`client_id`', '`Other`.`name`', '`Other`.`login`', '`Other`.`passwd`', '`Other`.`addr_1`', '`Other`.`addr_2`', '`Other`.`zip_code`', '`Other`.`city`', '`Other`.`country`', '`Other`.`phone`', '`Other`.`fax`', '`Other`.`url`', '`Other`.`email`', '`Other`.`comments`', '`Other`.`last_login`', '`Other`.`created`', '`Other`.`updated`' ); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, null, array(), false); $expected = array('id', 'client_id', 'name', 'login', 'passwd', 'addr_1', 'addr_2', 'zip_code', 'city', 'country', 'phone', 'fax', 'url', 'email', 'comments', 'last_login', 'created', 'updated'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, null, 'COUNT(*)'); $expected = array('COUNT(*)'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, null, 'SUM(Thread.unread_buyer) AS ' . $this->Dbo->name('sum_unread_buyer')); $expected = array('SUM(`Thread`.`unread_buyer`) AS `sum_unread_buyer`'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, null, 'name, count(*)'); $expected = array('`TestModel`.`name`', 'count(*)'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, null, 'count(*), name'); $expected = array('count(*)', '`TestModel`.`name`'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields( $this->Model, null, 'field1, field2, field3, count(*), name' ); $expected = array( '`TestModel`.`field1`', '`TestModel`.`field2`', '`TestModel`.`field3`', 'count(*)', '`TestModel`.`name`' ); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, null, array('dayofyear(now())')); $expected = array('dayofyear(now())'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, null, array('MAX(Model.field) As Max')); $expected = array('MAX(`Model`.`field`) As Max'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, null, array('Model.field AS AnotherName')); $expected = array('`Model`.`field` AS `AnotherName`'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, null, array('field AS AnotherName')); $expected = array('`field` AS `AnotherName`'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, null, array( 'TestModel.field AS AnotherName' )); $expected = array('`TestModel`.`field` AS `AnotherName`'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->Model, 'Foo', array( 'id', 'title', '(user_count + discussion_count + post_count) AS score' )); $expected = array( '`Foo`.`id`', '`Foo`.`title`', '(user_count + discussion_count + post_count) AS score' ); $this->assertEquals($expected, $result); } /** * test that fields() will accept objects made from DboSource::expression * * @return void */ public function testFieldsWithExpression() { $this->Model = new TestModel; $expression = $this->Dbo->expression("CASE Sample.id WHEN 1 THEN 'Id One' ELSE 'Other Id' END AS case_col"); $result = $this->Dbo->fields($this->Model, null, array("id", $expression)); $expected = array( '`TestModel`.`id`', "CASE Sample.id WHEN 1 THEN 'Id One' ELSE 'Other Id' END AS case_col" ); $this->assertEquals($expected, $result); } /** * testRenderStatement method * * @return void */ public function testRenderStatement() { $result = $this->Dbo->renderStatement('select', array( 'fields' => 'id', 'table' => 'table', 'conditions' => 'WHERE 1=1', 'alias' => '', 'joins' => '', 'order' => '', 'limit' => '', 'group' => '' )); $this->assertRegExp('/^\s*SELECT\s+id\s+FROM\s+table\s+WHERE\s+1=1\s*$/', $result); $result = $this->Dbo->renderStatement('update', array('fields' => 'value=2', 'table' => 'table', 'conditions' => 'WHERE 1=1', 'alias' => '')); $this->assertRegExp('/^\s*UPDATE\s+table\s+SET\s+value=2\s+WHERE\s+1=1\s*$/', $result); $result = $this->Dbo->renderStatement('update', array('fields' => 'value=2', 'table' => 'table', 'conditions' => 'WHERE 1=1', 'alias' => 'alias', 'joins' => '')); $this->assertRegExp('/^\s*UPDATE\s+table\s+AS\s+alias\s+SET\s+value=2\s+WHERE\s+1=1\s*$/', $result); $result = $this->Dbo->renderStatement('delete', array('fields' => 'value=2', 'table' => 'table', 'conditions' => 'WHERE 1=1', 'alias' => '')); $this->assertRegExp('/^\s*DELETE\s+FROM\s+table\s+WHERE\s+1=1\s*$/', $result); $result = $this->Dbo->renderStatement('delete', array('fields' => 'value=2', 'table' => 'table', 'conditions' => 'WHERE 1=1', 'alias' => 'alias', 'joins' => '')); $this->assertRegExp('/^\s*DELETE\s+alias\s+FROM\s+table\s+AS\s+alias\s+WHERE\s+1=1\s*$/', $result); } /** * testSchema method * * @return void */ public function testSchema() { $Schema = new CakeSchema(); $Schema->tables = array('table' => array(), 'anotherTable' => array()); $result = $this->Dbo->dropSchema($Schema, 'non_existing'); $this->assertTrue(empty($result)); $result = $this->Dbo->dropSchema($Schema, 'table'); $this->assertRegExp('/^\s*DROP TABLE IF EXISTS\s+' . $this->Dbo->fullTableName('table') . ';\s*$/s', $result); } /** * testDropSchemaNoSchema method * * @expectedException PHPUnit_Framework_Error * @throws PHPUnit_Framework_Error * @return void */ public function testDropSchemaNoSchema() { try { $this->Dbo->dropSchema(null); } catch (Throwable $t) { throw new PHPUnit_Framework_Error($t); } } /** * testOrderParsing method * * @return void */ public function testOrderParsing() { $result = $this->Dbo->order("ADDTIME(Event.time_begin, '-06:00:00') ASC"); $expected = " ORDER BY ADDTIME(`Event`.`time_begin`, '-06:00:00') ASC"; $this->assertEquals($expected, $result); $result = $this->Dbo->order("title, id"); $this->assertRegExp('/^\s*ORDER BY\s+`title`\s+ASC,\s+`id`\s+ASC\s*$/', $result); $result = $this->Dbo->order("title desc, id desc"); $this->assertRegExp('/^\s*ORDER BY\s+`title`\s+desc,\s+`id`\s+desc\s*$/', $result); $result = $this->Dbo->order(array("title desc, id desc")); $this->assertRegExp('/^\s*ORDER BY\s+`title`\s+desc,\s+`id`\s+desc\s*$/', $result); $result = $this->Dbo->order(array("title", "id")); $this->assertRegExp('/^\s*ORDER BY\s+`title`\s+ASC,\s+`id`\s+ASC\s*$/', $result); $result = $this->Dbo->order(array(array('title'), array('id'))); $this->assertRegExp('/^\s*ORDER BY\s+`title`\s+ASC,\s+`id`\s+ASC\s*$/', $result); $result = $this->Dbo->order(array("Post.title" => 'asc', "Post.id" => 'desc')); $this->assertRegExp('/^\s*ORDER BY\s+`Post`.`title`\s+asc,\s+`Post`.`id`\s+desc\s*$/', $result); $result = $this->Dbo->order(array(array("Post.title" => 'asc', "Post.id" => 'desc'))); $this->assertRegExp('/^\s*ORDER BY\s+`Post`.`title`\s+asc,\s+`Post`.`id`\s+desc\s*$/', $result); $result = $this->Dbo->order(array("title")); $this->assertRegExp('/^\s*ORDER BY\s+`title`\s+ASC\s*$/', $result); $result = $this->Dbo->order(array(array("title"))); $this->assertRegExp('/^\s*ORDER BY\s+`title`\s+ASC\s*$/', $result); $result = $this->Dbo->order("Dealer.id = 7 desc, Dealer.id = 3 desc, Dealer.title asc"); $expected = " ORDER BY `Dealer`.`id` = 7 desc, `Dealer`.`id` = 3 desc, `Dealer`.`title` asc"; $this->assertEquals($expected, $result); $result = $this->Dbo->order(array("Page.name" => "='test' DESC")); $this->assertRegExp("/^\s*ORDER BY\s+`Page`\.`name`\s*='test'\s+DESC\s*$/", $result); $result = $this->Dbo->order("Page.name = 'view' DESC"); $this->assertRegExp("/^\s*ORDER BY\s+`Page`\.`name`\s*=\s*'view'\s+DESC\s*$/", $result); $result = $this->Dbo->order("(Post.views)"); $this->assertRegExp("/^\s*ORDER BY\s+\(`Post`\.`views`\)\s+ASC\s*$/", $result); $result = $this->Dbo->order("(Post.views)*Post.views"); $this->assertRegExp("/^\s*ORDER BY\s+\(`Post`\.`views`\)\*`Post`\.`views`\s+ASC\s*$/", $result); $result = $this->Dbo->order("(Post.views) * Post.views"); $this->assertRegExp("/^\s*ORDER BY\s+\(`Post`\.`views`\) \* `Post`\.`views`\s+ASC\s*$/", $result); $result = $this->Dbo->order("(Model.field1 + Model.field2) * Model.field3"); $this->assertRegExp("/^\s*ORDER BY\s+\(`Model`\.`field1` \+ `Model`\.`field2`\) \* `Model`\.`field3`\s+ASC\s*$/", $result); $result = $this->Dbo->order("Model.name+0 ASC"); $this->assertRegExp("/^\s*ORDER BY\s+`Model`\.`name`\+0\s+ASC\s*$/", $result); $result = $this->Dbo->order("Anuncio.destaque & 2 DESC"); $expected = ' ORDER BY `Anuncio`.`destaque` & 2 DESC'; $this->assertEquals($expected, $result); $result = $this->Dbo->order("3963.191 * id"); $expected = ' ORDER BY 3963.191 * id ASC'; $this->assertEquals($expected, $result); $result = $this->Dbo->order(array('Property.sale_price IS NULL')); $expected = ' ORDER BY `Property`.`sale_price` IS NULL ASC'; $this->assertEquals($expected, $result); } /** * testComplexSortExpression method * * @return void */ public function testComplexSortExpression() { $result = $this->Dbo->order(array('(Model.field > 100) DESC', 'Model.field ASC')); $this->assertRegExp("/^\s*ORDER BY\s+\(`Model`\.`field`\s+>\s+100\)\s+DESC,\s+`Model`\.`field`\s+ASC\s*$/", $result); } /** * testCalculations method * * @return void */ public function testCalculations() { $this->Model = new TestModel(); $result = $this->Dbo->calculate($this->Model, 'count'); $this->assertEquals('COUNT(*) AS `count`', $result); $result = $this->Dbo->calculate($this->Model, 'count', array('id')); $this->assertEquals('COUNT(`id`) AS `count`', $result); $result = $this->Dbo->calculate( $this->Model, 'count', array($this->Dbo->expression('DISTINCT id')) ); $this->assertEquals('COUNT(DISTINCT id) AS `count`', $result); $result = $this->Dbo->calculate($this->Model, 'count', array('id', 'id_count')); $this->assertEquals('COUNT(`id`) AS `id_count`', $result); $result = $this->Dbo->calculate($this->Model, 'count', array('Model.id', 'id_count')); $this->assertEquals('COUNT(`Model`.`id`) AS `id_count`', $result); $result = $this->Dbo->calculate($this->Model, 'max', array('id')); $this->assertEquals('MAX(`id`) AS `id`', $result); $result = $this->Dbo->calculate($this->Model, 'max', array('Model.id', 'id')); $this->assertEquals('MAX(`Model`.`id`) AS `id`', $result); $result = $this->Dbo->calculate($this->Model, 'max', array('`Model`.`id`', 'id')); $this->assertEquals('MAX(`Model`.`id`) AS `id`', $result); $result = $this->Dbo->calculate($this->Model, 'min', array('`Model`.`id`', 'id')); $this->assertEquals('MIN(`Model`.`id`) AS `id`', $result); $result = $this->Dbo->calculate($this->Model, 'min', 'left'); $this->assertEquals('MIN(`left`) AS `left`', $result); } /** * testLength method * * @return void */ public function testLength() { $result = $this->Dbo->length('varchar(255)'); $expected = 255; $this->assertSame($expected, $result); $result = $this->Dbo->length('int(11)'); $expected = 11; $this->assertSame($expected, $result); $result = $this->Dbo->length('float(5,3)'); $expected = '5,3'; $this->assertSame($expected, $result); $result = $this->Dbo->length('decimal(5,2)'); $expected = '5,2'; $this->assertSame($expected, $result); $result = $this->Dbo->length("enum('test','me','now')"); $expected = 4; $this->assertSame($expected, $result); $result = $this->Dbo->length("set('a','b','cd')"); $expected = 2; $this->assertSame($expected, $result); $result = $this->Dbo->length(false); $this->assertNull($result); $result = $this->Dbo->length('datetime'); $expected = null; $this->assertSame($expected, $result); $result = $this->Dbo->length('text'); $expected = null; $this->assertSame($expected, $result); } /** * testBuildIndex method * * @return void */ public function testBuildIndex() { $data = array( 'PRIMARY' => array('column' => 'id') ); $result = $this->Dbo->buildIndex($data); $expected = array('PRIMARY KEY (`id`)'); $this->assertSame($expected, $result); $data = array( 'MyIndex' => array('column' => 'id', 'unique' => true) ); $result = $this->Dbo->buildIndex($data); $expected = array('UNIQUE KEY `MyIndex` (`id`)'); $this->assertEquals($expected, $result); $data = array( 'MyIndex' => array('column' => array('id', 'name'), 'unique' => true) ); $result = $this->Dbo->buildIndex($data); $expected = array('UNIQUE KEY `MyIndex` (`id`, `name`)'); $this->assertEquals($expected, $result); $data = array( 'MyFtIndex' => array('column' => array('name', 'description'), 'type' => 'fulltext') ); $result = $this->Dbo->buildIndex($data); $expected = array('FULLTEXT KEY `MyFtIndex` (`name`, `description`)'); $this->assertEquals($expected, $result); $data = array( 'MyTextIndex' => array('column' => 'text_field', 'length' => array('text_field' => 20)) ); $result = $this->Dbo->buildIndex($data); $expected = array('KEY `MyTextIndex` (`text_field`(20))'); $this->assertEquals($expected, $result); $data = array( 'MyMultiTextIndex' => array('column' => array('text_field1', 'text_field2'), 'length' => array('text_field1' => 20, 'text_field2' => 20)) ); $result = $this->Dbo->buildIndex($data); $expected = array('KEY `MyMultiTextIndex` (`text_field1`(20), `text_field2`(20))'); $this->assertEquals($expected, $result); } /** * testBuildColumn method * * @return void */ public function testBuildColumn2() { $data = array( 'name' => 'testName', 'type' => 'string', 'length' => 255, 'default', 'null' => true, 'key' ); $result = $this->Dbo->buildColumn($data); $expected = '`testName` varchar(255) DEFAULT NULL'; $this->assertEquals($expected, $result); $data = array( 'name' => 'int_field', 'type' => 'integer', 'default' => '', 'null' => false, ); $restore = $this->Dbo->columns; $this->Dbo->columns = array('integer' => array('name' => 'int', 'limit' => '11', 'formatter' => 'intval'), ); $result = $this->Dbo->buildColumn($data); $expected = '`int_field` int(11) NOT NULL'; $this->assertEquals($expected, $result); $this->Dbo->fieldParameters['param'] = array( 'value' => 'COLLATE', 'quote' => false, 'join' => ' ', 'column' => 'Collate', 'position' => 'beforeDefault', 'options' => array('GOOD', 'OK') ); $data = array( 'name' => 'int_field', 'type' => 'integer', 'default' => '', 'null' => false, 'param' => 'BAD' ); $result = $this->Dbo->buildColumn($data); $expected = '`int_field` int(11) NOT NULL'; $this->assertEquals($expected, $result); $data = array( 'name' => 'int_field', 'type' => 'integer', 'default' => '', 'null' => false, 'param' => 'GOOD' ); $result = $this->Dbo->buildColumn($data); $expected = '`int_field` int(11) COLLATE GOOD NOT NULL'; $this->assertEquals($expected, $result); $this->Dbo->columns = $restore; $data = array( 'name' => 'created', 'type' => 'timestamp', 'default' => 'current_timestamp', 'null' => false, ); $result = $this->Dbo->buildColumn($data); $expected = '`created` timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL'; $this->assertEquals($expected, $result); $data = array( 'name' => 'created', 'type' => 'timestamp', 'default' => 'CURRENT_TIMESTAMP', 'null' => true, ); $result = $this->Dbo->buildColumn($data); $expected = '`created` timestamp DEFAULT CURRENT_TIMESTAMP'; $this->assertEquals($expected, $result); $data = array( 'name' => 'modified', 'type' => 'timestamp', 'null' => true, ); $result = $this->Dbo->buildColumn($data); $expected = '`modified` timestamp NULL'; $this->assertEquals($expected, $result); $data = array( 'name' => 'modified', 'type' => 'timestamp', 'default' => null, 'null' => true, ); $result = $this->Dbo->buildColumn($data); $expected = '`modified` timestamp NULL'; $this->assertEquals($expected, $result); } /** * testBuildColumnBadType method * * @expectedException PHPUnit_Framework_Error * @return void */ public function testBuildColumnBadType() { $data = array( 'name' => 'testName', 'type' => 'varchar(255)', 'default', 'null' => true, 'key' ); $this->Dbo->buildColumn($data); } /** * Test `unsigned` field parameter * * @param array $data Column data * @param string $expected Expected sql part * * @return void * * @dataProvider buildColumnUnsignedProvider */ public function testBuildColumnUnsigned($data, $expected) { $result = $this->Dbo->buildColumn($data); $this->assertEquals($expected, $result); } /** * Data provider testBuildColumnUnsigned method * * @return array */ public function buildColumnUnsignedProvider() { return array( //set #0 array( array( 'name' => 'testName', 'type' => 'integer', 'length' => 11, 'unsigned' => true ), '`testName` int(11) UNSIGNED' ), //set #1 array( array( 'name' => 'testName', 'type' => 'biginteger', 'length' => 20, 'unsigned' => true ), '`testName` bigint(20) UNSIGNED' ), //set #2 array( array( 'name' => 'testName', 'type' => 'float', 'unsigned' => true ), '`testName` float UNSIGNED' ), //set #3 array( array( 'name' => 'testName', 'type' => 'string', 'length' => 255, 'unsigned' => true ), '`testName` varchar(255)' ), //set #4 array( array( 'name' => 'testName', 'type' => 'date', 'unsigned' => true ), '`testName` date' ), //set #5 array( array( 'name' => 'testName', 'type' => 'date', 'unsigned' => false ), '`testName` date' ), //set #6 array( array( 'name' => 'testName', 'type' => 'integer', 'length' => 11, 'unsigned' => false ), '`testName` int(11)' ), //set #7 array( array( 'name' => 'testName', 'type' => 'decimal', 'unsigned' => true ), '`testName` decimal UNSIGNED' ), //set #8 array( array( 'name' => 'testName', 'type' => 'decimal', 'unsigned' => true, 'default' => 1 ), '`testName` decimal UNSIGNED DEFAULT 1' ) ); } /** * Test getting `unsigned` field parameter from DB * * @return void */ public function testSchemaUnsigned() { $this->loadFixtures('Unsigned'); $Model = ClassRegistry::init('Model'); $Model->setSource('unsigned'); $types = $this->Dbo->fieldParameters['unsigned']['types']; $schema = $Model->schema(); foreach ($types as $type) { $this->assertArrayHasKey('unsigned', $schema['u' . $type]); $this->assertTrue($schema['u' . $type]['unsigned']); $this->assertArrayHasKey('unsigned', $schema[$type]); $this->assertFalse($schema[$type]['unsigned']); } $this->assertArrayNotHasKey('unsigned', $schema['string']); } /** * test hasAny() * * @return void */ public function testHasAny() { $db = $this->Dbo->config['database']; $this->Dbo = $this->getMock('Mysql', array('connect', '_execute', 'execute', 'value')); $this->Dbo->config['database'] = $db; $this->Model = $this->getMock('TestModel', array('getDataSource')); $this->Model->expects($this->any()) ->method('getDataSource') ->will($this->returnValue($this->Dbo)); $this->Dbo->expects($this->at(0))->method('value') ->with('harry') ->will($this->returnValue("'harry'")); $modelTable = $this->Dbo->fullTableName($this->Model); $this->Dbo->expects($this->at(1))->method('execute') ->with('SELECT COUNT(`TestModel`.`id`) AS count FROM ' . $modelTable . ' AS `TestModel` WHERE `TestModel`.`name` = \'harry\''); $this->Dbo->expects($this->at(2))->method('execute') ->with('SELECT COUNT(`TestModel`.`id`) AS count FROM ' . $modelTable . ' AS `TestModel` WHERE 1 = 1'); $this->Dbo->hasAny($this->Model, array('TestModel.name' => 'harry')); $this->Dbo->hasAny($this->Model, array()); } /** * test fields generating usable virtual fields to use in query * * @return void */ public function testVirtualFields() { $this->loadFixtures('Article', 'Comment', 'Tag'); $this->Dbo->virtualFieldSeparator = '__'; $Article = ClassRegistry::init('Article'); $commentsTable = $this->Dbo->fullTableName('comments', false, false); $Article->virtualFields = array( 'this_moment' => 'NOW()', 'two' => '1 + 1', 'comment_count' => 'SELECT COUNT(*) FROM ' . $commentsTable . ' WHERE Article.id = ' . $commentsTable . '.article_id' ); $result = $this->Dbo->fields($Article); $expected = array( '`Article`.`id`', '`Article`.`user_id`', '`Article`.`title`', '`Article`.`body`', '`Article`.`published`', '`Article`.`created`', '`Article`.`updated`', '(NOW()) AS `Article__this_moment`', '(1 + 1) AS `Article__two`', "(SELECT COUNT(*) FROM $commentsTable WHERE `Article`.`id` = `$commentsTable`.`article_id`) AS `Article__comment_count`" ); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($Article, null, array('this_moment', 'title')); $expected = array( '`Article`.`title`', '(NOW()) AS `Article__this_moment`', ); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($Article, null, array('Article.title', 'Article.this_moment')); $expected = array( '`Article`.`title`', '(NOW()) AS `Article__this_moment`', ); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($Article, null, array('Article.this_moment', 'Article.title')); $expected = array( '`Article`.`title`', '(NOW()) AS `Article__this_moment`', ); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($Article, null, array('Article.*')); $expected = array( '`Article`.*', '(NOW()) AS `Article__this_moment`', '(1 + 1) AS `Article__two`', "(SELECT COUNT(*) FROM $commentsTable WHERE `Article`.`id` = `$commentsTable`.`article_id`) AS `Article__comment_count`" ); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($Article, null, array('*')); $expected = array( '*', '(NOW()) AS `Article__this_moment`', '(1 + 1) AS `Article__two`', "(SELECT COUNT(*) FROM $commentsTable WHERE `Article`.`id` = `$commentsTable`.`article_id`) AS `Article__comment_count`" ); $this->assertEquals($expected, $result); } /** * test find() generating usable virtual fields to use in query without modifying custom subqueries. * * @return void */ public function testVirtualFieldsWithSubquery() { $this->loadFixtures('Article', 'Comment', 'User', 'Tag', 'ArticlesTag'); $this->Dbo->virtualFieldSeparator = '__'; $Article = ClassRegistry::init('Article'); $commentsTable = $this->Dbo->fullTableName('comments', false, false); $Article->Comment->virtualFields = array( 'extra' => 'SELECT id FROM ' . $commentsTable . ' WHERE id = (SELECT 1)', ); $conditions = array('Article.id' => array(1, 2)); $contain = array('Comment.extra'); $test = ConnectionManager::getDatasource('test'); $test->getLog(); $result = $Article->find('all', compact('conditions', 'contain')); $expected = 'SELECT `Comment`.`id`, `Comment`.`article_id`, `Comment`.`user_id`, `Comment`.`comment`,' . ' `Comment`.`published`, `Comment`.`created`,' . ' `Comment`.`updated`, (SELECT id FROM comments WHERE id = (SELECT 1)) AS `Comment__extra`' . ' FROM ' . $test->fullTableName('comments') . ' AS `Comment` WHERE `Comment`.`article_id` IN (1, 2)'; $log = $test->getLog(); $this->assertTextEquals($expected, $log['log'][count($log['log']) - 2]['query']); } /** * test conditions to generate query conditions for virtual fields * * @return void */ public function testVirtualFieldsInConditions() { $Article = ClassRegistry::init('Article'); $commentsTable = $this->Dbo->fullTableName('comments', false, false); $Article->virtualFields = array( 'this_moment' => 'NOW()', 'two' => '1 + 1', 'comment_count' => 'SELECT COUNT(*) FROM ' . $commentsTable . ' WHERE Article.id = ' . $commentsTable . '.article_id' ); $conditions = array('two' => 2); $result = $this->Dbo->conditions($conditions, true, false, $Article); $expected = '(1 + 1) = 2'; $this->assertEquals($expected, $result); $conditions = array('this_moment BETWEEN ? AND ?' => array(1, 2)); $expected = 'NOW() BETWEEN 1 AND 2'; $result = $this->Dbo->conditions($conditions, true, false, $Article); $this->assertEquals($expected, $result); $conditions = array('comment_count >' => 5); $expected = "(SELECT COUNT(*) FROM $commentsTable WHERE `Article`.`id` = `$commentsTable`.`article_id`) > 5"; $result = $this->Dbo->conditions($conditions, true, false, $Article); $this->assertEquals($expected, $result); $conditions = array('NOT' => array('two' => 2)); $result = $this->Dbo->conditions($conditions, true, false, $Article); $expected = 'NOT ((1 + 1) = 2)'; $this->assertEquals($expected, $result); } /** * test that virtualFields with complex functions and aliases work. * * @return void */ public function testConditionsWithComplexVirtualFields() { $Article = ClassRegistry::init('Article', 'Comment', 'Tag'); $Article->virtualFields = array( 'distance' => 'ACOS(SIN(20 * PI() / 180) * SIN(Article.latitude * PI() / 180) + COS(20 * PI() / 180) * COS(Article.latitude * PI() / 180) * COS((50 - Article.longitude) * PI() / 180) ) * 180 / PI() * 60 * 1.1515 * 1.609344' ); $conditions = array('distance >=' => 20); $result = $this->Dbo->conditions($conditions, true, true, $Article); $this->assertRegExp('/\) >= 20/', $result); $this->assertRegExp('/[`\'"]Article[`\'"].[`\'"]latitude[`\'"]/', $result); $this->assertRegExp('/[`\'"]Article[`\'"].[`\'"]longitude[`\'"]/', $result); } /** * test calculate to generate claculate statements on virtual fields * * @return void */ public function testVirtualFieldsInCalculate() { $Article = ClassRegistry::init('Article'); $commentsTable = $this->Dbo->fullTableName('comments', false, false); $Article->virtualFields = array( 'this_moment' => 'NOW()', 'two' => '1 + 1', 'comment_count' => 'SELECT COUNT(*) FROM ' . $commentsTable . ' WHERE Article.id = ' . $commentsTable . '.article_id' ); $result = $this->Dbo->calculate($Article, 'count', array('this_moment')); $expected = 'COUNT(NOW()) AS `count`'; $this->assertEquals($expected, $result); $result = $this->Dbo->calculate($Article, 'max', array('comment_count')); $expected = "MAX(SELECT COUNT(*) FROM $commentsTable WHERE `Article`.`id` = `$commentsTable`.`article_id`) AS `comment_count`"; $this->assertEquals($expected, $result); } /** * test reading virtual fields containing newlines when recursive > 0 * * @return void */ public function testReadVirtualFieldsWithNewLines() { $Article = new Article(); $Article->recursive = 1; $Article->virtualFields = array( 'test' => ' User.id + User.id ' ); $result = $this->Dbo->fields($Article, null, array()); $result = $this->Dbo->fields($Article, $Article->alias, $result); $this->assertRegExp('/[`\"]User[`\"]\.[`\"]id[`\"] \+ [`\"]User[`\"]\.[`\"]id[`\"]/', $result[7]); } /** * test group to generate GROUP BY statements on virtual fields * * @return void */ public function testVirtualFieldsInGroup() { $Article = ClassRegistry::init('Article'); $Article->virtualFields = array( 'this_year' => 'YEAR(Article.created)' ); $result = $this->Dbo->group('this_year', $Article); $expected = " GROUP BY (YEAR(`Article`.`created`))"; $this->assertEquals($expected, $result); } /** * test that virtualFields with complex functions and aliases work. * * @return void */ public function testFieldsWithComplexVirtualFields() { $Article = new Article(); $Article->virtualFields = array( 'distance' => 'ACOS(SIN(20 * PI() / 180) * SIN(Article.latitude * PI() / 180) + COS(20 * PI() / 180) * COS(Article.latitude * PI() / 180) * COS((50 - Article.longitude) * PI() / 180) ) * 180 / PI() * 60 * 1.1515 * 1.609344' ); $fields = array('id', 'distance'); $result = $this->Dbo->fields($Article, null, $fields); $qs = $this->Dbo->startQuote; $qe = $this->Dbo->endQuote; $this->assertEquals("{$qs}Article{$qe}.{$qs}id{$qe}", $result[0]); $this->assertRegExp('/Article__distance/', $result[1]); $this->assertRegExp('/[`\'"]Article[`\'"].[`\'"]latitude[`\'"]/', $result[1]); $this->assertRegExp('/[`\'"]Article[`\'"].[`\'"]longitude[`\'"]/', $result[1]); } /** * test that execute runs queries. * * @return void */ public function testExecute() { $query = 'SELECT * FROM ' . $this->Dbo->fullTableName('articles') . ' WHERE 1 = 1'; $this->Dbo->took = null; $this->Dbo->affected = null; $result = $this->Dbo->execute($query, array('log' => false)); $this->assertNotNull($result, 'No query performed! %s'); $this->assertNull($this->Dbo->took, 'Stats were set %s'); $this->assertNull($this->Dbo->affected, 'Stats were set %s'); $result = $this->Dbo->execute($query); $this->assertNotNull($result, 'No query performed! %s'); $this->assertNotNull($this->Dbo->took, 'Stats were not set %s'); $this->assertNotNull($this->Dbo->affected, 'Stats were not set %s'); } /** * test a full example of using virtual fields * * @return void */ public function testVirtualFieldsFetch() { $this->loadFixtures('Article', 'Comment'); $Article = ClassRegistry::init('Article'); $Article->virtualFields = array( 'comment_count' => 'SELECT COUNT(*) FROM ' . $this->Dbo->fullTableName('comments') . ' WHERE Article.id = ' . $this->Dbo->fullTableName('comments') . '.article_id' ); $conditions = array('comment_count >' => 2); $query = 'SELECT ' . implode(',', $this->Dbo->fields($Article, null, array('id', 'comment_count'))) . ' FROM ' . $this->Dbo->fullTableName($Article) . ' Article ' . $this->Dbo->conditions($conditions, true, true, $Article); $result = $this->Dbo->fetchAll($query); $expected = array(array( 'Article' => array('id' => 1, 'comment_count' => 4) )); $this->assertEquals($expected, $result); } /** * test reading complex virtualFields with subqueries. * * @return void */ public function testVirtualFieldsComplexRead() { $this->loadFixtures('DataTest', 'Article', 'Comment', 'User', 'Tag', 'ArticlesTag'); $Article = ClassRegistry::init('Article'); $commentTable = $this->Dbo->fullTableName('comments'); $Article = ClassRegistry::init('Article'); $Article->virtualFields = array( 'comment_count' => 'SELECT COUNT(*) FROM ' . $commentTable . ' AS Comment WHERE Article.id = Comment.article_id' ); $result = $Article->find('all'); $this->assertTrue(count($result) > 0); $this->assertTrue($result[0]['Article']['comment_count'] > 0); $DataTest = ClassRegistry::init('DataTest'); $DataTest->virtualFields = array( 'complicated' => 'ACOS(SIN(20 * PI() / 180) * SIN(DataTest.float * PI() / 180) + COS(20 * PI() / 180) * COS(DataTest.count * PI() / 180) * COS((50 - DataTest.float) * PI() / 180) ) * 180 / PI() * 60 * 1.1515 * 1.609344' ); $result = $DataTest->find('all'); $this->assertTrue(count($result) > 0); $this->assertTrue($result[0]['DataTest']['complicated'] > 0); } /** * testIntrospectType method * * @return void */ public function testIntrospectType() { $this->assertEquals('integer', $this->Dbo->introspectType(0)); $this->assertEquals('integer', $this->Dbo->introspectType(2)); $this->assertEquals('string', $this->Dbo->introspectType('2')); $this->assertEquals('string', $this->Dbo->introspectType('2.2')); $this->assertEquals('float', $this->Dbo->introspectType(2.2)); $this->assertEquals('string', $this->Dbo->introspectType('stringme')); $this->assertEquals('string', $this->Dbo->introspectType('0stringme')); $data = array(2.2); $this->assertEquals('float', $this->Dbo->introspectType($data)); $data = array('2.2'); $this->assertEquals('float', $this->Dbo->introspectType($data)); $data = array(2); $this->assertEquals('integer', $this->Dbo->introspectType($data)); $data = array('2'); $this->assertEquals('integer', $this->Dbo->introspectType($data)); $data = array('string'); $this->assertEquals('string', $this->Dbo->introspectType($data)); $data = array(2.2, '2.2'); $this->assertEquals('float', $this->Dbo->introspectType($data)); $data = array(2, '2'); $this->assertEquals('integer', $this->Dbo->introspectType($data)); $data = array('string one', 'string two'); $this->assertEquals('string', $this->Dbo->introspectType($data)); $data = array('2.2', 3); $this->assertEquals('integer', $this->Dbo->introspectType($data)); $data = array('2.2', '0stringme'); $this->assertEquals('string', $this->Dbo->introspectType($data)); $data = array(2.2, 3); $this->assertEquals('integer', $this->Dbo->introspectType($data)); $data = array(2.2, '0stringme'); $this->assertEquals('string', $this->Dbo->introspectType($data)); $data = array(2, 'stringme'); $this->assertEquals('string', $this->Dbo->introspectType($data)); $data = array(2, '2.2', 'stringgme'); $this->assertEquals('string', $this->Dbo->introspectType($data)); $data = array(2, '2.2'); $this->assertEquals('integer', $this->Dbo->introspectType($data)); $data = array(2, 2.2); $this->assertEquals('integer', $this->Dbo->introspectType($data)); // null $result = $this->Dbo->value(null, 'boolean'); $this->assertEquals('NULL', $result); // EMPTY STRING $result = $this->Dbo->value('', 'boolean'); $this->assertEquals("'0'", $result); // BOOLEAN $result = $this->Dbo->value('true', 'boolean'); $this->assertEquals("'1'", $result); $result = $this->Dbo->value('false', 'boolean'); $this->assertEquals("'1'", $result); $result = $this->Dbo->value(true, 'boolean'); $this->assertEquals("'1'", $result); $result = $this->Dbo->value(false, 'boolean'); $this->assertEquals("'0'", $result); $result = $this->Dbo->value(1, 'boolean'); $this->assertEquals("'1'", $result); $result = $this->Dbo->value(0, 'boolean'); $this->assertEquals("'0'", $result); $result = $this->Dbo->value('abc', 'boolean'); $this->assertEquals("'1'", $result); $result = $this->Dbo->value(1.234, 'boolean'); $this->assertEquals("'1'", $result); $result = $this->Dbo->value('1.234e05', 'boolean'); $this->assertEquals("'1'", $result); // NUMBERS $result = $this->Dbo->value(123, 'integer'); $this->assertEquals(123, $result); $result = $this->Dbo->value('123', 'integer'); $this->assertEquals('123', $result); $result = $this->Dbo->value('0123', 'integer'); $this->assertEquals("'0123'", $result); $result = $this->Dbo->value('0x123ABC', 'integer'); $this->assertEquals("'0x123ABC'", $result); $result = $this->Dbo->value('0x123', 'integer'); $this->assertEquals("'0x123'", $result); $result = $this->Dbo->value(1.234, 'float'); $this->assertEquals(1.234, $result); $result = $this->Dbo->value('1.234', 'float'); $this->assertEquals('1.234', $result); $result = $this->Dbo->value(' 1.234 ', 'float'); $this->assertEquals("' 1.234 '", $result); $result = $this->Dbo->value('1.234e05', 'float'); $this->assertEquals("'1.234e05'", $result); $result = $this->Dbo->value('1.234e+5', 'float'); $this->assertEquals("'1.234e+5'", $result); $result = $this->Dbo->value('1,234', 'float'); $this->assertEquals("'1,234'", $result); $result = $this->Dbo->value('FFF', 'integer'); $this->assertEquals("'FFF'", $result); $result = $this->Dbo->value('abc', 'integer'); $this->assertEquals("'abc'", $result); // STRINGS $result = $this->Dbo->value('123', 'string'); $this->assertEquals("'123'", $result); $result = $this->Dbo->value(123, 'string'); $this->assertEquals("'123'", $result); $result = $this->Dbo->value(1.234, 'string'); $this->assertEquals("'1.234'", $result); $result = $this->Dbo->value('abc', 'string'); $this->assertEquals("'abc'", $result); $result = $this->Dbo->value(' abc ', 'string'); $this->assertEquals("' abc '", $result); $result = $this->Dbo->value('a bc', 'string'); $this->assertEquals("'a bc'", $result); } /** * testRealQueries method * * @return void */ public function testRealQueries() { $this->loadFixtures('Apple', 'Article', 'User', 'Comment', 'Tag', 'Sample', 'ArticlesTag'); $Apple = ClassRegistry::init('Apple'); $Article = ClassRegistry::init('Article'); $result = $this->Dbo->rawQuery('SELECT color, name FROM ' . $this->Dbo->fullTableName('apples')); $this->assertTrue(!empty($result)); $result = $this->Dbo->fetchRow($result); $expected = array($this->Dbo->fullTableName('apples', false, false) => array( 'color' => 'Red 1', 'name' => 'Red Apple 1' )); $this->assertEquals($expected, $result); $result = $this->Dbo->fetchAll('SELECT name FROM ' . $this->Dbo->fullTableName('apples') . ' ORDER BY id'); $expected = array( array($this->Dbo->fullTableName('apples', false, false) => array('name' => 'Red Apple 1')), array($this->Dbo->fullTableName('apples', false, false) => array('name' => 'Bright Red Apple')), array($this->Dbo->fullTableName('apples', false, false) => array('name' => 'green blue')), array($this->Dbo->fullTableName('apples', false, false) => array('name' => 'Test Name')), array($this->Dbo->fullTableName('apples', false, false) => array('name' => 'Blue Green')), array($this->Dbo->fullTableName('apples', false, false) => array('name' => 'My new apple')), array($this->Dbo->fullTableName('apples', false, false) => array('name' => 'Some odd color')) ); $this->assertEquals($expected, $result); $result = $this->Dbo->field($this->Dbo->fullTableName('apples', false, false), 'SELECT color, name FROM ' . $this->Dbo->fullTableName('apples') . ' ORDER BY id'); $expected = array( 'color' => 'Red 1', 'name' => 'Red Apple 1' ); $this->assertEquals($expected, $result); $Apple->unbindModel(array(), false); $result = $this->Dbo->read($Apple, array( 'fields' => array($Apple->escapeField('name')), 'conditions' => null, 'recursive' => -1 )); $expected = array( array('Apple' => array('name' => 'Red Apple 1')), array('Apple' => array('name' => 'Bright Red Apple')), array('Apple' => array('name' => 'green blue')), array('Apple' => array('name' => 'Test Name')), array('Apple' => array('name' => 'Blue Green')), array('Apple' => array('name' => 'My new apple')), array('Apple' => array('name' => 'Some odd color')) ); $this->assertEquals($expected, $result); $result = $this->Dbo->read($Article, array( 'fields' => array('id', 'user_id', 'title'), 'conditions' => null, 'recursive' => 1 )); $this->assertTrue(Set::matches('/Article[id=1]', $result)); $this->assertTrue(Set::matches('/Comment[id=1]', $result)); $this->assertTrue(Set::matches('/Comment[id=2]', $result)); $this->assertFalse(Set::matches('/Comment[id=10]', $result)); } /** * @expectedException MissingConnectionException * @return void */ public function testExceptionOnBrokenConnection() { new Mysql(array( 'driver' => 'mysql', 'host' => 'imaginary_host', 'login' => 'mark', 'password' => 'inyurdatabase', 'database' => 'imaginary' )); } /** * testStatements method * * @return void */ public function testUpdateStatements() { $this->loadFixtures('Article', 'User'); $test = ConnectionManager::getDatasource('test'); $db = $test->config['database']; $this->Dbo = $this->getMock('Mysql', array('execute'), array($test->config)); $this->Dbo->expects($this->at(0))->method('execute') ->with("UPDATE `$db`.`articles` SET `field1` = 'value1' WHERE 1 = 1"); $this->Dbo->expects($this->at(1))->method('execute') ->with("UPDATE `$db`.`articles` AS `Article` LEFT JOIN `$db`.`users` AS `User` ON " . "(`Article`.`user_id` = `User`.`id`)" . " SET `Article`.`field1` = 2 WHERE 2=2"); $this->Dbo->expects($this->at(2))->method('execute') ->with("UPDATE `$db`.`articles` AS `Article` LEFT JOIN `$db`.`users` AS `User` ON " . "(`Article`.`user_id` = `User`.`id`)" . " SET `Article`.`field1` = 'value' WHERE `index` = 'val'"); $Article = new Article(); $this->Dbo->update($Article, array('field1'), array('value1')); $this->Dbo->update($Article, array('field1'), array('2'), '2=2'); $this->Dbo->update($Article, array('field1'), array("'value'"), array('index' => 'val')); } /** * Test deletes with a mock. * * @return void */ public function testDeleteStatements() { $this->loadFixtures('Article', 'User'); $test = ConnectionManager::getDatasource('test'); $db = $test->config['database']; $this->Dbo = $this->getMock('Mysql', array('execute'), array($test->config)); $this->Dbo->expects($this->at(0))->method('execute') ->with("DELETE FROM `$db`.`articles` WHERE 1 = 1"); $this->Dbo->expects($this->at(1))->method('execute') ->with("DELETE `Article` FROM `$db`.`articles` AS `Article` LEFT JOIN `$db`.`users` AS `User` " . "ON (`Article`.`user_id` = `User`.`id`)" . " WHERE 1 = 1"); $this->Dbo->expects($this->at(2))->method('execute') ->with("DELETE `Article` FROM `$db`.`articles` AS `Article` LEFT JOIN `$db`.`users` AS `User` " . "ON (`Article`.`user_id` = `User`.`id`)" . " WHERE 2=2"); $Article = new Article(); $this->Dbo->delete($Article); $this->Dbo->delete($Article, true); $this->Dbo->delete($Article, '2=2'); } /** * Test truncate with a mock. * * @return void */ public function testTruncateStatements() { $this->loadFixtures('Article', 'User'); $db = ConnectionManager::getDatasource('test'); $schema = $db->config['database']; $Article = new Article(); $this->Dbo = $this->getMock('Mysql', array('execute'), array($db->config)); $this->Dbo->expects($this->at(0))->method('execute') ->with("TRUNCATE TABLE `$schema`.`articles`"); $this->Dbo->truncate($Article); $this->Dbo->expects($this->at(0))->method('execute') ->with("TRUNCATE TABLE `$schema`.`articles`"); $this->Dbo->truncate('articles'); // #2355: prevent duplicate prefix $this->Dbo->config['prefix'] = 'tbl_'; $Article->tablePrefix = 'tbl_'; $this->Dbo->expects($this->at(0))->method('execute') ->with("TRUNCATE TABLE `$schema`.`tbl_articles`"); $this->Dbo->truncate($Article); $this->Dbo->expects($this->at(0))->method('execute') ->with("TRUNCATE TABLE `$schema`.`tbl_articles`"); $this->Dbo->truncate('articles'); } /** * Test nested transaction * * @return void */ public function testNestedTransaction() { $nested = $this->Dbo->useNestedTransactions; $this->Dbo->useNestedTransactions = true; if ($this->Dbo->nestedTransactionSupported() === false) { $this->Dbo->useNestedTransactions = $nested; $this->skipIf(true, 'The MySQL server do not support nested transaction'); } $this->loadFixtures('Inno'); $model = ClassRegistry::init('Inno'); $model->hasOne = $model->hasMany = $model->belongsTo = $model->hasAndBelongsToMany = array(); $model->cacheQueries = false; $this->Dbo->cacheMethods = false; $this->assertTrue($this->Dbo->begin()); $this->assertNotEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->begin()); $this->assertTrue($model->delete(1)); $this->assertEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->rollback()); $this->assertNotEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->begin()); $this->assertTrue($model->delete(1)); $this->assertEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->commit()); $this->assertEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->rollback()); $this->assertNotEmpty($model->read(null, 1)); $this->Dbo->useNestedTransactions = $nested; } /** * Test that value() quotes set values even when numeric. * * @return void */ public function testSetValue() { $column = "set('a','b','c')"; $result = $this->Dbo->value('1', $column); $this->assertEquals("'1'", $result); $result = $this->Dbo->value(1, $column); $this->assertEquals("'1'", $result); $result = $this->Dbo->value('a', $column); $this->assertEquals("'a'", $result); } /** * Test isConnected * * @return void */ public function testIsConnected() { $this->Dbo->disconnect(); $this->assertFalse($this->Dbo->isConnected(), 'Not connected now.'); $this->Dbo->connect(); $this->assertTrue($this->Dbo->isConnected(), 'Should be connected.'); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php000066400000000000000000001225521265552240500263710ustar00rootroot00000000000000simulated[] = $sql; return null; } /** * getLastQuery method * * @return void */ public function getLastQuery() { return $this->simulated[count($this->simulated) - 1]; } } /** * PostgresTestModel class * * @package Cake.Test.Case.Model.Datasource.Database */ class PostgresTestModel extends Model { /** * useTable property * * @var bool */ public $useTable = false; /** * belongsTo property * * @var array */ public $belongsTo = array( 'PostgresClientTestModel' => array( 'foreignKey' => 'client_id' ) ); /** * find method * * @param mixed $conditions * @param mixed $fields * @param mixed $order * @param mixed $recursive * @return void */ public function find($conditions = null, $fields = null, $order = null, $recursive = null) { return $conditions; } /** * findAll method * * @param mixed $conditions * @param mixed $fields * @param mixed $order * @param mixed $recursive * @return void */ public function findAll($conditions = null, $fields = null, $order = null, $recursive = null) { return $conditions; } /** * schema method * * @return void */ public function schema($field = false) { return array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'client_id' => array('type' => 'integer', 'null' => '', 'default' => '0', 'length' => '11'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'login' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'passwd' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'), 'addr_1' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'), 'addr_2' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '25'), 'zip_code' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'city' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'country' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'phone' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'fax' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'url' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'), 'email' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'comments' => array('type' => 'text', 'null' => '1', 'default' => '', 'length' => ''), 'last_login' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => ''), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); } } /** * PostgresClientTestModel class * * @package Cake.Test.Case.Model.Datasource.Database */ class PostgresClientTestModel extends Model { /** * useTable property * * @var bool */ public $useTable = false; /** * schema method * * @return void */ public function schema($field = false) { return array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8', 'key' => 'primary'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'email' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'created' => array('type' => 'datetime', 'null' => true, 'default' => null, 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => true, 'default' => null, 'length' => null) ); } } /** * PostgresTest class * * @package Cake.Test.Case.Model.Datasource.Database */ class PostgresTest extends CakeTestCase { /** * Do not automatically load fixtures for each test, they will be loaded manually * using CakeTestCase::loadFixtures * * @var bool */ public $autoFixtures = false; /** * Fixtures * * @var object */ public $fixtures = array('core.user', 'core.binary_test', 'core.comment', 'core.article', 'core.tag', 'core.articles_tag', 'core.attachment', 'core.person', 'core.post', 'core.author', 'core.datatype', ); /** * Actual DB connection used in testing * * @var DboSource */ public $Dbo = null; /** * Simulated DB connection used in testing * * @var DboSource */ public $Dbo2 = null; /** * Sets up a Dbo class instance for testing * * @return void */ public function setUp() { parent::setUp(); Configure::write('Cache.disable', true); $this->Dbo = ConnectionManager::getDataSource('test'); $this->skipIf(!($this->Dbo instanceof Postgres)); $this->Dbo2 = new DboPostgresTestDb($this->Dbo->config, false); $this->model = new PostgresTestModel(); } /** * Sets up a Dbo class instance for testing * * @return void */ public function tearDown() { parent::tearDown(); Configure::write('Cache.disable', false); unset($this->Dbo2); } /** * Test field quoting method * * @return void */ public function testFieldQuoting() { $fields = array( '"PostgresTestModel"."id" AS "PostgresTestModel__id"', '"PostgresTestModel"."client_id" AS "PostgresTestModel__client_id"', '"PostgresTestModel"."name" AS "PostgresTestModel__name"', '"PostgresTestModel"."login" AS "PostgresTestModel__login"', '"PostgresTestModel"."passwd" AS "PostgresTestModel__passwd"', '"PostgresTestModel"."addr_1" AS "PostgresTestModel__addr_1"', '"PostgresTestModel"."addr_2" AS "PostgresTestModel__addr_2"', '"PostgresTestModel"."zip_code" AS "PostgresTestModel__zip_code"', '"PostgresTestModel"."city" AS "PostgresTestModel__city"', '"PostgresTestModel"."country" AS "PostgresTestModel__country"', '"PostgresTestModel"."phone" AS "PostgresTestModel__phone"', '"PostgresTestModel"."fax" AS "PostgresTestModel__fax"', '"PostgresTestModel"."url" AS "PostgresTestModel__url"', '"PostgresTestModel"."email" AS "PostgresTestModel__email"', '"PostgresTestModel"."comments" AS "PostgresTestModel__comments"', '"PostgresTestModel"."last_login" AS "PostgresTestModel__last_login"', '"PostgresTestModel"."created" AS "PostgresTestModel__created"', '"PostgresTestModel"."updated" AS "PostgresTestModel__updated"' ); $result = $this->Dbo->fields($this->model); $expected = $fields; $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->model, null, 'PostgresTestModel.*'); $expected = $fields; $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->model, null, array('*', 'AnotherModel.id', 'AnotherModel.name')); $expected = array_merge($fields, array( '"AnotherModel"."id" AS "AnotherModel__id"', '"AnotherModel"."name" AS "AnotherModel__name"')); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($this->model, null, array('*', 'PostgresClientTestModel.*')); $expected = array_merge($fields, array( '"PostgresClientTestModel"."id" AS "PostgresClientTestModel__id"', '"PostgresClientTestModel"."name" AS "PostgresClientTestModel__name"', '"PostgresClientTestModel"."email" AS "PostgresClientTestModel__email"', '"PostgresClientTestModel"."created" AS "PostgresClientTestModel__created"', '"PostgresClientTestModel"."updated" AS "PostgresClientTestModel__updated"')); $this->assertEquals($expected, $result); } /** * testColumnParsing method * * @return void */ public function testColumnParsing() { $this->assertEquals('text', $this->Dbo2->column('text')); $this->assertEquals('date', $this->Dbo2->column('date')); $this->assertEquals('boolean', $this->Dbo2->column('boolean')); $this->assertEquals('string', $this->Dbo2->column('character varying')); $this->assertEquals('time', $this->Dbo2->column('time without time zone')); $this->assertEquals('datetime', $this->Dbo2->column('timestamp without time zone')); $this->assertEquals('decimal', $this->Dbo2->column('decimal')); $this->assertEquals('decimal', $this->Dbo2->column('numeric')); $this->assertEquals('float', $this->Dbo2->column('float')); $this->assertEquals('float', $this->Dbo2->column('double precision')); $result = $this->Dbo2->column('bigint'); $expected = 'biginteger'; $this->assertEquals($expected, $result); } /** * testValueQuoting method * * @return void */ public function testValueQuoting() { $this->assertEquals("1.200000", $this->Dbo->value(1.2, 'float')); $this->assertEquals("'1,2'", $this->Dbo->value('1,2', 'float')); $this->assertEquals("0", $this->Dbo->value('0', 'integer')); $this->assertEquals('NULL', $this->Dbo->value('', 'integer')); $this->assertEquals('NULL', $this->Dbo->value('', 'float')); $this->assertEquals('""', $this->Dbo->value('', 'integer', false)); $this->assertEquals('""', $this->Dbo->value('', 'float', false)); $this->assertEquals("'0.0'", $this->Dbo->value('0.0', 'float')); $this->assertEquals("'TRUE'", $this->Dbo->value('t', 'boolean')); $this->assertEquals("'FALSE'", $this->Dbo->value('f', 'boolean')); $this->assertEquals("'TRUE'", $this->Dbo->value(true)); $this->assertEquals("'FALSE'", $this->Dbo->value(false)); $this->assertEquals("'t'", $this->Dbo->value('t')); $this->assertEquals("'f'", $this->Dbo->value('f')); $this->assertEquals("'TRUE'", $this->Dbo->value('true', 'boolean')); $this->assertEquals("'FALSE'", $this->Dbo->value('false', 'boolean')); $this->assertEquals("'FALSE'", $this->Dbo->value('', 'boolean')); $this->assertEquals("'FALSE'", $this->Dbo->value(0, 'boolean')); $this->assertEquals("'TRUE'", $this->Dbo->value(1, 'boolean')); $this->assertEquals("'TRUE'", $this->Dbo->value('1', 'boolean')); $this->assertEquals("NULL", $this->Dbo->value(null, 'boolean')); $this->assertEquals("NULL", $this->Dbo->value(array())); } /** * test that localized floats don't cause trouble. * * @return void */ public function testLocalizedFloats() { $restore = setlocale(LC_NUMERIC, 0); $this->skipIf(setlocale(LC_NUMERIC, 'de_DE') === false, "The German locale isn't available."); $result = $this->db->value(3.141593, 'float'); $this->assertEquals("3.141593", $result); $result = $this->db->value(3.14); $this->assertEquals("3.140000", $result); setlocale(LC_NUMERIC, $restore); } /** * test that date and time columns do not generate errors with null and nullish values. * * @return void */ public function testDateAndTimeAsNull() { $this->assertEquals('NULL', $this->Dbo->value(null, 'date')); $this->assertEquals('NULL', $this->Dbo->value('', 'date')); $this->assertEquals('NULL', $this->Dbo->value('', 'datetime')); $this->assertEquals('NULL', $this->Dbo->value(null, 'datetime')); $this->assertEquals('NULL', $this->Dbo->value('', 'timestamp')); $this->assertEquals('NULL', $this->Dbo->value(null, 'timestamp')); $this->assertEquals('NULL', $this->Dbo->value('', 'time')); $this->assertEquals('NULL', $this->Dbo->value(null, 'time')); } /** * Tests that different Postgres boolean 'flavors' are properly returned as native PHP booleans * * @return void */ public function testBooleanNormalization() { $this->assertEquals(true, $this->Dbo2->boolean('t', false)); $this->assertEquals(true, $this->Dbo2->boolean('true', false)); $this->assertEquals(true, $this->Dbo2->boolean('TRUE', false)); $this->assertEquals(true, $this->Dbo2->boolean(true, false)); $this->assertEquals(true, $this->Dbo2->boolean(1, false)); $this->assertEquals(true, $this->Dbo2->boolean(" ", false)); $this->assertEquals(false, $this->Dbo2->boolean('f', false)); $this->assertEquals(false, $this->Dbo2->boolean('false', false)); $this->assertEquals(false, $this->Dbo2->boolean('FALSE', false)); $this->assertEquals(false, $this->Dbo2->boolean(false, false)); $this->assertEquals(false, $this->Dbo2->boolean(0, false)); $this->assertEquals(false, $this->Dbo2->boolean('', false)); } /** * test that default -> false in schemas works correctly. * * @return void */ public function testBooleanDefaultFalseInSchema() { $this->loadFixtures('Datatype'); $model = new Model(array('name' => 'Datatype', 'table' => 'datatypes', 'ds' => 'test')); $model->create(); $this->assertSame(false, $model->data['Datatype']['bool']); } /** * testLastInsertIdMultipleInsert method * * @return void */ public function testLastInsertIdMultipleInsert() { $this->loadFixtures('User'); $db1 = ConnectionManager::getDataSource('test'); $table = $db1->fullTableName('users', false); $password = '5f4dcc3b5aa765d61d8327deb882cf99'; $db1->execute( "INSERT INTO {$table} (\"user\", password) VALUES ('mariano', '{$password}')" ); $this->assertEquals(5, $db1->lastInsertId($table)); $db1->execute("INSERT INTO {$table} (\"user\", password) VALUES ('hoge', '{$password}')"); $this->assertEquals(6, $db1->lastInsertId($table)); } /** * Tests that column types without default lengths in $columns do not have length values * applied when generating schemas. * * @return void */ public function testColumnUseLength() { $result = array('name' => 'foo', 'type' => 'string', 'length' => 100, 'default' => 'FOO'); $expected = '"foo" varchar(100) DEFAULT \'FOO\''; $this->assertEquals($expected, $this->Dbo->buildColumn($result)); $result = array('name' => 'foo', 'type' => 'text', 'length' => 100, 'default' => 'FOO'); $expected = '"foo" text DEFAULT \'FOO\''; $this->assertEquals($expected, $this->Dbo->buildColumn($result)); } /** * Tests that binary data is escaped/unescaped properly on reads and writes * * @return void */ public function testBinaryDataIntegrity() { $this->loadFixtures('BinaryTest'); $data = '%PDF-1.3 %ฦ’ร‚รšร‚รŽรŸร›โ€ โ€“ฦ’โˆ† 4 0 obj << /Length 5 0 R /Filter /FlateDecode >> stream xยตYMรฌโ‚ฌโˆ†ฮฉโ€žWรƒ%)nรฏ0ยฏรฎรข-ยซรฉ]Q"ฯ€Xยตรกรฟโ€ขIp - P V,]รš#cหšห‡โ€ฐutยฅโ€ โˆTi9 รœ=โ€โ€บร˜_หœ4>ร โˆ‘โ€šร‰pcรฉยขPxรฆยฎ2q\' 1UยชbU รกห‡โ€™+รถยซโˆš[ฤฑยตโ„รฃo"Rโˆ‘"HiGรฆรคโ‚ฌ(รฅโ‰ โ‰ˆ^รƒรธsm?Ylฦ’รƒรตยช๏ฌโ€นรขEรšB&โ€šรŽโ—Š7bร’^ยธmยฐรทห›?2ยฑร˜sโ€œ๏ฌu#ยฎUโˆšห‡รบรทgยฅ๏ฃฟC;รค")n})JยบIร”3ร‹Snร‘รŽยฅโ‰คฤฑDโˆ†ยขโˆ‚Msx1รผรจGหšยฑล’โ„ขโ„>ยถySรฏufร˜ย หยธ?Uฯ€รƒรฃโˆš6๏ฌ‚รŒรšC=รธK?หโ€ฆs ห›ยงยฏห‡:-๏ฃฟหœรฒ7โ‚ฌร“Fรฆโˆ‚โˆ‘ร•ห›โˆ†โ€œVโ€™>ฤฑl๏ฌ‚รซร…dยซรœQdI โ€บรŽB%Wยฟฮฉฤฑร‰n~h vรชCS>ยซรฉห›(ร˜รดK!โ‚ฌยกzB!โˆš [ล“รœ"รปรŸ ยทiHยธ[รƒโ‚ฌยบรฆโˆ‘ยฏยกL,ร€รšAlSโˆซห†=โˆซล’โ‰คcร„r&ห†รˆ:โˆšรฟยฃหšรˆยซ4๏ฌ‚โ€ขร€]vcโ€บbร…รดรฟรฎ=siXe4/ยกp]รฃ]รดร†Iล“โ„ขย ฮฉ๏ฌ‚ร _ฦ’โ€šG?ยซ7 รนรฟย ฤฑยฏK4รฏIpVโ—Šรทยท\'รฉยตรณยชรšรฆ>รฎ ;โ€บsรบ!2๏ฌ‚ยฌFโ€ข/fโˆ‘jยฃ dw"IรŠรœฯ€<รดรฟห†%IG1ytร›D๏ฌ‚Xg|ร‰รฒaยงหœ}Cห›ยฟรฟeยฐGยดรšยฑjรm~ยฟ/โˆ‚hรฃ<#-ยฅโ€ขฤฑรนe87โ‚ฌtหœรต6w}ยด{รฆ mโ€นรชโ€“ โˆ†ยก 6โ„\ rAร€BรนZ3aร‹โ€šr$Gยท$รณ0ร‘ รผรขUY4รˆโ„ขยก%Cโˆ‘ลธ2rcรCรคฤฑ =ร•ec=รซRหโ€eรฑ=รŠuNรชยฐโ€œโˆšรœย โ€นรŠ9iร™0ห™AAEร ห™`โˆ‚ยฃ\'รปceโ€ขรฅฦ’Xโ€บลธรยด1SK{qdรก"tร[wQ#SยตBeโˆžโˆ‘ยตรณโ€ฆรŒV`B"ร‘โ‰ฅโ€ž!รจ_ร“รโ€ -ยบ*ยบรบยฟร‹0ห†eรชโˆ‚ยดรซ+HFjโ€ฆโ€กzvHร“N|ร”Lรทรปรฑ3รตรœ$z%sรกโ€ฆpรŽรณV38รขs ร‡oยตโ€ขรŸ3โ€ <9Bยทยจรป~ยข3)ร‚xรณรฟรCร•รฒร† โˆซร=ยปรฟSฯ€S;โˆ†~ยฑรชร†TEpโˆ‘รณรˆรทร€uรฌDHรˆ $ร‰รตรฆรœjรƒยปยง"โ‰ครƒONMยฎRร‹รญRr{รตS โˆรŠโ„ขopยฑW;ร‚Uร” Pโˆซkร”ห‡๏ฌ‚Tรฆโˆ‘รณ๏ฌ‚ร‹โ€ ร†Cยฉร”[โ‰ฅโ—ŠHรหšยจhรช"ร†bF?รบ%hห™ห‡4xรจร•(รณ2ร™รกรญM])ร‘d|=fรซ-cI0รฑLยขkร–รชkโ€ฐRฦ’ยซฤฑร„Wรฑ8mO3โˆ&โˆšรฆร‹XยฏHรณโ€”รฌ]yF2ยปโ€“หœรกdร ร โ€กโ€นร‡รŽยฟโ€žโ‰ฅ7mยชHASโˆ‘ยถ.;ล’x(1} _kdยฉ.๏ฌdรง48M\'ร รกยชCp^Krรญ<ร‰โ€ฐXร“ฤฑรฏl!รŒ$N<ฤฑโˆžBยปG]โ€ฆโˆ‚ร“ยฏ>ห›ร”bรตร’ฯ€ร€โ€ข:รดO@รˆ$pร–uโ€นรŠยด-QqVย ?Vโ‰ฅJร†รqร›X8(lฯ€รฏ@zgร–}Fe<ห‡โ€กSรฑโ€œรฟหœรช?6โ€กLโˆซOรŸ~ยต โ€“?ร‹eรครšยฎYรฎร• =รœ=ยขDรu*GvBk;)LยฌNยซรฎ:flรถโˆ‚โ‰ ร‡ฮฉqโ€žร‘mรญโ€ขหœร‹โˆ‚โ€š"รปโ‰ฅยง:ยฑโ‰คi^ฮฉร‘!)W๏ฃฟฤฑyร…ยงรด รกโ€žRร„รทร’รดcโ€™โ‰ โ€”sโ„ขrฤฑ๏ฃฟโ€šPdรชรฃhห˜รŸHVรง5๏ฌ๏ฌรˆFโ‚ฌรงรŒร›uรงร–/M=gรซยตยฑรฟGรป1coร”uรฑรฆโ€˜zยฎ. รตโˆ‘7ร‰รรœร†,ยฐโ€™Hโ€ รร‰รŒโˆ‚7e ยบยฎย รญห†โ„โ—ŠรธNWKโ€ร‚Yยตโ€šรฑรฉ;ยตยถgV-๏ฌ‚>ยตtร‹ยฅรกรŸN2 ยฏยถBaP-)eW.ร รดt^โˆ1โ€บCโˆ‘ร–?Lโ€ž&โ€5โ€™4jvรฃโ€“ยชZ รท+4%ย ยด0lโ€ฆยปรบ^ยฐยดยฉย รปiฯ€โˆ‘๏ฃฟรฉยฎรณรœยฑร’รฟโ€ฐรฏห†รŒโ€“dห†โ—Šร†19rQ=ร|ฤฑโ€ขrMรฆยฌ;รฒโ€ฐYโ€ฐรฉ9.โ€ โ€นหVยซรฃยฏโˆ,+รซยฎj*ยกยท/'; $model = new AppModel(array('name' => 'BinaryTest', 'ds' => 'test')); $model->save(compact('data')); $result = $model->find('first'); $this->assertEquals($data, $result['BinaryTest']['data']); } /** * Tests passing PostgreSQL regular expression operators when building queries * * @return void */ public function testRegexpOperatorConditionsParsing() { $this->assertSame(' WHERE "name" ~ \'[a-z_]+\'', $this->Dbo->conditions(array('name ~' => '[a-z_]+'))); $this->assertSame(' WHERE "name" ~* \'[a-z_]+\'', $this->Dbo->conditions(array('name ~*' => '[a-z_]+'))); $this->assertSame(' WHERE "name" !~ \'[a-z_]+\'', $this->Dbo->conditions(array('name !~' => '[a-z_]+'))); $this->assertSame(' WHERE "name" !~* \'[a-z_]+\'', $this->Dbo->conditions(array('name !~*' => '[a-z_]+'))); $this->assertSame( ' WHERE EXTRACT( \'YEAR\' FROM "User"."birthday" ) = 2015', $this->Dbo->conditions(array('EXTRACT( \'YEAR\' FROM User.birthday )' => 2015)) ); } /** * Tests the syntax of generated schema indexes * * @return void */ public function testSchemaIndexSyntax() { $schema = new CakeSchema(); $schema->tables = array('i18n' => array( 'id' => array( 'type' => 'integer', 'null' => false, 'default' => null, 'length' => 10, 'key' => 'primary' ), 'locale' => array('type' => 'string', 'null' => false, 'length' => 6, 'key' => 'index'), 'model' => array('type' => 'string', 'null' => false, 'key' => 'index'), 'foreign_key' => array( 'type' => 'integer', 'null' => false, 'length' => 10, 'key' => 'index' ), 'field' => array('type' => 'string', 'null' => false, 'key' => 'index'), 'content' => array('type' => 'text', 'null' => true, 'default' => null), 'indexes' => array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'locale' => array('column' => 'locale', 'unique' => 0), 'model' => array('column' => 'model', 'unique' => 0), 'row_id' => array('column' => 'foreign_key', 'unique' => 0), 'field' => array('column' => 'field', 'unique' => 0) ) )); $result = $this->Dbo->createSchema($schema); $this->assertNotRegExp('/^CREATE INDEX(.+);,$/', $result); } /** * testCakeSchema method * * Test that schema generated postgresql queries are valid. ref #5696 * Check that the create statement for a schema generated table is the same as the original sql * * @return void */ public function testCakeSchema() { $db1 = ConnectionManager::getDataSource('test'); $db1->cacheSources = false; $db1->rawQuery('CREATE TABLE ' . $db1->fullTableName('datatype_tests') . ' ( id serial NOT NULL, "varchar" character varying(40) NOT NULL, "full_length" character varying NOT NULL, "huge_int" bigint NOT NULL, "timestamp" timestamp without time zone, "date" date, CONSTRAINT test_data_types_pkey PRIMARY KEY (id) )'); $schema = new CakeSchema(array('connection' => 'test')); $result = $schema->read(array( 'connection' => 'test', 'models' => array('DatatypeTest') )); $schema->tables = array( 'datatype_tests' => $result['tables']['missing']['datatype_tests'] ); $result = $db1->createSchema($schema, 'datatype_tests'); $this->assertNotRegExp('/timestamp DEFAULT/', $result); $this->assertRegExp('/\"full_length\"\s*text\s.*,/', $result); $this->assertContains('timestamp ,', $result); $this->assertContains('"huge_int" bigint NOT NULL,', $result); $db1->query('DROP TABLE ' . $db1->fullTableName('datatype_tests')); $db1->query($result); $result2 = $schema->read(array( 'connection' => 'test', 'models' => array('DatatypeTest') )); $schema->tables = array('datatype_tests' => $result2['tables']['missing']['datatype_tests']); $result2 = $db1->createSchema($schema, 'datatype_tests'); $this->assertEquals($result, $result2); $db1->query('DROP TABLE ' . $db1->fullTableName('datatype_tests')); } /** * testCakeSchemaBegserial method * * Test that schema generated postgresql queries are valid. * * @return void */ public function testCakeSchemaBigserial() { $db1 = ConnectionManager::getDataSource('test'); $db1->cacheSources = false; $db1->rawQuery('CREATE TABLE ' . $db1->fullTableName('bigserial_tests') . ' ( "id" bigserial NOT NULL, "varchar" character varying(40) NOT NULL, PRIMARY KEY ("id") )'); $schema = new CakeSchema(array('connection' => 'test')); $result = $schema->read(array( 'connection' => 'test', 'models' => array('BigserialTest') )); $schema->tables = array( 'bigserial_tests' => $result['tables']['missing']['bigserial_tests'] ); $result = $db1->createSchema($schema, 'bigserial_tests'); $this->assertContains('"id" bigserial NOT NULL,', $result); $db1->query('DROP TABLE ' . $db1->fullTableName('bigserial_tests')); } /** * Test index generation from table info. * * @return void */ public function testIndexGeneration() { $name = $this->Dbo->fullTableName('index_test', false, false); $this->Dbo->query('CREATE TABLE ' . $name . ' ("id" serial NOT NULL PRIMARY KEY, "bool" integer, "small_char" varchar(50), "description" varchar(40) )'); $this->Dbo->query('CREATE INDEX pointless_bool ON ' . $name . '("bool")'); $this->Dbo->query('CREATE UNIQUE INDEX char_index ON ' . $name . '("small_char")'); $expected = array( 'PRIMARY' => array('unique' => true, 'column' => 'id'), 'pointless_bool' => array('unique' => false, 'column' => 'bool'), 'char_index' => array('unique' => true, 'column' => 'small_char'), ); $result = $this->Dbo->index($name); $this->Dbo->query('DROP TABLE ' . $name); $this->assertEquals($expected, $result); $name = $this->Dbo->fullTableName('index_test_2', false, false); $this->Dbo->query('CREATE TABLE ' . $name . ' ("id" serial NOT NULL PRIMARY KEY, "bool" integer, "small_char" varchar(50), "description" varchar(40) )'); $this->Dbo->query('CREATE UNIQUE INDEX multi_col ON ' . $name . '("small_char", "bool")'); $expected = array( 'PRIMARY' => array('unique' => true, 'column' => 'id'), 'multi_col' => array('unique' => true, 'column' => array('small_char', 'bool')), ); $result = $this->Dbo->index($name); $this->Dbo->query('DROP TABLE ' . $name); $this->assertEquals($expected, $result); } /** * Test the alterSchema capabilities of postgres * * @return void */ public function testAlterSchema() { $Old = new CakeSchema(array( 'connection' => 'test', 'name' => 'AlterPosts', 'alter_posts' => array( 'id' => array('type' => 'integer', 'key' => 'primary'), 'author_id' => array('type' => 'integer', 'null' => false), 'title' => array('type' => 'string', 'null' => true), 'body' => array('type' => 'text'), 'published' => array('type' => 'string', 'length' => 1, 'default' => 'N'), 'created' => array('type' => 'datetime'), 'updated' => array('type' => 'datetime'), ) )); $this->Dbo->query($this->Dbo->createSchema($Old)); $New = new CakeSchema(array( 'connection' => 'test', 'name' => 'AlterPosts', 'alter_posts' => array( 'id' => array('type' => 'integer', 'key' => 'primary'), 'author_id' => array('type' => 'integer', 'null' => true), 'title' => array('type' => 'string', 'null' => false, 'default' => 'my title'), 'body' => array('type' => 'string', 'length' => 500), 'status' => array('type' => 'integer', 'length' => 3, 'default' => 1), 'created' => array('type' => 'datetime'), 'updated' => array('type' => 'datetime'), ) )); $this->Dbo->query($this->Dbo->alterSchema($New->compare($Old), 'alter_posts')); $model = new CakeTestModel(array('table' => 'alter_posts', 'ds' => 'test')); $result = $model->schema(); $this->assertTrue(isset($result['status'])); $this->assertFalse(isset($result['published'])); $this->assertEquals('string', $result['body']['type']); $this->assertEquals(1, $result['status']['default']); $this->assertEquals(true, $result['author_id']['null']); $this->assertEquals(false, $result['title']['null']); $this->Dbo->query($this->Dbo->dropSchema($New)); $New = new CakeSchema(array( 'connection' => 'test_suite', 'name' => 'AlterPosts', 'alter_posts' => array( 'id' => array('type' => 'string', 'length' => 36, 'key' => 'primary'), 'author_id' => array('type' => 'integer', 'null' => false), 'title' => array('type' => 'string', 'null' => true), 'body' => array('type' => 'text'), 'published' => array('type' => 'string', 'length' => 1, 'default' => 'N'), 'created' => array('type' => 'datetime'), 'updated' => array('type' => 'datetime'), ) )); $result = $this->Dbo->alterSchema($New->compare($Old), 'alter_posts'); $this->assertNotRegExp('/varchar\(36\) NOT NULL/i', $result); } /** * Test the alterSchema changing boolean to integer * * @return void */ public function testAlterSchemaBooleanToIntegerField() { $default = array( 'connection' => 'test', 'name' => 'BoolField', 'bool_fields' => array( 'id' => array('type' => 'integer', 'key' => 'primary'), 'name' => array('type' => 'string', 'length' => 50), 'active' => array('type' => 'boolean', 'null' => false), ) ); $Old = new CakeSchema($default); $result = $this->Dbo->query($this->Dbo->createSchema($Old)); $this->assertTrue($result); $modified = $default; $modified['bool_fields']['active'] = array('type' => 'integer', 'null' => true); $New = new CakeSchema($modified); $query = $this->Dbo->alterSchema($New->compare($Old)); $result = $this->Dbo->query($query); $this->Dbo->query($this->Dbo->dropSchema($Old)); } /** * Test the alterSchema changing text to integer * * @return void */ public function testAlterSchemaTextToIntegerField() { $default = array( 'connection' => 'test', 'name' => 'TextField', 'text_fields' => array( 'id' => array('type' => 'integer', 'key' => 'primary'), 'name' => array('type' => 'string', 'length' => 50), 'active' => array('type' => 'text', 'null' => false), ) ); $Old = new CakeSchema($default); $result = $this->Dbo->query($this->Dbo->createSchema($Old)); $this->assertTrue($result); $modified = $default; $modified['text_fields']['active'] = array('type' => 'integer', 'null' => true); $New = new CakeSchema($modified); $this->Dbo->query($this->Dbo->alterSchema($New->compare($Old))); $result = $this->Dbo->describe('text_fields'); $this->Dbo->query($this->Dbo->dropSchema($Old)); $expected = array( 'type' => 'integer', 'null' => true, 'default' => null, 'length' => null, ); $this->assertEquals($expected, $result['active']); } /** * Test the alter index capabilities of postgres * * @return void */ public function testAlterIndexes() { $this->Dbo->cacheSources = false; $schema1 = new CakeSchema(array( 'name' => 'AlterTest1', 'connection' => 'test', 'altertest' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'name' => array('type' => 'string', 'null' => false, 'length' => 50), 'group1' => array('type' => 'integer', 'null' => true), 'group2' => array('type' => 'integer', 'null' => true) ) )); $this->Dbo->rawQuery($this->Dbo->createSchema($schema1)); $schema2 = new CakeSchema(array( 'name' => 'AlterTest2', 'connection' => 'test', 'altertest' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'name' => array('type' => 'string', 'null' => false, 'length' => 50), 'group1' => array('type' => 'integer', 'null' => true), 'group2' => array('type' => 'integer', 'null' => true), 'indexes' => array( 'name_idx' => array('unique' => false, 'column' => 'name'), 'group_idx' => array('unique' => false, 'column' => 'group1'), 'compound_idx' => array('unique' => false, 'column' => array('group1', 'group2')), 'PRIMARY' => array('unique' => true, 'column' => 'id') ) ) )); $this->Dbo->query($this->Dbo->alterSchema($schema2->compare($schema1))); $indexes = $this->Dbo->index('altertest'); $this->assertEquals($schema2->tables['altertest']['indexes'], $indexes); // Change three indexes, delete one and add another one $schema3 = new CakeSchema(array( 'name' => 'AlterTest3', 'connection' => 'test', 'altertest' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'name' => array('type' => 'string', 'null' => false, 'length' => 50), 'group1' => array('type' => 'integer', 'null' => true), 'group2' => array('type' => 'integer', 'null' => true), 'indexes' => array( 'name_idx' => array('unique' => true, 'column' => 'name'), 'group_idx' => array('unique' => false, 'column' => 'group2'), 'compound_idx' => array('unique' => false, 'column' => array('group2', 'group1')), 'another_idx' => array('unique' => false, 'column' => array('group1', 'name'))) ))); $this->Dbo->query($this->Dbo->alterSchema($schema3->compare($schema2))); $indexes = $this->Dbo->index('altertest'); $this->assertEquals($schema3->tables['altertest']['indexes'], $indexes); // Compare us to ourself. $this->assertEquals(array(), $schema3->compare($schema3)); // Drop the indexes $this->Dbo->query($this->Dbo->alterSchema($schema1->compare($schema3))); $indexes = $this->Dbo->index('altertest'); $this->assertEquals(array(), $indexes); $this->Dbo->query($this->Dbo->dropSchema($schema1)); } /** * Test the alterSchema RENAME statements * * @return void */ public function testAlterSchemaRenameTo() { $query = $this->Dbo->alterSchema(array( 'posts' => array( 'change' => array( 'title' => array('name' => 'subject', 'type' => 'string', 'null' => false) ) ) )); $this->assertContains('RENAME "title" TO "subject";', $query); $this->assertContains('ALTER COLUMN "subject" TYPE', $query); $this->assertNotContains(";\n\tALTER COLUMN \"subject\" TYPE", $query); $this->assertNotContains('ALTER COLUMN "title" TYPE "subject"', $query); } /** * Test it is possible to use virtual field with postgresql * * @return void */ public function testVirtualFields() { $this->loadFixtures('Article', 'Comment', 'User', 'Attachment', 'Tag', 'ArticlesTag'); $Article = new Article; $Article->virtualFields = array( 'next_id' => 'Article.id + 1', 'complex' => 'Article.title || Article.body', 'functional' => 'COALESCE(User.user, Article.title)', 'subquery' => 'SELECT count(*) FROM ' . $Article->Comment->table ); $result = $Article->find('first'); $this->assertEquals(2, $result['Article']['next_id']); $this->assertEquals($result['Article']['complex'], $result['Article']['title'] . $result['Article']['body']); $this->assertEquals($result['Article']['functional'], $result['User']['user']); $this->assertEquals(6, $result['Article']['subquery']); } /** * Test that virtual fields work with SQL constants * * @return void */ public function testVirtualFieldAsAConstant() { $this->loadFixtures('Article', 'Comment'); $Article = ClassRegistry::init('Article'); $Article->virtualFields = array( 'empty' => "NULL", 'number' => 43, 'truth' => 'TRUE' ); $result = $Article->find('first'); $this->assertNull($result['Article']['empty']); $this->assertTrue($result['Article']['truth']); $this->assertEquals(43, $result['Article']['number']); } /** * Tests additional order options for postgres * * @return void */ public function testOrderAdditionalParams() { $result = $this->Dbo->order(array('title' => 'DESC NULLS FIRST', 'body' => 'DESC')); $expected = ' ORDER BY "title" DESC NULLS FIRST, "body" DESC'; $this->assertEquals($expected, $result); } /** * Test it is possible to do a SELECT COUNT(DISTINCT Model.field) * query in postgres and it gets correctly quoted * * @return void */ public function testQuoteDistinctInFunction() { $this->loadFixtures('Article'); $Article = new Article; $result = $this->Dbo->fields($Article, null, array('COUNT(DISTINCT Article.id)')); $expected = array('COUNT(DISTINCT "Article"."id")'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($Article, null, array('COUNT(DISTINCT id)')); $expected = array('COUNT(DISTINCT "id")'); $this->assertEquals($expected, $result); $result = $this->Dbo->fields($Article, null, array('COUNT(DISTINCT FUNC(id))')); $expected = array('COUNT(DISTINCT FUNC("id"))'); $this->assertEquals($expected, $result); } /** * test that saveAll works even with conditions that lack a model name. * * @return void */ public function testUpdateAllWithNonQualifiedConditions() { $this->loadFixtures('Article'); $Article = new Article(); $result = $Article->updateAll(array('title' => "'Awesome'"), array('title' => 'Third Article')); $this->assertTrue($result); $result = $Article->find('count', array( 'conditions' => array('Article.title' => 'Awesome') )); $this->assertEquals(1, $result, 'Article count is wrong or fixture has changed.'); } /** * test alterSchema on two tables. * * @return void */ public function testAlteringTwoTables() { $schema1 = new CakeSchema(array( 'name' => 'AlterTest1', 'connection' => 'test', 'altertest' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'name' => array('type' => 'string', 'null' => false, 'length' => 50), ), 'other_table' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'name' => array('type' => 'string', 'null' => false, 'length' => 50), ) )); $schema2 = new CakeSchema(array( 'name' => 'AlterTest1', 'connection' => 'test', 'altertest' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'field_two' => array('type' => 'string', 'null' => false, 'length' => 50), ), 'other_table' => array( 'id' => array('type' => 'integer', 'null' => false, 'default' => 0), 'field_two' => array('type' => 'string', 'null' => false, 'length' => 50), ) )); $result = $this->db->alterSchema($schema2->compare($schema1)); $this->assertEquals(2, substr_count($result, 'field_two'), 'Too many fields'); $this->assertFalse(strpos(';ALTER', $result), 'Too many semi colons'); } /** * test encoding setting. * * @return void */ public function testEncoding() { $result = $this->Dbo->setEncoding('UTF8'); $this->assertTrue($result); $result = $this->Dbo->getEncoding(); $this->assertEquals('UTF8', $result); $result = $this->Dbo->setEncoding('EUC_JP'); /* 'EUC_JP' is right character code name in PostgreSQL */ $this->assertTrue($result); $result = $this->Dbo->getEncoding(); $this->assertEquals('EUC_JP', $result); } /** * Test truncate with a mock. * * @return void */ public function testTruncateStatements() { $this->loadFixtures('Article', 'User'); $db = ConnectionManager::getDatasource('test'); $schema = $db->config['schema']; $Article = new Article(); $this->Dbo = $this->getMock('Postgres', array('execute'), array($db->config)); $this->Dbo->expects($this->at(0))->method('execute') ->with("DELETE FROM \"$schema\".\"articles\""); $this->Dbo->truncate($Article); $this->Dbo->expects($this->at(0))->method('execute') ->with("DELETE FROM \"$schema\".\"articles\""); $this->Dbo->truncate('articles'); // #2355: prevent duplicate prefix $this->Dbo->config['prefix'] = 'tbl_'; $Article->tablePrefix = 'tbl_'; $this->Dbo->expects($this->at(0))->method('execute') ->with("DELETE FROM \"$schema\".\"tbl_articles\""); $this->Dbo->truncate($Article); $this->Dbo->expects($this->at(0))->method('execute') ->with("DELETE FROM \"$schema\".\"tbl_articles\""); $this->Dbo->truncate('articles'); } /** * Test nested transaction * * @return void */ public function testNestedTransaction() { $this->Dbo->useNestedTransactions = true; $this->skipIf($this->Dbo->nestedTransactionSupported() === false, 'The Postgres server do not support nested transaction'); $this->loadFixtures('Article'); $model = new Article(); $model->hasOne = $model->hasMany = $model->belongsTo = $model->hasAndBelongsToMany = array(); $model->cacheQueries = false; $this->Dbo->cacheMethods = false; $this->assertTrue($this->Dbo->begin()); $this->assertNotEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->begin()); $this->assertTrue($model->delete(1)); $this->assertEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->rollback()); $this->assertNotEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->begin()); $this->assertTrue($model->delete(1)); $this->assertEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->commit()); $this->assertEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->rollback()); $this->assertNotEmpty($model->read(null, 1)); } public function testResetSequence() { $model = new Article(); $table = $this->Dbo->fullTableName($model, false); $fields = array( 'id', 'user_id', 'title', 'body', 'published', ); $values = array( array(1, 1, 'test', 'first post', false), array(2, 1, 'test 2', 'second post post', false), ); $this->Dbo->insertMulti($table, $fields, $values); $sequence = $this->Dbo->getSequence($table); $result = $this->Dbo->rawQuery("SELECT nextval('$sequence')"); $original = $result->fetch(PDO::FETCH_ASSOC); $this->assertTrue($this->Dbo->resetSequence($table, 'id')); $result = $this->Dbo->rawQuery("SELECT currval('$sequence')"); $new = $result->fetch(PDO::FETCH_ASSOC); $this->assertTrue($new['currval'] > $original['nextval'], 'Sequence did not update'); } public function testSettings() { Configure::write('Cache.disable', true); $this->Dbo = ConnectionManager::getDataSource('test'); $this->skipIf(!($this->Dbo instanceof Postgres)); $config2 = $this->Dbo->config; $config2['settings']['datestyle'] = 'sql, dmy'; ConnectionManager::create('test2', $config2); $dbo2 = new Postgres($config2, true); $expected = array(array('r' => date('d/m/Y'))); $r = $dbo2->fetchRow('SELECT now()::date AS "r"'); $this->assertEquals($expected, $r); $dbo2->execute('SET DATESTYLE TO ISO'); $dbo2->disconnect(); } /** * Test the limit function. * * @return void */ public function testLimit() { $db = $this->Dbo; $result = $db->limit('0'); $this->assertNull($result); $result = $db->limit('10'); $this->assertEquals(' LIMIT 10', $result); $result = $db->limit('FARTS', 'BOOGERS'); $this->assertEquals(' LIMIT 0 OFFSET 0', $result); $result = $db->limit(20, 10); $this->assertEquals(' LIMIT 20 OFFSET 10', $result); $result = $db->limit(10, 300000000000000000000000000000); $scientificNotation = sprintf('%.1E', 300000000000000000000000000000); $this->assertNotContains($scientificNotation, $result); } /** * Test that postgres describes UUID columns correctly. * * @return void */ public function testDescribeUuid() { $db = $this->Dbo; $db->execute('CREATE TABLE test_uuid_describe (id UUID PRIMARY KEY, name VARCHAR(255))'); $data = $db->describe('test_uuid_describe'); $expected = array( 'type' => 'string', 'null' => false, 'default' => null, 'length' => 36, ); $this->assertSame($expected, $data['id']); $db->execute('DROP TABLE test_uuid_describe'); } /** * Test describe() behavior for timestamp columns. * * @return void */ public function testDescribeTimestamp() { $this->loadFixtures('User'); $model = ClassRegistry::init('User'); $result = $this->Dbo->describe($model); $expected = array( 'id' => array( 'type' => 'integer', 'null' => false, 'default' => null, 'length' => 11, 'key' => 'primary' ), 'user' => array( 'type' => 'string', 'null' => true, 'default' => null, 'length' => 255 ), 'password' => array( 'type' => 'string', 'null' => true, 'default' => null, 'length' => 255 ), 'created' => array( 'type' => 'datetime', 'null' => true, 'default' => null, 'length' => null ), 'updated' => array( 'type' => 'datetime', 'null' => true, 'default' => null, 'length' => null ) ); $this->assertEquals($expected, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Datasource/Database/SqliteTest.php000066400000000000000000000355321265552240500260250ustar00rootroot00000000000000simulated[] = $sql; return null; } /** * getLastQuery method * * @return void */ public function getLastQuery() { return $this->simulated[count($this->simulated) - 1]; } } /** * DboSqliteTest class * * @package Cake.Test.Case.Model.Datasource.Database */ class SqliteTest extends CakeTestCase { /** * Do not automatically load fixtures for each test, they will be loaded manually using CakeTestCase::loadFixtures * * @var bool */ public $autoFixtures = false; /** * Fixtures * * @var object */ public $fixtures = array('core.user', 'core.uuid', 'core.datatype'); /** * Actual DB connection used in testing * * @var DboSource */ public $Dbo = null; /** * Sets up a Dbo class instance for testing * * @return void */ public function setUp() { parent::setUp(); Configure::write('Cache.disable', true); $this->Dbo = ConnectionManager::getDataSource('test'); if (!$this->Dbo instanceof Sqlite) { $this->markTestSkipped('The Sqlite extension is not available.'); } } /** * Sets up a Dbo class instance for testing * * @return void */ public function tearDown() { parent::tearDown(); Configure::write('Cache.disable', false); } /** * Tests that SELECT queries from DboSqlite::listSources() are not cached * * @return void */ public function testTableListCacheDisabling() { $this->assertFalse(in_array('foo_test', $this->Dbo->listSources())); $this->Dbo->query('CREATE TABLE foo_test (test VARCHAR(255))'); $this->assertTrue(in_array('foo_test', $this->Dbo->listSources())); $this->Dbo->cacheSources = false; $this->Dbo->query('DROP TABLE foo_test'); $this->assertFalse(in_array('foo_test', $this->Dbo->listSources())); } /** * test Index introspection. * * @return void */ public function testIndex() { $name = $this->Dbo->fullTableName('with_a_key', false, false); $this->Dbo->query('CREATE TABLE ' . $name . ' ("id" int(11) PRIMARY KEY, "bool" int(1), "small_char" varchar(50), "description" varchar(40) );'); $this->Dbo->query('CREATE INDEX pointless_bool ON ' . $name . '("bool")'); $this->Dbo->query('CREATE UNIQUE INDEX char_index ON ' . $name . '("small_char")'); $expected = array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'pointless_bool' => array('column' => 'bool', 'unique' => 0), 'char_index' => array('column' => 'small_char', 'unique' => 1), ); $result = $this->Dbo->index($name); $this->assertEquals($expected, $result); $this->Dbo->query('DROP TABLE ' . $name); $this->Dbo->query('CREATE TABLE ' . $name . ' ("id" int(11) PRIMARY KEY, "bool" int(1), "small_char" varchar(50), "description" varchar(40) );'); $this->Dbo->query('CREATE UNIQUE INDEX multi_col ON ' . $name . '("small_char", "bool")'); $expected = array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'multi_col' => array('column' => array('small_char', 'bool'), 'unique' => 1), ); $result = $this->Dbo->index($name); $this->assertEquals($expected, $result); $this->Dbo->query('DROP TABLE ' . $name); } /** * Tests that cached table descriptions are saved under the sanitized key name * * @return void */ public function testCacheKeyName() { Configure::write('Cache.disable', false); $dbName = 'db' . rand() . '$(*%&).db'; $this->assertFalse(file_exists(TMP . $dbName)); $db = new Sqlite(array_merge($this->Dbo->config, array('database' => TMP . $dbName))); $this->assertTrue(file_exists(TMP . $dbName)); $db->execute("CREATE TABLE test_list (id VARCHAR(255));"); $db->cacheSources = true; $this->assertEquals(array('test_list'), $db->listSources()); $db->cacheSources = false; $fileName = '_' . preg_replace('/[^A-Za-z0-9_\-+]/', '_', TMP . $dbName) . '_list'; $result = Cache::read($fileName, '_cake_model_'); $this->assertEquals(array('test_list'), $result); Cache::delete($fileName, '_cake_model_'); Configure::write('Cache.disable', true); } /** * test building columns with SQLite * * @return void */ public function testBuildColumn() { $data = array( 'name' => 'int_field', 'type' => 'integer', 'null' => false, ); $result = $this->Dbo->buildColumn($data); $expected = '"int_field" integer NOT NULL'; $this->assertEquals($expected, $result); $data = array( 'name' => 'name', 'type' => 'string', 'length' => 20, 'null' => false, ); $result = $this->Dbo->buildColumn($data); $expected = '"name" varchar(20) NOT NULL'; $this->assertEquals($expected, $result); $data = array( 'name' => 'testName', 'type' => 'string', 'length' => 20, 'default' => null, 'null' => true, 'collate' => 'NOCASE' ); $result = $this->Dbo->buildColumn($data); $expected = '"testName" varchar(20) DEFAULT NULL COLLATE NOCASE'; $this->assertEquals($expected, $result); $data = array( 'name' => 'testName', 'type' => 'string', 'length' => 20, 'default' => 'test-value', 'null' => false, ); $result = $this->Dbo->buildColumn($data); $expected = '"testName" varchar(20) DEFAULT \'test-value\' NOT NULL'; $this->assertEquals($expected, $result); $data = array( 'name' => 'testName', 'type' => 'integer', 'length' => 10, 'default' => 10, 'null' => false, ); $result = $this->Dbo->buildColumn($data); $expected = '"testName" integer(10) DEFAULT 10 NOT NULL'; $this->assertEquals($expected, $result); $data = array( 'name' => 'testName', 'type' => 'integer', 'length' => 10, 'default' => 10, 'null' => false, 'collate' => 'BADVALUE' ); $result = $this->Dbo->buildColumn($data); $expected = '"testName" integer(10) DEFAULT 10 NOT NULL'; $this->assertEquals($expected, $result); $data = array( 'name' => 'huge', 'type' => 'biginteger', 'length' => 20, 'null' => false, ); $result = $this->Dbo->buildColumn($data); $expected = '"huge" bigint(20) NOT NULL'; $this->assertEquals($expected, $result); $data = array( 'name' => 'id', 'type' => 'biginteger', 'length' => 20, 'null' => false, 'key' => 'primary', ); $result = $this->Dbo->buildColumn($data); $expected = '"id" bigint(20) NOT NULL PRIMARY KEY'; $this->assertEquals($expected, $result); } /** * test describe() and normal results. * * @return void */ public function testDescribe() { $this->loadFixtures('User'); $Model = new Model(array( 'name' => 'User', 'ds' => 'test', 'table' => 'users' )); $this->Dbo->cacheSources = true; Configure::write('Cache.disable', false); $result = $this->Dbo->describe($Model); $expected = array( 'id' => array( 'type' => 'integer', 'key' => 'primary', 'null' => false, 'default' => null, 'length' => 11 ), 'user' => array( 'type' => 'string', 'length' => 255, 'null' => true, 'default' => null ), 'password' => array( 'type' => 'string', 'length' => 255, 'null' => true, 'default' => null ), 'created' => array( 'type' => 'datetime', 'null' => true, 'default' => null, 'length' => null, ), 'updated' => array( 'type' => 'datetime', 'null' => true, 'default' => null, 'length' => null, ) ); $this->assertEquals($expected, $result); $result = $this->Dbo->describe($Model->useTable); $this->assertEquals($expected, $result); $result = Cache::read('test_users', '_cake_model_'); $this->assertEquals($expected, $result); } /** * Test that datatypes are reflected * * @return void */ public function testDatatypes() { $this->loadFixtures('Datatype'); $Model = new Model(array( 'name' => 'Datatype', 'ds' => 'test', 'table' => 'datatypes' )); $result = $this->Dbo->describe($Model); $expected = array( 'id' => array( 'type' => 'integer', 'null' => false, 'default' => '', 'length' => 11, 'key' => 'primary', ), 'float_field' => array( 'type' => 'float', 'null' => false, 'default' => '', 'length' => '5,2', ), 'decimal_field' => array( 'type' => 'decimal', 'null' => true, 'default' => '0.000', 'length' => '6,3', ), 'huge_int' => array( 'type' => 'biginteger', 'null' => true, 'default' => null, 'length' => 20, ), 'bool' => array( 'type' => 'boolean', 'null' => false, 'default' => '0', 'length' => null ), ); $this->assertSame($expected, $result); } /** * test that describe does not corrupt UUID primary keys * * @return void */ public function testDescribeWithUuidPrimaryKey() { $tableName = 'uuid_tests'; $this->Dbo->query("CREATE TABLE {$tableName} (id VARCHAR(36) PRIMARY KEY, name VARCHAR, created DATETIME, modified DATETIME)"); $Model = new Model(array('name' => 'UuidTest', 'ds' => 'test', 'table' => 'uuid_tests')); $result = $this->Dbo->describe($Model); $expected = array( 'type' => 'string', 'length' => 36, 'null' => false, 'default' => null, 'key' => 'primary', ); $this->assertEquals($expected, $result['id']); $this->Dbo->query('DROP TABLE ' . $tableName); $tableName = 'uuid_tests'; $this->Dbo->query("CREATE TABLE {$tableName} (id CHAR(36) PRIMARY KEY, name VARCHAR, created DATETIME, modified DATETIME)"); $Model = new Model(array('name' => 'UuidTest', 'ds' => 'test', 'table' => 'uuid_tests')); $result = $this->Dbo->describe($Model); $expected = array( 'type' => 'string', 'length' => 36, 'null' => false, 'default' => null, 'key' => 'primary', ); $this->assertEquals($expected, $result['id']); $this->Dbo->query('DROP TABLE ' . $tableName); } /** * Test virtualFields with functions. * * @return void */ public function testVirtualFieldWithFunction() { $this->loadFixtures('User'); $User = ClassRegistry::init('User'); $User->virtualFields = array('name' => 'SUBSTR(User.user, 5, LENGTH(User.user) - 4)'); $result = $User->find('first', array( 'conditions' => array('User.user' => 'garrett') )); $this->assertEquals('ett', $result['User']['name']); } /** * Test that records can be inserted with UUID primary keys, and * that the primary key is not blank * * @return void */ public function testUuidPrimaryKeyInsertion() { $this->loadFixtures('Uuid'); $Model = ClassRegistry::init('Uuid'); $data = array( 'title' => 'A UUID should work', 'count' => 10 ); $Model->create($data); $this->assertTrue((bool)$Model->save()); $result = $Model->read(); $this->assertEquals($data['title'], $result['Uuid']['title']); $this->assertTrue(Validation::uuid($result['Uuid']['id']), 'Not a UUID'); } /** * Test nested transaction * * @return void */ public function testNestedTransaction() { $this->skipIf($this->Dbo->nestedTransactionSupported() === false, 'The Sqlite version do not support nested transaction'); $this->loadFixtures('User'); $model = new User(); $model->hasOne = $model->hasMany = $model->belongsTo = $model->hasAndBelongsToMany = array(); $model->cacheQueries = false; $this->Dbo->cacheMethods = false; $this->assertTrue($this->Dbo->begin()); $this->assertNotEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->begin()); $this->assertTrue($model->delete(1)); $this->assertEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->rollback()); $this->assertNotEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->begin()); $this->assertTrue($model->delete(1)); $this->assertEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->commit()); $this->assertEmpty($model->read(null, 1)); $this->assertTrue($this->Dbo->rollback()); $this->assertNotEmpty($model->read(null, 1)); } /** * Test the limit function. * * @return void */ public function testLimit() { $db = $this->Dbo; $result = $db->limit('0'); $this->assertNull($result); $result = $db->limit('10'); $this->assertEquals(' LIMIT 10', $result); $result = $db->limit('FARTS', 'BOOGERS'); $this->assertEquals(' LIMIT 0 OFFSET 0', $result); $result = $db->limit(20, 10); $this->assertEquals(' LIMIT 20 OFFSET 10', $result); $result = $db->limit(10, 300000000000000000000000000000); $scientificNotation = sprintf('%.1E', 300000000000000000000000000000); $this->assertNotContains($scientificNotation, $result); } /** * Test that fields are parsed out in a reasonable fashion. * * @return void */ public function testFetchRowColumnParsing() { $this->loadFixtures('User'); $sql = 'SELECT "User"."id", "User"."user", "User"."password", "User"."created", (1 + 1) AS "two" ' . 'FROM "users" AS "User" WHERE ' . '"User"."id" IN (SELECT MAX("id") FROM "users") ' . 'OR "User.id" IN (5, 6, 7, 8)'; $result = $this->Dbo->fetchRow($sql); $expected = array( 'User' => array( 'id' => 4, 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23' ), 0 => array( 'two' => 2 ) ); $this->assertEquals($expected, $result); $sql = 'SELECT "User"."id", "User"."user" ' . 'FROM "users" AS "User" WHERE "User"."id" = 4 ' . 'UNION ' . 'SELECT "User"."id", "User"."user" ' . 'FROM "users" AS "User" WHERE "User"."id" = 3'; $result = $this->Dbo->fetchRow($sql); $expected = array( 'User' => array( 'id' => 3, 'user' => 'larry', ), ); $this->assertEquals($expected, $result); } /** * Test parsing more complex field names. * * @return void */ public function testFetchColumnRowParsingMoreComplex() { $this->loadFixtures('User'); $sql = 'SELECT COUNT(*) AS User__count, COUNT(CASE id WHEN 2 THEN 1 ELSE NULL END) as User__case, AVG(CAST("User"."id" AS BIGINT)) AS User__bigint FROM "users" AS "User" WHERE "User"."id" > 0'; $result = $this->Dbo->fetchRow($sql); $expected = array( '0' => array( 'User__count' => '4', 'User__case' => '1', 'User__bigint' => '2.5', ), ); $this->assertEquals($expected, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Datasource/Database/SqlserverTest.php000066400000000000000000000465251265552240500265560ustar00rootroot00000000000000simulated[] = $sql; return empty($this->executeResultsStack) ? null : array_pop($this->executeResultsStack); } /** * fetchAll method * * @param mixed $sql * @return void */ protected function _matchRecords(Model $model, $conditions = null) { return $this->conditions(array('id' => array(1, 2))); } /** * getLastQuery method * * @return string */ public function getLastQuery() { return $this->simulated[count($this->simulated) - 1]; } /** * getPrimaryKey method * * @param mixed $model * @return string */ public function getPrimaryKey($model) { return parent::_getPrimaryKey($model); } /** * clearFieldMappings method * * @return void */ public function clearFieldMappings() { $this->_fieldMappings = array(); } /** * describe method * * @param object $model * @return void */ public function describe($model) { return empty($this->describe) ? parent::describe($model) : $this->describe; } } /** * SqlserverTestModel class * * @package Cake.Test.Case.Model.Datasource.Database */ class SqlserverTestModel extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; /** * _schema property * * @var array */ protected $_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8', 'key' => 'primary'), 'client_id' => array('type' => 'integer', 'null' => '', 'default' => '0', 'length' => '11'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'login' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'passwd' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'), 'addr_1' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'), 'addr_2' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '25'), 'zip_code' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'city' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'country' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'phone' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'fax' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'url' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'), 'email' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'comments' => array('type' => 'text', 'null' => '1', 'default' => '', 'length' => ''), 'last_login' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => ''), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); /** * belongsTo property * * @var array */ public $belongsTo = array( 'SqlserverClientTestModel' => array( 'foreignKey' => 'client_id' ) ); /** * find method * * @param mixed $conditions * @param mixed $fields * @param mixed $order * @param mixed $recursive * @return void */ public function find($conditions = null, $fields = null, $order = null, $recursive = null) { return $conditions; } } /** * SqlserverClientTestModel class * * @package Cake.Test.Case.Model.Datasource.Database */ class SqlserverClientTestModel extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; /** * _schema property * * @var array */ protected $_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8', 'key' => 'primary'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'email' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'created' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); } /** * SqlserverTestResultIterator class * * @package Cake.Test.Case.Model.Datasource.Database */ class SqlserverTestResultIterator extends ArrayIterator { /** * closeCursor method * * @return void */ public function closeCursor() { } /** * fetch method * * @return void */ public function fetch() { if (!$this->valid()) { return null; } $current = $this->current(); $this->next(); return $current; } } /** * SqlserverTest class * * @package Cake.Test.Case.Model.Datasource.Database */ class SqlserverTest extends CakeTestCase { /** * The Dbo instance to be tested * * @var DboSource */ public $db = null; /** * autoFixtures property * * @var bool */ public $autoFixtures = false; /** * fixtures property * * @var array */ public $fixtures = array('core.user', 'core.category', 'core.author', 'core.post'); /** * Sets up a Dbo class instance for testing * * @return void */ public function setUp() { parent::setUp(); $this->Dbo = ConnectionManager::getDataSource('test'); if (!($this->Dbo instanceof Sqlserver)) { $this->markTestSkipped('Please configure the test datasource to use SQL Server.'); } $this->db = new SqlserverTestDb($this->Dbo->config); $this->model = new SqlserverTestModel(); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Dbo); unset($this->model); } /** * testQuoting method * * @return void */ public function testQuoting() { $expected = "1.2"; $result = $this->db->value(1.2, 'float'); $this->assertSame($expected, $result); $expected = "'1,2'"; $result = $this->db->value('1,2', 'float'); $this->assertSame($expected, $result); $expected = 'NULL'; $result = $this->db->value('', 'integer'); $this->assertSame($expected, $result); $expected = 'NULL'; $result = $this->db->value('', 'float'); $this->assertSame($expected, $result); $expected = "''"; $result = $this->db->value('', 'binary'); $this->assertSame($expected, $result); $expected = 'NULL'; $result = $this->db->value(null, 'string'); $this->assertSame($expected, $result); } /** * testFields method * * @return void */ public function testFields() { $fields = array( '[SqlserverTestModel].[id] AS [SqlserverTestModel__id]', '[SqlserverTestModel].[client_id] AS [SqlserverTestModel__client_id]', '[SqlserverTestModel].[name] AS [SqlserverTestModel__name]', '[SqlserverTestModel].[login] AS [SqlserverTestModel__login]', '[SqlserverTestModel].[passwd] AS [SqlserverTestModel__passwd]', '[SqlserverTestModel].[addr_1] AS [SqlserverTestModel__addr_1]', '[SqlserverTestModel].[addr_2] AS [SqlserverTestModel__addr_2]', '[SqlserverTestModel].[zip_code] AS [SqlserverTestModel__zip_code]', '[SqlserverTestModel].[city] AS [SqlserverTestModel__city]', '[SqlserverTestModel].[country] AS [SqlserverTestModel__country]', '[SqlserverTestModel].[phone] AS [SqlserverTestModel__phone]', '[SqlserverTestModel].[fax] AS [SqlserverTestModel__fax]', '[SqlserverTestModel].[url] AS [SqlserverTestModel__url]', '[SqlserverTestModel].[email] AS [SqlserverTestModel__email]', '[SqlserverTestModel].[comments] AS [SqlserverTestModel__comments]', 'CONVERT(VARCHAR(20), [SqlserverTestModel].[last_login], 20) AS [SqlserverTestModel__last_login]', '[SqlserverTestModel].[created] AS [SqlserverTestModel__created]', 'CONVERT(VARCHAR(20), [SqlserverTestModel].[updated], 20) AS [SqlserverTestModel__updated]' ); $result = $this->db->fields($this->model); $expected = $fields; $this->assertEquals($expected, $result); $this->db->clearFieldMappings(); $result = $this->db->fields($this->model, null, 'SqlserverTestModel.*'); $expected = $fields; $this->assertEquals($expected, $result); $this->db->clearFieldMappings(); $result = $this->db->fields($this->model, null, array('*', 'AnotherModel.id', 'AnotherModel.name')); $expected = array_merge($fields, array( '[AnotherModel].[id] AS [AnotherModel__id]', '[AnotherModel].[name] AS [AnotherModel__name]')); $this->assertEquals($expected, $result); $this->db->clearFieldMappings(); $result = $this->db->fields($this->model, null, array('*', 'SqlserverClientTestModel.*')); $expected = array_merge($fields, array( '[SqlserverClientTestModel].[id] AS [SqlserverClientTestModel__id]', '[SqlserverClientTestModel].[name] AS [SqlserverClientTestModel__name]', '[SqlserverClientTestModel].[email] AS [SqlserverClientTestModel__email]', 'CONVERT(VARCHAR(20), [SqlserverClientTestModel].[created], 20) AS [SqlserverClientTestModel__created]', 'CONVERT(VARCHAR(20), [SqlserverClientTestModel].[updated], 20) AS [SqlserverClientTestModel__updated]')); $this->assertEquals($expected, $result); } /** * testDistinctFields method * * @return void */ public function testDistinctFields() { $result = $this->db->fields($this->model, null, array('DISTINCT Car.country_code')); $expected = array('DISTINCT [Car].[country_code] AS [Car__country_code]'); $this->assertEquals($expected, $result); $result = $this->db->fields($this->model, null, 'DISTINCT Car.country_code'); $expected = array('DISTINCT [Car].[country_code] AS [Car__country_code]'); $this->assertEquals($expected, $result); } /** * testDistinctWithLimit method * * @return void */ public function testDistinctWithLimit() { $this->db->read($this->model, array( 'fields' => array('DISTINCT SqlserverTestModel.city', 'SqlserverTestModel.country'), 'limit' => 5 )); $result = $this->db->getLastQuery(); $this->assertRegExp('/^SELECT DISTINCT TOP 5/', $result); } /** * testDescribe method * * @return void */ public function testDescribe() { $SqlserverTableDescription = new SqlserverTestResultIterator(array( (object)array( 'Default' => '((0))', 'Field' => 'count', 'Key' => 0, 'Length' => '4', 'Null' => 'NO', 'Type' => 'integer' ), (object)array( 'Default' => '', 'Field' => 'body', 'Key' => 0, 'Length' => '-1', 'Null' => 'YES', 'Type' => 'nvarchar' ), (object)array( 'Default' => '', 'Field' => 'published', 'Key' => 0, 'Type' => 'datetime2', 'Length' => 8, 'Null' => 'YES', 'Size' => '' ), (object)array( 'Default' => '', 'Field' => 'id', 'Key' => 1, 'Type' => 'nchar', 'Length' => 72, 'Null' => 'NO', 'Size' => '' ), (object)array( 'Default' => null, 'Field' => 'parent_id', 'Key' => '0', 'Type' => 'bigint', 'Length' => 8, 'Null' => 'YES', 'Size' => '0', ), (object)array( 'Default' => null, 'Field' => 'description', 'Key' => '0', 'Type' => 'text', 'Length' => 16, 'Null' => 'YES', 'Size' => '0', ), )); $this->db->executeResultsStack = array($SqlserverTableDescription); $dummyModel = $this->model; $result = $this->db->describe($dummyModel); $expected = array( 'count' => array( 'type' => 'integer', 'null' => false, 'default' => '0', 'length' => 4 ), 'body' => array( 'type' => 'text', 'null' => true, 'default' => null, 'length' => null ), 'published' => array( 'type' => 'datetime', 'null' => true, 'default' => '', 'length' => null ), 'id' => array( 'type' => 'string', 'null' => false, 'default' => '', 'length' => 36, 'key' => 'primary' ), 'parent_id' => array( 'type' => 'biginteger', 'null' => true, 'default' => null, 'length' => 8, ), 'description' => array( 'type' => 'text', 'null' => true, 'default' => null, 'length' => null, ) ); $this->assertEquals($expected, $result); $this->assertSame($expected['parent_id'], $result['parent_id']); } /** * testBuildColumn * * @return void */ public function testBuildColumn() { $column = array('name' => 'id', 'type' => 'integer', 'null' => false, 'default' => '', 'length' => '8', 'key' => 'primary'); $result = $this->db->buildColumn($column); $expected = '[id] int IDENTITY (1, 1) NOT NULL'; $this->assertEquals($expected, $result); $column = array('name' => 'client_id', 'type' => 'integer', 'null' => false, 'default' => '0', 'length' => '11'); $result = $this->db->buildColumn($column); $expected = '[client_id] int DEFAULT 0 NOT NULL'; $this->assertEquals($expected, $result); $column = array('name' => 'client_id', 'type' => 'integer', 'null' => true); $result = $this->db->buildColumn($column); $expected = '[client_id] int NULL'; $this->assertEquals($expected, $result); // 'name' => 'type' format for columns $column = array('type' => 'integer', 'name' => 'client_id'); $result = $this->db->buildColumn($column); $expected = '[client_id] int NULL'; $this->assertEquals($expected, $result); $column = array('type' => 'string', 'name' => 'name'); $result = $this->db->buildColumn($column); $expected = '[name] nvarchar(255) NULL'; $this->assertEquals($expected, $result); $column = array('name' => 'name', 'type' => 'string', 'null' => false, 'default' => '', 'length' => '255'); $result = $this->db->buildColumn($column); $expected = '[name] nvarchar(255) DEFAULT \'\' NOT NULL'; $this->assertEquals($expected, $result); $column = array('name' => 'name', 'type' => 'string', 'null' => false, 'length' => '255'); $result = $this->db->buildColumn($column); $expected = '[name] nvarchar(255) NOT NULL'; $this->assertEquals($expected, $result); $column = array('name' => 'name', 'type' => 'string', 'null' => false, 'default' => null, 'length' => '255'); $result = $this->db->buildColumn($column); $expected = '[name] nvarchar(255) NOT NULL'; $this->assertEquals($expected, $result); $column = array('name' => 'name', 'type' => 'string', 'null' => true, 'default' => null, 'length' => '255'); $result = $this->db->buildColumn($column); $expected = '[name] nvarchar(255) NULL'; $this->assertEquals($expected, $result); $column = array('name' => 'name', 'type' => 'string', 'null' => true, 'default' => '', 'length' => '255'); $result = $this->db->buildColumn($column); $expected = '[name] nvarchar(255) DEFAULT \'\''; $this->assertEquals($expected, $result); $column = array('name' => 'body', 'type' => 'text'); $result = $this->db->buildColumn($column); $expected = '[body] nvarchar(MAX)'; $this->assertEquals($expected, $result); $column = array( 'name' => 'checked', 'type' => 'boolean', 'length' => 10, 'default' => '1' ); $result = $this->db->buildColumn($column); $expected = "[checked] bit DEFAULT '1'"; $this->assertEquals($expected, $result); $column = array( 'name' => 'huge', 'type' => 'biginteger', ); $result = $this->db->buildColumn($column); $expected = "[huge] bigint"; $this->assertEquals($expected, $result); } /** * testBuildIndex method * * @return void */ public function testBuildIndex() { $indexes = array( 'PRIMARY' => array('column' => 'id', 'unique' => 1), 'client_id' => array('column' => 'client_id', 'unique' => 1) ); $result = $this->db->buildIndex($indexes, 'items'); $expected = array( 'PRIMARY KEY ([id])', 'ALTER TABLE items ADD CONSTRAINT client_id UNIQUE([client_id]);' ); $this->assertEquals($expected, $result); $indexes = array('client_id' => array('column' => 'client_id')); $result = $this->db->buildIndex($indexes, 'items'); $this->assertSame(array(), $result); $indexes = array('client_id' => array('column' => array('client_id', 'period_id'), 'unique' => 1)); $result = $this->db->buildIndex($indexes, 'items'); $expected = array('ALTER TABLE items ADD CONSTRAINT client_id UNIQUE([client_id], [period_id]);'); $this->assertEquals($expected, $result); } /** * testUpdateAllSyntax method * * @return void */ public function testUpdateAllSyntax() { $fields = array('SqlserverTestModel.client_id' => '[SqlserverTestModel].[client_id] + 1'); $conditions = array('SqlserverTestModel.updated <' => date('2009-01-01 00:00:00')); $this->db->update($this->model, $fields, null, $conditions); $result = $this->db->getLastQuery(); $this->assertNotRegExp('/SqlserverTestModel/', $result); $this->assertRegExp('/^UPDATE \[sqlserver_test_models\]/', $result); $this->assertRegExp('/SET \[client_id\] = \[client_id\] \+ 1/', $result); } /** * testGetPrimaryKey method * * @return void */ public function testGetPrimaryKey() { $schema = $this->model->schema(); $this->db->describe = $schema; $result = $this->db->getPrimaryKey($this->model); $this->assertEquals('id', $result); unset($schema['id']['key']); $this->db->describe = $schema; $result = $this->db->getPrimaryKey($this->model); $this->assertNull($result); } /** * SQL server < 11 doesn't have proper limit/offset support, test that our hack works. * * @return void */ public function testLimitOffsetHack() { $this->loadFixtures('Author', 'Post', 'User'); $query = array( 'limit' => 2, 'page' => 1, 'order' => 'User.user ASC', ); $User = ClassRegistry::init('User'); $results = $User->find('all', $query); $this->assertEquals(2, count($results)); $this->assertEquals('garrett', $results[0]['User']['user']); $this->assertEquals('larry', $results[1]['User']['user']); $query = array( 'limit' => 2, 'page' => 2, 'order' => 'User.user ASC', ); $User = ClassRegistry::init('User'); $results = $User->find('all', $query); $this->assertEquals(2, count($results)); $this->assertFalse(isset($results[0][0])); $this->assertEquals('mariano', $results[0]['User']['user']); $this->assertEquals('nate', $results[1]['User']['user']); } /** * Test that the return of stored procedures is honoured * * @return void */ public function testStoredProcedureReturn() { $sql = <<Dbo->execute($sql); $sql = <<Dbo->execute($sql); $this->Dbo->execute('DROP PROC cake_test_procedure'); $result = $query->fetch(); $this->assertEquals(2, $result['value']); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Datasource/DboSourceTest.php000066400000000000000000001622561265552240500247510ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model.Datasource * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Model', 'Model'); App::uses('AppModel', 'Model'); App::uses('DataSource', 'Model/Datasource'); App::uses('DboSource', 'Model/Datasource'); App::uses('DboTestSource', 'Model/Datasource'); App::uses('DboSecondTestSource', 'Model/Datasource'); App::uses('MockDataSource', 'Model/Datasource'); require_once dirname(dirname(__FILE__)) . DS . 'models.php'; /** * Class MockPDO * * @package Cake.Test.Case.Model.Datasource */ class MockPDO extends PDO { /** * Constructor. */ public function __construct() { } } /** * Class MockDataSource * * @package Cake.Test.Case.Model.Datasource */ class MockDataSource extends DataSource { } /** * Class DboTestSource * * @package Cake.Test.Case.Model.Datasource */ class DboTestSource extends DboSource { public $nestedSupport = false; public function connect($config = array()) { $this->connected = true; } public function mergeAssociation(&$data, &$merge, $association, $type, $selfJoin = false) { return parent::_mergeAssociation($data, $merge, $association, $type, $selfJoin); } public function setConfig($config = array()) { $this->config = $config; } public function setConnection($conn) { $this->_connection = $conn; } public function nestedTransactionSupported() { return $this->useNestedTransactions && $this->nestedSupport; } } /** * Class DboSecondTestSource * * @package Cake.Test.Case.Model.Datasource */ class DboSecondTestSource extends DboSource { public $startQuote = '_'; public $endQuote = '_'; public function connect($config = array()) { $this->connected = true; } public function mergeAssociation(&$data, &$merge, $association, $type, $selfJoin = false) { return parent::_mergeAssociation($data, $merge, $association, $type, $selfJoin); } public function setConfig($config = array()) { $this->config = $config; } public function setConnection($conn) { $this->_connection = $conn; } } /** * DboSourceTest class * * @package Cake.Test.Case.Model.Datasource */ class DboSourceTest extends CakeTestCase { /** * autoFixtures property * * @var bool */ public $autoFixtures = false; /** * fixtures property * * @var array */ public $fixtures = array( 'core.apple', 'core.article', 'core.articles_tag', 'core.attachment', 'core.comment', 'core.sample', 'core.tag', 'core.user', 'core.post', 'core.author', 'core.data_test' ); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->testDb = new DboTestSource(); $this->testDb->cacheSources = false; $this->testDb->startQuote = '`'; $this->testDb->endQuote = '`'; $this->Model = new TestModel(); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Model); } /** * test that booleans and null make logical condition strings. * * @return void */ public function testBooleanNullConditionsParsing() { $result = $this->testDb->conditions(true); $this->assertEquals(' WHERE 1 = 1', $result, 'true conditions failed %s'); $result = $this->testDb->conditions(false); $this->assertEquals(' WHERE 0 = 1', $result, 'false conditions failed %s'); $result = $this->testDb->conditions(null); $this->assertEquals(' WHERE 1 = 1', $result, 'null conditions failed %s'); $result = $this->testDb->conditions(array()); $this->assertEquals(' WHERE 1 = 1', $result, 'array() conditions failed %s'); $result = $this->testDb->conditions(''); $this->assertEquals(' WHERE 1 = 1', $result, '"" conditions failed %s'); $result = $this->testDb->conditions(' ', '" " conditions failed %s'); $this->assertEquals(' WHERE 1 = 1', $result); } /** * test that booleans work on empty set. * * @return void */ public function testBooleanEmptyConditionsParsing() { $result = $this->testDb->conditions(array('OR' => array())); $this->assertEquals(' WHERE 1 = 1', $result, 'empty conditions failed'); $result = $this->testDb->conditions(array('OR' => array('OR' => array()))); $this->assertEquals(' WHERE 1 = 1', $result, 'nested empty conditions failed'); } /** * test that order() will accept objects made from DboSource::expression * * @return void */ public function testOrderWithExpression() { $expression = $this->testDb->expression("CASE Sample.id WHEN 1 THEN 'Id One' ELSE 'Other Id' END AS case_col"); $result = $this->testDb->order($expression); $expected = " ORDER BY CASE Sample.id WHEN 1 THEN 'Id One' ELSE 'Other Id' END AS case_col"; $this->assertEquals($expected, $result); } /** * testMergeAssociations method * * @return void */ public function testMergeAssociations() { $data = array('Article2' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' )); $merge = array('Topic' => array(array( 'id' => '1', 'topic' => 'Topic', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ))); $expected = array( 'Article2' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Topic' => array( 'id' => '1', 'topic' => 'Topic', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ); $this->testDb->mergeAssociation($data, $merge, 'Topic', 'hasOne'); $this->assertEquals($expected, $data); $data = array('Article2' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' )); $merge = array('User2' => array(array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ))); $expected = array( 'Article2' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User2' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ); $this->testDb->mergeAssociation($data, $merge, 'User2', 'belongsTo'); $this->assertEquals($expected, $data); $data = array( 'Article2' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ) ); $merge = array(array('Comment' => false)); $expected = array( 'Article2' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Comment' => array() ); $this->testDb->mergeAssociation($data, $merge, 'Comment', 'hasMany'); $this->assertEquals($expected, $data); $data = array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ) ); $merge = array( array( 'Comment' => array( 'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ), array( 'Comment' => array( 'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ) ); $expected = array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Comment' => array( array( 'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), array( 'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ) ); $this->testDb->mergeAssociation($data, $merge, 'Comment', 'hasMany'); $this->assertEquals($expected, $data); $data = array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ) ); $merge = array( array( 'Comment' => array( 'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'User2' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ), array( 'Comment' => array( 'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'User2' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ) ); $expected = array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Comment' => array( array( 'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'User2' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ), array( 'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'User2' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ) ) ); $this->testDb->mergeAssociation($data, $merge, 'Comment', 'hasMany'); $this->assertEquals($expected, $data); $data = array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ) ); $merge = array( array( 'Comment' => array( 'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'User2' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Tag' => array( array('id' => 1, 'tag' => 'Tag 1'), array('id' => 2, 'tag' => 'Tag 2') ) ), array( 'Comment' => array( 'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'User2' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Tag' => array() ) ); $expected = array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Comment' => array( array( 'id' => '1', 'comment' => 'Comment 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'User2' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Tag' => array( array('id' => 1, 'tag' => 'Tag 1'), array('id' => 2, 'tag' => 'Tag 2') ) ), array( 'id' => '2', 'comment' => 'Comment 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'User2' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Tag' => array() ) ) ); $this->testDb->mergeAssociation($data, $merge, 'Comment', 'hasMany'); $this->assertEquals($expected, $data); $data = array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ) ); $merge = array( array( 'Tag' => array( 'id' => '1', 'tag' => 'Tag 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ), array( 'Tag' => array( 'id' => '2', 'tag' => 'Tag 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ), array( 'Tag' => array( 'id' => '3', 'tag' => 'Tag 3', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ) ); $expected = array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Tag' => array( array( 'id' => '1', 'tag' => 'Tag 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), array( 'id' => '2', 'tag' => 'Tag 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), array( 'id' => '3', 'tag' => 'Tag 3', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ) ); $this->testDb->mergeAssociation($data, $merge, 'Tag', 'hasAndBelongsToMany'); $this->assertEquals($expected, $data); $data = array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ) ); $merge = array( array( 'Tag' => array( 'id' => '1', 'tag' => 'Tag 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ), array( 'Tag' => array( 'id' => '2', 'tag' => 'Tag 2', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ), array( 'Tag' => array( 'id' => '3', 'tag' => 'Tag 3', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ) ) ); $expected = array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Tag' => array('id' => '1', 'tag' => 'Tag 1', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31') ); $this->testDb->mergeAssociation($data, $merge, 'Tag', 'hasOne'); $this->assertEquals($expected, $data); } /** * testMagicMethodQuerying method * * @return void */ public function testMagicMethodQuerying() { $result = $this->db->query('findByFieldName', array('value'), $this->Model); $expected = array('first', array( 'conditions' => array('TestModel.field_name' => 'value'), 'fields' => null, 'order' => null, 'recursive' => null )); $this->assertEquals($expected, $result); $result = $this->db->query('findByFindBy', array('value'), $this->Model); $expected = array('first', array( 'conditions' => array('TestModel.find_by' => 'value'), 'fields' => null, 'order' => null, 'recursive' => null )); $this->assertEquals($expected, $result); $result = $this->db->query('findAllByFieldName', array('value'), $this->Model); $expected = array('all', array( 'conditions' => array('TestModel.field_name' => 'value'), 'fields' => null, 'order' => null, 'limit' => null, 'page' => null, 'recursive' => null )); $this->assertEquals($expected, $result); $result = $this->db->query('findAllById', array('a'), $this->Model); $expected = array('all', array( 'conditions' => array('TestModel.id' => 'a'), 'fields' => null, 'order' => null, 'limit' => null, 'page' => null, 'recursive' => null )); $this->assertEquals($expected, $result); $result = $this->db->query('findByFieldName', array(array('value1', 'value2', 'value3')), $this->Model); $expected = array('first', array( 'conditions' => array('TestModel.field_name' => array('value1', 'value2', 'value3')), 'fields' => null, 'order' => null, 'recursive' => null )); $this->assertEquals($expected, $result); $result = $this->db->query('findByFieldName', array(null), $this->Model); $expected = array('first', array( 'conditions' => array('TestModel.field_name' => null), 'fields' => null, 'order' => null, 'recursive' => null )); $this->assertEquals($expected, $result); $result = $this->db->query('findByFieldName', array('= a'), $this->Model); $expected = array('first', array( 'conditions' => array('TestModel.field_name' => '= a'), 'fields' => null, 'order' => null, 'recursive' => null )); $this->assertEquals($expected, $result); $result = $this->db->query('findByFieldName', array(), $this->Model); $expected = false; $this->assertEquals($expected, $result); // findByAnd $result = $this->db->query('findByFieldXAndFieldY', array('x', 'y'), $this->Model); $expected = array('first', array( 'conditions' => array('TestModel.field_x' => 'x', 'TestModel.field_y' => 'y'), 'fields' => null, 'order' => null, 'recursive' => null )); $this->assertEquals($expected, $result); // findByOr $result = $this->db->query('findByFieldXOrFieldY', array('x', 'y'), $this->Model); $expected = array('first', array( 'conditions' => array('OR' => array('TestModel.field_x' => 'x', 'TestModel.field_y' => 'y')), 'fields' => null, 'order' => null, 'recursive' => null )); $this->assertEquals($expected, $result); // findMyFancySearchBy $result = $this->db->query('findMyFancySearchByFieldX', array('x'), $this->Model); $expected = array('myFancySearch', array( 'conditions' => array('TestModel.field_x' => 'x'), 'fields' => null, 'order' => null, 'limit' => null, 'page' => null, 'recursive' => null )); $this->assertEquals($expected, $result); // findFirstBy $result = $this->db->query('findFirstByFieldX', array('x'), $this->Model); $expected = array('first', array( 'conditions' => array('TestModel.field_x' => 'x'), 'fields' => null, 'order' => null, 'recursive' => null )); $this->assertEquals($expected, $result); // findBy with optional parameters $result = $this->db->query('findByFieldX', array('x', 'y', 'priority', -1), $this->Model); $expected = array('first', array( 'conditions' => array('TestModel.field_x' => 'x'), 'fields' => 'y', 'order' => 'priority', 'recursive' => -1 )); $this->assertEquals($expected, $result); // findByAnd with optional parameters $result = $this->db->query('findByFieldXAndFieldY', array('x', 'y', 'z', 'priority', -1), $this->Model); $expected = array('first', array( 'conditions' => array('TestModel.field_x' => 'x', 'TestModel.field_y' => 'y'), 'fields' => 'z', 'order' => 'priority', 'recursive' => -1 )); $this->assertEquals($expected, $result); // findAllBy with optional parameters $result = $this->db->query('findAllByFieldX', array('x', 'y', 'priority', 10, 2, -1), $this->Model); $expected = array('all', array( 'conditions' => array('TestModel.field_x' => 'x'), 'fields' => 'y', 'order' => 'priority', 'limit' => 10, 'page' => 2, 'recursive' => -1 )); $this->assertEquals($expected, $result); // findAllByAnd with optional parameters $result = $this->db->query('findAllByFieldXAndFieldY', array('x', 'y', 'z', 'priority', 10, 2, -1), $this->Model); $expected = array('all', array( 'conditions' => array('TestModel.field_x' => 'x', 'TestModel.field_y' => 'y'), 'fields' => 'z', 'order' => 'priority', 'limit' => 10, 'page' => 2, 'recursive' => -1 )); $this->assertEquals($expected, $result); } /** * @expectedException PDOException * @return void */ public function testDirectCallThrowsException() { $this->db->query('directCall', array(), $this->Model); } /** * testValue method * * @return void */ public function testValue() { if ($this->db instanceof Sqlserver) { $this->markTestSkipped('Cannot run this test with SqlServer'); } $result = $this->db->value('{$__cakeForeignKey__$}'); $this->assertEquals('{$__cakeForeignKey__$}', $result); $result = $this->db->value(array('first', 2, 'third')); $expected = array('\'first\'', 2, '\'third\''); $this->assertEquals($expected, $result); } /** * Tests if the connection can be re-established and that the new (optional) config is set. * * @return void */ public function testReconnect() { $this->testDb->reconnect(array('prefix' => 'foo')); $this->assertTrue($this->testDb->connected); $this->assertEquals('foo', $this->testDb->config['prefix']); } /** * testName method * * @return void */ public function testName() { $result = $this->testDb->name('name'); $expected = '`name`'; $this->assertEquals($expected, $result); $result = $this->testDb->name(array('name', 'Model.*')); $expected = array('`name`', '`Model`.*'); $this->assertEquals($expected, $result); $result = $this->testDb->name('MTD()'); $expected = 'MTD()'; $this->assertEquals($expected, $result); $result = $this->testDb->name('(sm)'); $expected = '(sm)'; $this->assertEquals($expected, $result); $result = $this->testDb->name('name AS x'); $expected = '`name` AS `x`'; $this->assertEquals($expected, $result); $result = $this->testDb->name('Model.name AS x'); $expected = '`Model`.`name` AS `x`'; $this->assertEquals($expected, $result); $result = $this->testDb->name('Function(Something.foo)'); $expected = 'Function(`Something`.`foo`)'; $this->assertEquals($expected, $result); $result = $this->testDb->name('Function(SubFunction(Something.foo))'); $expected = 'Function(SubFunction(`Something`.`foo`))'; $this->assertEquals($expected, $result); $result = $this->testDb->name('Function(Something.foo) AS x'); $expected = 'Function(`Something`.`foo`) AS `x`'; $this->assertEquals($expected, $result); $result = $this->testDb->name('I18n__title__pt-br.locale'); $expected = '`I18n__title__pt-br`.`locale`'; $this->assertEquals($expected, $result); $result = $this->testDb->name('name-with-minus'); $expected = '`name-with-minus`'; $this->assertEquals($expected, $result); $result = $this->testDb->name(array('my-name', 'Foo-Model.*')); $expected = array('`my-name`', '`Foo-Model`.*'); $this->assertEquals($expected, $result); $result = $this->testDb->name(array('Team.P%', 'Team.G/G')); $expected = array('`Team`.`P%`', '`Team`.`G/G`'); $this->assertEquals($expected, $result); $result = $this->testDb->name('Model.name as y'); $expected = '`Model`.`name` AS `y`'; $this->assertEquals($expected, $result); } /** * test that cacheMethod works as expected * * @return void */ public function testCacheMethod() { $this->testDb->cacheMethods = true; $result = $this->testDb->cacheMethod('name', 'some-key', 'stuff'); $this->assertEquals('stuff', $result); $result = $this->testDb->cacheMethod('name', 'some-key'); $this->assertEquals('stuff', $result); $result = $this->testDb->cacheMethod('conditions', 'some-key'); $this->assertNull($result); $result = $this->testDb->cacheMethod('name', 'other-key'); $this->assertNull($result); $this->testDb->cacheMethods = false; $result = $this->testDb->cacheMethod('name', 'some-key', 'stuff'); $this->assertEquals('stuff', $result); $result = $this->testDb->cacheMethod('name', 'some-key'); $this->assertNull($result); } /** * Test that rare collisions do not happen with method caching * * @return void */ public function testNameMethodCacheCollisions() { $this->testDb->cacheMethods = true; $this->testDb->flushMethodCache(); $this->testDb->name('Model.fieldlbqndkezcoapfgirmjsh'); $result = $this->testDb->name('Model.fieldkhdfjmelarbqnzsogcpi'); $expected = '`Model`.`fieldkhdfjmelarbqnzsogcpi`'; $this->assertEquals($expected, $result); } /** * Test that flushMethodCache works as expected * * @return void */ public function testFlushMethodCache() { $this->testDb->cacheMethods = true; $this->testDb->cacheMethod('name', 'some-key', 'stuff'); Cache::write('method_cache', DboTestSource::$methodCache, '_cake_core_'); $this->testDb->flushMethodCache(); $result = $this->testDb->cacheMethod('name', 'some-key'); $this->assertNull($result); } /** * testLog method * * @outputBuffering enabled * @return void */ public function testLog() { $this->testDb->logQuery('Query 1'); $this->testDb->logQuery('Query 2'); $log = $this->testDb->getLog(false, false); $result = Hash::extract($log['log'], '{n}.query'); $expected = array('Query 1', 'Query 2'); $this->assertEquals($expected, $result); $oldDebug = Configure::read('debug'); Configure::write('debug', 2); ob_start(); $this->testDb->showLog(); $contents = ob_get_clean(); $this->assertRegExp('/Query 1/s', $contents); $this->assertRegExp('/Query 2/s', $contents); ob_start(); $this->testDb->showLog(true); $contents = ob_get_clean(); $this->assertRegExp('/Query 1/s', $contents); $this->assertRegExp('/Query 2/s', $contents); Configure::write('debug', $oldDebug); } /** * test getting the query log as an array. * * @return void */ public function testGetLog() { $this->testDb->logQuery('Query 1'); $this->testDb->logQuery('Query 2'); $log = $this->testDb->getLog(); $expected = array('query' => 'Query 1', 'params' => array(), 'affected' => '', 'numRows' => '', 'took' => ''); $this->assertEquals($expected, $log['log'][0]); $expected = array('query' => 'Query 2', 'params' => array(), 'affected' => '', 'numRows' => '', 'took' => ''); $this->assertEquals($expected, $log['log'][1]); $expected = array('query' => 'Error 1', 'affected' => '', 'numRows' => '', 'took' => ''); } /** * test getting the query log as an array, setting bind params. * * @return void */ public function testGetLogParams() { $this->testDb->logQuery('Query 1', array(1, 2, 'abc')); $this->testDb->logQuery('Query 2', array('field1' => 1, 'field2' => 'abc')); $log = $this->testDb->getLog(); $expected = array('query' => 'Query 1', 'params' => array(1, 2, 'abc'), 'affected' => '', 'numRows' => '', 'took' => ''); $this->assertEquals($expected, $log['log'][0]); $expected = array('query' => 'Query 2', 'params' => array('field1' => 1, 'field2' => 'abc'), 'affected' => '', 'numRows' => '', 'took' => ''); $this->assertEquals($expected, $log['log'][1]); } /** * test that query() returns boolean values from operations like CREATE TABLE * * @return void */ public function testFetchAllBooleanReturns() { $name = $this->db->fullTableName('test_query'); $query = "CREATE TABLE {$name} (name varchar(10));"; $result = $this->db->query($query); $this->assertTrue($result, 'Query did not return a boolean'); $query = "DROP TABLE {$name};"; $result = $this->db->query($query); $this->assertTrue($result, 'Query did not return a boolean'); } /** * Test NOT NULL on ENUM data type with empty string as a value * * @return void */ public function testNotNullOnEnum() { if (!$this->db instanceof Mysql) { $this->markTestSkipped('This test can only run on MySQL'); } $name = $this->db->fullTableName('enum_tests'); $query = "CREATE TABLE {$name} (mood ENUM('','happy','sad','ok') NOT NULL);"; $result = $this->db->query($query); $this->assertTrue($result); $EnumTest = ClassRegistry::init('EnumTest'); $enumResult = $EnumTest->save(array('mood' => '')); $query = "DROP TABLE {$name};"; $result = $this->db->query($query); $this->assertTrue($result); $this->assertEquals(array( 'EnumTest' => array( 'mood' => '', 'id' => '0' ) ), $enumResult); } /** * test order to generate query order clause for virtual fields * * @return void */ public function testVirtualFieldsInOrder() { $Article = ClassRegistry::init('Article'); $Article->virtualFields = array( 'this_moment' => 'NOW()', 'two' => '1 + 1', ); $order = array('two', 'this_moment'); $result = $this->db->order($order, 'ASC', $Article); $expected = ' ORDER BY (1 + 1) ASC, (NOW()) ASC'; $this->assertEquals($expected, $result); $order = array('Article.two', 'Article.this_moment'); $result = $this->db->order($order, 'ASC', $Article); $expected = ' ORDER BY (1 + 1) ASC, (NOW()) ASC'; $this->assertEquals($expected, $result); } /** * test the permutations of fullTableName() * * @return void */ public function testFullTablePermutations() { $Article = ClassRegistry::init('Article'); $result = $this->testDb->fullTableName($Article, false, false); $this->assertEquals('articles', $result); $Article->tablePrefix = 'tbl_'; $result = $this->testDb->fullTableName($Article, false, false); $this->assertEquals('tbl_articles', $result); $Article->useTable = $Article->table = 'with spaces'; $Article->tablePrefix = ''; $result = $this->testDb->fullTableName($Article, true, false); $this->assertEquals('`with spaces`', $result); $this->loadFixtures('Article'); $Article->useTable = $Article->table = 'articles'; $Article->setDataSource('test'); $testdb = $Article->getDataSource(); $result = $testdb->fullTableName($Article, false, true); $this->assertEquals($testdb->getSchemaName() . '.articles', $result); // tests for empty schemaName $noschema = ConnectionManager::create('noschema', array( 'datasource' => 'DboTestSource' )); $Article->setDataSource('noschema'); $Article->schemaName = null; $result = $noschema->fullTableName($Article, false, true); $this->assertEquals('articles', $result); $this->testDb->config['prefix'] = 't_'; $result = $this->testDb->fullTableName('post_tag', false, false); $this->assertEquals('t_post_tag', $result); } /** * test that read() only calls queryAssociation on db objects when the method is defined. * * @return void */ public function testReadOnlyCallingQueryAssociationWhenDefined() { $this->loadFixtures('Article', 'User', 'ArticlesTag', 'Tag'); ConnectionManager::create('test_no_queryAssociation', array( 'datasource' => 'MockDataSource' )); $Article = ClassRegistry::init('Article'); $Article->Comment->useDbConfig = 'test_no_queryAssociation'; $result = $Article->find('all'); $this->assertTrue(is_array($result)); } /** * test that queryAssociation() reuse already joined data for 'belongsTo' and 'hasOne' associations * instead of running unneeded queries for each record * * @return void */ public function testQueryAssociationUnneededQueries() { $this->loadFixtures('Article', 'User', 'Comment', 'Attachment', 'Tag', 'ArticlesTag'); $Comment = ClassRegistry::init('Comment'); $fullDebug = $this->db->fullDebug; $this->db->fullDebug = true; $Comment->find('all', array('recursive' => 2)); // ensure Model descriptions are saved $this->db->getLog(); // case: Comment belongsTo User and Article $Comment->unbindModel(array( 'hasOne' => array('Attachment') )); $Comment->Article->unbindModel(array( 'belongsTo' => array('User'), 'hasMany' => array('Comment'), 'hasAndBelongsToMany' => array('Tag') )); $Comment->find('all', array('recursive' => 2)); $log = $this->db->getLog(); $this->assertEquals(1, count($log['log'])); // case: Comment belongsTo Article, Article belongsTo User $Comment->unbindModel(array( 'belongsTo' => array('User'), 'hasOne' => array('Attachment') )); $Comment->Article->unbindModel(array( 'hasMany' => array('Comment'), 'hasAndBelongsToMany' => array('Tag'), )); $Comment->find('all', array('recursive' => 2)); $log = $this->db->getLog(); $this->assertEquals(7, count($log['log'])); // case: Comment hasOne Attachment $Comment->unbindModel(array( 'belongsTo' => array('Article', 'User'), )); $Comment->Attachment->unbindModel(array( 'belongsTo' => array('Comment'), )); $Comment->find('all', array('recursive' => 2)); $log = $this->db->getLog(); $this->assertEquals(1, count($log['log'])); $this->db->fullDebug = $fullDebug; } /** * Tests that generation association queries without LinkModel still works. * Mainly BC. * * @return void */ public function testGenerateAssociationQuery() { $this->loadFixtures('Article'); $Article = ClassRegistry::init('Article'); $queryData = array( 'conditions' => array( 'Article.id' => 1 ), 'fields' => array( 'Article.id', 'Article.title', ), 'joins' => array(), 'limit' => 2, 'offset' => 2, 'order' => array('title'), 'page' => 2, 'group' => null, 'callbacks' => 1 ); $result = $this->db->generateAssociationQuery($Article, null, null, null, null, $queryData, false); $this->assertContains('SELECT', $result); $this->assertContains('FROM', $result); $this->assertContains('WHERE', $result); $this->assertContains('ORDER', $result); } /** * test that fields() is using methodCache() * * @return void */ public function testFieldsUsingMethodCache() { $this->testDb->cacheMethods = false; DboTestSource::$methodCache = array(); $Article = ClassRegistry::init('Article'); $this->testDb->fields($Article, null, array('title', 'body', 'published')); $this->assertTrue(empty(DboTestSource::$methodCache['fields']), 'Cache not empty'); } /** * test that fields() method cache detects datasource changes * * @return void */ public function testFieldsCacheKeyWithDatasourceChange() { ConnectionManager::create('firstschema', array( 'datasource' => 'DboTestSource' )); ConnectionManager::create('secondschema', array( 'datasource' => 'DboSecondTestSource' )); Cache::delete('method_cache', '_cake_core_'); DboTestSource::$methodCache = array(); $Article = ClassRegistry::init('Article'); $Article->setDataSource('firstschema'); $ds = $Article->getDataSource(); $ds->cacheMethods = true; $first = $ds->fields($Article, null, array('title', 'body', 'published')); $Article->setDataSource('secondschema'); $ds = $Article->getDataSource(); $ds->cacheMethods = true; $second = $ds->fields($Article, null, array('title', 'body', 'published')); $this->assertNotEquals($first, $second); $this->assertEquals(2, count(DboTestSource::$methodCache['fields'])); } /** * test that fields() method cache detects schema name changes * * @return void */ public function testFieldsCacheKeyWithSchemanameChange() { if ($this->db instanceof Postgres || $this->db instanceof Sqlserver) { $this->markTestSkipped('Cannot run this test with SqlServer or Postgres'); } Cache::delete('method_cache', '_cake_core_'); DboSource::$methodCache = array(); $Article = ClassRegistry::init('Article'); $ds = $Article->getDataSource(); $ds->cacheMethods = true; $first = $ds->fields($Article); $Article->schemaName = 'secondSchema'; $ds = $Article->getDataSource(); $ds->cacheMethods = true; $second = $ds->fields($Article); $this->assertEquals(2, count(DboSource::$methodCache['fields'])); } /** * Test that group works without a model * * @return void */ public function testGroupNoModel() { $result = $this->db->group('created'); $this->assertEquals(' GROUP BY created', $result); } /** * Test getting the last error. * * @return void */ public function testLastError() { $stmt = $this->getMock('PDOStatement'); $stmt->expects($this->any()) ->method('errorInfo') ->will($this->returnValue(array('', 'something', 'bad'))); $result = $this->db->lastError($stmt); $expected = 'something: bad'; $this->assertEquals($expected, $result); } /** * Tests that transaction commands are logged * * @return void */ public function testTransactionLogging() { $conn = $this->getMock('MockPDO'); $db = new DboTestSource(); $db->setConnection($conn); $conn->expects($this->exactly(2))->method('beginTransaction') ->will($this->returnValue(true)); $conn->expects($this->once())->method('commit')->will($this->returnValue(true)); $conn->expects($this->once())->method('rollback')->will($this->returnValue(true)); $db->begin(); $log = $db->getLog(); $expected = array('query' => 'BEGIN', 'params' => array(), 'affected' => '', 'numRows' => '', 'took' => ''); $this->assertEquals($expected, $log['log'][0]); $db->commit(); $expected = array('query' => 'COMMIT', 'params' => array(), 'affected' => '', 'numRows' => '', 'took' => ''); $log = $db->getLog(); $this->assertEquals($expected, $log['log'][0]); $db->begin(); $expected = array('query' => 'BEGIN', 'params' => array(), 'affected' => '', 'numRows' => '', 'took' => ''); $log = $db->getLog(); $this->assertEquals($expected, $log['log'][0]); $db->rollback(); $expected = array('query' => 'ROLLBACK', 'params' => array(), 'affected' => '', 'numRows' => '', 'took' => ''); $log = $db->getLog(); $this->assertEquals($expected, $log['log'][0]); } /** * Test nested transaction calls * * @return void */ public function testTransactionNested() { $conn = $this->getMock('MockPDO'); $db = new DboTestSource(); $db->setConnection($conn); $db->useNestedTransactions = true; $db->nestedSupport = true; $conn->expects($this->at(0))->method('beginTransaction')->will($this->returnValue(true)); $conn->expects($this->at(1))->method('exec')->with($this->equalTo('SAVEPOINT LEVEL1'))->will($this->returnValue(true)); $conn->expects($this->at(2))->method('exec')->with($this->equalTo('RELEASE SAVEPOINT LEVEL1'))->will($this->returnValue(true)); $conn->expects($this->at(3))->method('exec')->with($this->equalTo('SAVEPOINT LEVEL1'))->will($this->returnValue(true)); $conn->expects($this->at(4))->method('exec')->with($this->equalTo('ROLLBACK TO SAVEPOINT LEVEL1'))->will($this->returnValue(true)); $conn->expects($this->at(5))->method('commit')->will($this->returnValue(true)); $this->_runTransactions($db); } /** * Test nested transaction calls without support * * @return void */ public function testTransactionNestedWithoutSupport() { $conn = $this->getMock('MockPDO'); $db = new DboTestSource(); $db->setConnection($conn); $db->useNestedTransactions = true; $db->nestedSupport = false; $conn->expects($this->once())->method('beginTransaction')->will($this->returnValue(true)); $conn->expects($this->never())->method('exec'); $conn->expects($this->once())->method('commit')->will($this->returnValue(true)); $this->_runTransactions($db); } /** * Test nested transaction disabled * * @return void */ public function testTransactionNestedDisabled() { $conn = $this->getMock('MockPDO'); $db = new DboTestSource(); $db->setConnection($conn); $db->useNestedTransactions = false; $db->nestedSupport = true; $conn->expects($this->once())->method('beginTransaction')->will($this->returnValue(true)); $conn->expects($this->never())->method('exec'); $conn->expects($this->once())->method('commit')->will($this->returnValue(true)); $this->_runTransactions($db); } /** * Nested transaction calls * * @param DboTestSource $db * @return void */ protected function _runTransactions($db) { $db->begin(); $db->begin(); $db->commit(); $db->begin(); $db->rollback(); $db->commit(); } /** * Test build statement with some fields missing * * @return void */ public function testBuildStatementDefaults() { $conn = $this->getMock('MockPDO', array('quote')); $conn->expects($this->at(0)) ->method('quote') ->will($this->returnValue('foo bar')); $db = new DboTestSource(); $db->setConnection($conn); $subQuery = $db->buildStatement( array( 'fields' => array('DISTINCT(AssetsTag.asset_id)'), 'table' => "assets_tags", 'alias' => "AssetsTag", 'conditions' => array("Tag.name" => 'foo bar'), 'limit' => null, 'group' => "AssetsTag.asset_id" ), $this->Model ); $expected = 'SELECT DISTINCT(AssetsTag.asset_id) FROM assets_tags AS AssetsTag WHERE Tag.name = foo bar GROUP BY AssetsTag.asset_id'; $this->assertEquals($expected, $subQuery); } /** * data provider for testBuildJoinStatement * * @return array */ public static function joinStatements() { return array( array(array( 'type' => 'CROSS', 'alias' => 'PostsTag', 'table' => 'posts_tags', 'conditions' => array('1 = 1') ), 'CROSS JOIN cakephp.posts_tags AS PostsTag'), array(array( 'type' => 'LEFT', 'alias' => 'PostsTag', 'table' => 'posts_tags', ), 'LEFT JOIN cakephp.posts_tags AS PostsTag'), array(array( 'type' => 'LEFT', 'alias' => 'PostsTag', 'table' => 'posts_tags', 'conditions' => array('PostsTag.post_id = Post.id') ), 'LEFT JOIN cakephp.posts_tags AS PostsTag ON (PostsTag.post_id = Post.id)'), array(array( 'type' => 'LEFT', 'alias' => 'Stock', 'table' => '(SELECT Stock.article_id, sum(quantite) quantite FROM stocks AS Stock GROUP BY Stock.article_id)', 'conditions' => 'Stock.article_id = Article.id' ), 'LEFT JOIN (SELECT Stock.article_id, sum(quantite) quantite FROM stocks AS Stock GROUP BY Stock.article_id) AS Stock ON (Stock.article_id = Article.id)') ); } /** * Test buildJoinStatement() * ensure that schemaName is not added when table value is a subquery * * @dataProvider joinStatements * @return void */ public function testBuildJoinStatement($join, $expected) { $db = $this->getMock('DboTestSource', array('getSchemaName')); $db->expects($this->any()) ->method('getSchemaName') ->will($this->returnValue('cakephp')); $result = $db->buildJoinStatement($join); $this->assertEquals($expected, $result); } /** * data provider for testBuildJoinStatementWithTablePrefix * * @return array */ public static function joinStatementsWithPrefix($schema) { return array( array(array( 'type' => 'LEFT', 'alias' => 'PostsTag', 'table' => 'posts_tags', 'conditions' => array('PostsTag.post_id = Post.id') ), 'LEFT JOIN pre_posts_tags AS PostsTag ON (PostsTag.post_id = Post.id)'), array(array( 'type' => 'LEFT', 'alias' => 'Stock', 'table' => '(SELECT Stock.article_id, sum(quantite) quantite FROM stocks AS Stock GROUP BY Stock.article_id)', 'conditions' => 'Stock.article_id = Article.id' ), 'LEFT JOIN (SELECT Stock.article_id, sum(quantite) quantite FROM stocks AS Stock GROUP BY Stock.article_id) AS Stock ON (Stock.article_id = Article.id)') ); } /** * Test buildJoinStatement() * ensure that prefix is not added when table value is a subquery * * @dataProvider joinStatementsWithPrefix * @return void */ public function testBuildJoinStatementWithTablePrefix($join, $expected) { $db = new DboTestSource(); $db->config['prefix'] = 'pre_'; $result = $db->buildJoinStatement($join); $this->assertEquals($expected, $result); } /** * Test conditionKeysToString() * * @return void */ public function testConditionKeysToString() { $Article = ClassRegistry::init('Article'); $conn = $this->getMock('MockPDO', array('quote')); $db = new DboTestSource(); $db->setConnection($conn); $conn->expects($this->at(0)) ->method('quote') ->will($this->returnValue('just text')); $conditions = array('Article.name' => 'just text'); $result = $db->conditionKeysToString($conditions, true, $Article); $expected = "Article.name = just text"; $this->assertEquals($expected, $result[0]); $conn->expects($this->at(0)) ->method('quote') ->will($this->returnValue('just text')); $conn->expects($this->at(1)) ->method('quote') ->will($this->returnValue('other text')); $conditions = array('Article.name' => array('just text', 'other text')); $result = $db->conditionKeysToString($conditions, true, $Article); $expected = "Article.name IN (just text, other text)"; $this->assertEquals($expected, $result[0]); } /** * Test conditionKeysToString() with virtual field * * @return void */ public function testConditionKeysToStringVirtualField() { $Article = ClassRegistry::init('Article'); $Article->virtualFields = array( 'extra' => 'something virtual' ); $conn = $this->getMock('MockPDO', array('quote')); $db = new DboTestSource(); $db->setConnection($conn); $conn->expects($this->at(0)) ->method('quote') ->will($this->returnValue('just text')); $conditions = array('Article.extra' => 'just text'); $result = $db->conditionKeysToString($conditions, true, $Article); $expected = "(" . $Article->virtualFields['extra'] . ") = just text"; $this->assertEquals($expected, $result[0]); $conn->expects($this->at(0)) ->method('quote') ->will($this->returnValue('just text')); $conn->expects($this->at(1)) ->method('quote') ->will($this->returnValue('other text')); $conditions = array('Article.extra' => array('just text', 'other text')); $result = $db->conditionKeysToString($conditions, true, $Article); $expected = "(" . $Article->virtualFields['extra'] . ") IN (just text, other text)"; $this->assertEquals($expected, $result[0]); } /** * Test the limit function. * * @return void */ public function testLimit() { $db = new DboTestSource(); $result = $db->limit('0'); $this->assertNull($result); $result = $db->limit('10'); $this->assertEquals(' LIMIT 10', $result); $result = $db->limit('FARTS', 'BOOGERS'); $this->assertEquals(' LIMIT 0, 0', $result); $result = $db->limit(20, 10); $this->assertEquals(' LIMIT 10, 20', $result); $result = $db->limit(10, 300000000000000000000000000000); $scientificNotation = sprintf('%.1E', 300000000000000000000000000000); $this->assertNotContains($scientificNotation, $result); } /** * Test insertMulti with id position. * * @return void */ public function testInsertMultiId() { $this->loadFixtures('Article'); $Article = ClassRegistry::init('Article'); $db = $Article->getDatasource(); $datetime = date('Y-m-d H:i:s'); $data = array( array( 'user_id' => 1, 'title' => 'test', 'body' => 'test', 'published' => 'N', 'created' => $datetime, 'updated' => $datetime, 'id' => 100, ), array( 'user_id' => 1, 'title' => 'test 101', 'body' => 'test 101', 'published' => 'N', 'created' => $datetime, 'updated' => $datetime, 'id' => 101, ) ); $result = $db->insertMulti('articles', array_keys($data[0]), $data); $this->assertTrue($result, 'Data was saved'); $data = array( array( 'id' => 102, 'user_id' => 1, 'title' => 'test', 'body' => 'test', 'published' => 'N', 'created' => $datetime, 'updated' => $datetime, ), array( 'id' => 103, 'user_id' => 1, 'title' => 'test 101', 'body' => 'test 101', 'published' => 'N', 'created' => $datetime, 'updated' => $datetime, ) ); $result = $db->insertMulti('articles', array_keys($data[0]), $data); $this->assertTrue($result, 'Data was saved'); } /** * Test defaultConditions() * * @return void */ public function testDefaultConditions() { $this->loadFixtures('Article'); $Article = ClassRegistry::init('Article'); $db = $Article->getDataSource(); // Creates a default set of conditions from the model if $conditions is null/empty. $Article->id = 1; $result = $db->defaultConditions($Article, null); $this->assertEquals(array('Article.id' => 1), $result); // $useAlias == false $Article->id = 1; $result = $db->defaultConditions($Article, null, false); $this->assertEquals(array($db->fullTableName($Article, false) . '.id' => 1), $result); // If conditions are supplied then they will be returned. $Article->id = 1; $result = $db->defaultConditions($Article, array('Article.title' => 'First article')); $this->assertEquals(array('Article.title' => 'First article'), $result); // If a model doesn't exist and no conditions were provided either null or false will be returned based on what was input. $Article->id = 1000000; $result = $db->defaultConditions($Article, null); $this->assertNull($result); $Article->id = 1000000; $result = $db->defaultConditions($Article, false); $this->assertFalse($result); // Safe update mode $Article->id = 1000000; $Article->__safeUpdateMode = true; $result = $db->defaultConditions($Article, null); $this->assertFalse($result); } /** * Test that count how many times afterFind is called * * @return void */ public function testCountAfterFindCalls() { $this->loadFixtures('Article', 'User', 'Comment', 'Attachment', 'Tag', 'ArticlesTag'); // Use alias to make testing "primary = true" easy $Primary = $this->getMock('Comment', array('afterFind'), array(array('alias' => 'Primary')), '', true); $Article = $this->getMock('Article', array('afterFind'), array(), '', true); $User = $this->getMock('User', array('afterFind'), array(), '', true); $Comment = $this->getMock('Comment', array('afterFind'), array(), '', true); $Tag = $this->getMock('Tag', array('afterFind'), array(), '', true); $Attachment = $this->getMock('Attachment', array('afterFind'), array(), '', true); $Primary->Article = $Article; $Primary->Article->User = $User; $Primary->Article->Tag = $Tag; $Primary->Article->Comment = $Comment; $Primary->Attachment = $Attachment; $Primary->Attachment->Comment = $Comment; $Primary->User = $User; // primary = true $Primary->expects($this->once()) ->method('afterFind')->with($this->anything(), $this->isTrue())->will($this->returnArgument(0)); // primary = false $Article->expects($this->once()) // Primary belongs to 1 Article ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0)); $User->expects($this->exactly(2)) // Article belongs to 1 User and Primary belongs to 1 User ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0)); $Tag->expects($this->exactly(2)) // Article has 2 Tags ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0)); $Comment->expects($this->exactly(3)) // Article has 2 Comments and Attachment belongs to 1 Comment ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0)); $Attachment->expects($this->once()) // Primary has 1 Attachment ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0)); $result = $Primary->find('first', array('conditions' => array('Primary.id' => 5), 'recursive' => 2)); $this->assertCount(2, $result['Article']['Tag']); $this->assertCount(2, $result['Article']['Comment']); // hasMany special case // Both User and Article has many Comments $User = $this->getMock('User', array('afterFind'), array(), '', true); $Article = $this->getMock('Article', array('afterFind'), array(), '', true); $Comment = $this->getMock('Comment', array('afterFind'), array(), '', true); $User->bindModel(array('hasMany' => array('Comment', 'Article'))); $Article->unbindModel(array('belongsTo' => array('User'), 'hasAndBelongsToMany' => array('Tag'))); $Comment->unbindModel(array('belongsTo' => array('User', 'Article'), 'hasOne' => 'Attachment')); $User->Comment = $Comment; $User->Article = $Article; $User->Article->Comment = $Comment; // primary = true $User->expects($this->once()) ->method('afterFind')->with($this->anything(), $this->isTrue())->will($this->returnArgument(0)); $Article->expects($this->exactly(2)) // User has 2 Articles ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0)); $Comment->expects($this->exactly(7)) // User1 has 3 Comments, Article[id=1] has 4 Comments and Article[id=3] has 0 Comments ->method('afterFind')->with($this->anything(), $this->isFalse())->will($this->returnArgument(0)); $result = $User->find('first', array('conditions' => array('User.id' => 1), 'recursive' => 2)); $this->assertCount(3, $result['Comment']); $this->assertCount(2, $result['Article']); $this->assertCount(4, $result['Article'][0]['Comment']); $this->assertCount(0, $result['Article'][1]['Comment']); } /** * Test format of $results in afterFind * * @return void */ public function testUseConsistentAfterFind() { $this->loadFixtures('Author', 'Post'); $expected = array( 'Author' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'test' => 'working', ), 'Post' => array( array( 'id' => '1', 'author_id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', ), array( 'id' => '3', 'author_id' => '1', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', ), ), ); $Author = new Author(); $Post = $this->getMock('Post', array('afterFind'), array(), '', true); $Post->expects($this->at(0))->method('afterFind')->with(array(array('Post' => $expected['Post'][0])), $this->isFalse())->will($this->returnArgument(0)); $Post->expects($this->at(1))->method('afterFind')->with(array(array('Post' => $expected['Post'][1])), $this->isFalse())->will($this->returnArgument(0)); $Author->bindModel(array('hasMany' => array('Post' => array('limit' => 2, 'order' => 'Post.id')))); $Author->Post = $Post; $result = $Author->find('first', array('conditions' => array('Author.id' => 1), 'recursive' => 1)); $this->assertEquals($expected, $result); // Backward compatiblity $Author = new Author(); $Post = $this->getMock('Post', array('afterFind'), array(), '', true); $Post->expects($this->once())->method('afterFind')->with($expected['Post'], $this->isFalse())->will($this->returnArgument(0)); $Post->useConsistentAfterFind = false; $Author->bindModel(array('hasMany' => array('Post' => array('limit' => 2, 'order' => 'Post.id')))); $Author->Post = $Post; $result = $Author->find('first', array('conditions' => array('Author.id' => 1), 'recursive' => 1)); $this->assertEquals($expected, $result); } /** * Test that afterFind is called correctly for 'joins' * * @return void */ public function testJoinsAfterFind() { $this->loadFixtures('Article', 'User'); $User = new User(); $User->bindModel(array('hasOne' => array('Article'))); $Article = $this->getMock('Article', array('afterFind'), array(), '', true); $Article->expects($this->once()) ->method('afterFind') ->with( array( 0 => array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ) ) ), $this->isFalse() ) ->will($this->returnArgument(0)); $User->Article = $Article; $User->find('first', array( 'fields' => array( 'Article.id', 'Article.user_id', 'Article.title', 'Article.body', 'Article.published', 'Article.created', 'Article.updated' ), 'conditions' => array('User.id' => 1), 'recursive' => -1, 'joins' => array( array( 'table' => 'articles', 'alias' => 'Article', 'type' => 'LEFT', 'conditions' => array( 'Article.user_id = User.id' ), ) ), 'order' => array('Article.id') )); } /** * Test that afterFind is called correctly for 'hasOne' association. * * @return void */ public function testHasOneAfterFind() { $this->loadFixtures('Article', 'User', 'Comment'); $User = new User(); $User->bindModel(array('hasOne' => array('Article'))); $Article = $this->getMock('Article', array('afterFind'), array(), '', true); $Article->unbindModel(array( 'belongsTo' => array('User'), 'hasMany' => array('Comment'), 'hasAndBelongsToMany' => array('Tag') )); $Article->bindModel(array( 'hasOne' => array('Comment'), )); $Article->expects($this->once()) ->method('afterFind') ->with( $this->equalTo( array( 0 => array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Comment' => array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', ) ) ) ) ), $this->isFalse() ) ->will($this->returnArgument(0)); $User->Article = $Article; $User->find('first', array('conditions' => array('User.id' => 1), 'recursive' => 2)); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Datasource/Session/000077500000000000000000000000001265552240500231225ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Model/Datasource/Session/CacheSessionTest.php000066400000000000000000000055051265552240500270470ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://cakephp.org CakePHP(tm) Project * @package Cake.Test.Case.Model.Datasource.Session * @since CakePHP(tm) v 2.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('CakeSession', 'Model/Datasource'); App::uses('CacheSession', 'Model/Datasource/Session'); class_exists('CakeSession'); /** * Class CacheSessionTest * * @package Cake.Test.Case.Model.Datasource.Session */ class CacheSessionTest extends CakeTestCase { protected static $_sessionBackup; /** * test case startup * * @return void */ public static function setupBeforeClass() { Cache::config('session_test', array( 'engine' => 'File', 'prefix' => 'session_test_' )); static::$_sessionBackup = Configure::read('Session'); Configure::write('Session.handler.config', 'session_test'); } /** * cleanup after test case. * * @return void */ public static function teardownAfterClass() { Cache::clear(false, 'session_test'); Cache::drop('session_test'); Configure::write('Session', static::$_sessionBackup); } /** * setup * * @return void */ public function setUp() { parent::setUp(); $this->storage = new CacheSession(); } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); unset($this->storage); } /** * test open * * @return void */ public function testOpen() { $this->assertTrue($this->storage->open()); } /** * test write() * * @return void */ public function testWrite() { $this->storage->write('abc', 'Some value'); $this->assertEquals('Some value', Cache::read('abc', 'session_test'), 'Value was not written.'); $this->assertFalse(Cache::read('abc', 'default'), 'Cache should only write to the given config.'); } /** * test reading. * * @return void */ public function testRead() { $this->storage->write('test_one', 'Some other value'); $this->assertEquals('Some other value', $this->storage->read('test_one'), 'Incorrect value.'); $this->storage->write('test_two', 0); $this->assertEquals(0, $this->storage->read('test_two')); } /** * test destroy * * @return void */ public function testDestroy() { $this->storage->write('test_one', 'Some other value'); $this->assertTrue($this->storage->destroy('test_one'), 'Value was not deleted.'); $this->assertFalse(Cache::read('test_one', 'session_test'), 'Value stuck around.'); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Datasource/Session/DatabaseSessionTest.php000066400000000000000000000122501265552240500275430ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://cakephp.org CakePHP(tm) Project * @package Cake.Test.Case.Model.Datasource.Session * @since CakePHP(tm) v 2.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Model', 'Model'); App::uses('CakeSession', 'Model/Datasource'); App::uses('DatabaseSession', 'Model/Datasource/Session'); class_exists('CakeSession'); /** * Class SessionTestModel * * @package Cake.Test.Case.Model.Datasource.Session */ class SessionTestModel extends Model { public $useTable = 'sessions'; } /** * Database session test. * * @package Cake.Test.Case.Model.Datasource.Session */ class DatabaseSessionTest extends CakeTestCase { protected static $_sessionBackup; /** * fixtures * * @var string */ public $fixtures = array('core.session'); /** * test case startup * * @return void */ public static function setupBeforeClass() { static::$_sessionBackup = Configure::read('Session'); Configure::write('Session.handler', array( 'model' => 'SessionTestModel', )); Configure::write('Session.timeout', 100); } /** * cleanup after test case. * * @return void */ public static function teardownAfterClass() { Configure::write('Session', static::$_sessionBackup); } /** * setUp * * @return void */ public function setUp() { parent::setUp(); $this->storage = new DatabaseSession(); } /** * tearDown * * @return void */ public function tearDown() { unset($this->storage); ClassRegistry::flush(); parent::tearDown(); } /** * test that constructor sets the right things up. * * @return void */ public function testConstructionSettings() { ClassRegistry::flush(); new DatabaseSession(); $session = ClassRegistry::getObject('session'); $this->assertInstanceOf('SessionTestModel', $session); $this->assertEquals('Session', $session->alias); $this->assertEquals('test', $session->useDbConfig); $this->assertEquals('sessions', $session->useTable); } /** * test opening the session * * @return void */ public function testOpen() { $this->assertTrue($this->storage->open()); } /** * test write() * * @return void */ public function testWrite() { $this->storage->write('foo', 'Some value'); $this->assertEquals($this->storage->read('foo'), 'Some value'); } /** * testReadAndWriteWithDatabaseStorage method * * @return void */ public function testWriteEmptySessionId() { $result = $this->storage->write('', 'This is a Test'); $this->assertFalse($result); } /** * test read() * * @return void */ public function testRead() { $this->storage->write('foo', 'Some value'); $this->assertEquals($this->storage->read('foo'), 'Some value'); $this->storage->write('bar', 0); $this->assertEquals(0, $this->storage->read('bar')); $this->assertSame('', $this->storage->read('made up value')); } /** * test blowing up the session. * * @return void */ public function testDestroy() { $this->storage->write('foo', 'Some value'); $this->assertTrue($this->storage->destroy('foo'), 'Destroy failed'); $this->assertSame($this->storage->read('foo'), ''); } /** * test the garbage collector * * @return void */ public function testGc() { ClassRegistry::flush(); Configure::write('Session.timeout', 0); $storage = new DatabaseSession(); $storage->write('foo', 'Some value'); sleep(1); $storage->gc(); $this->assertSame($storage->read('foo'), ''); } /** * testConcurrentInsert * * @return void */ public function testConcurrentInsert() { $this->skipIf( $this->db instanceof Sqlite, 'Sqlite does not throw exceptions when attempting to insert a duplicate primary key' ); ClassRegistry::removeObject('Session'); $mockedModel = $this->getMockForModel( 'SessionTestModel', array('exists'), array('alias' => 'MockedSessionTestModel', 'table' => 'sessions') ); Configure::write('Session.handler.model', 'MockedSessionTestModel'); $counter = 0; // First save $mockedModel->expects($this->at($counter++)) ->method('exists') ->will($this->returnValue(false)); // Second save $mockedModel->expects($this->at($counter++)) ->method('exists') ->will($this->returnValue(false)); // Second save retry $mockedModel->expects($this->at($counter++)) ->method('exists') ->will($this->returnValue(true)); // Datasource exists check $mockedModel->expects($this->at($counter++)) ->method('exists') ->will($this->returnValue(true)); $this->storage = new DatabaseSession(); $this->storage->write('foo', 'Some value'); $return = $this->storage->read('foo'); $this->assertSame('Some value', $return); $this->storage->write('foo', 'Some other value'); $return = $this->storage->read('foo'); $this->assertSame('Some other value', $return); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/ModelCrossSchemaHabtmTest.php000066400000000000000000000145151265552240500251330ustar00rootroot00000000000000 false on *both* database connections, * or one connection will step on the other. * * CakePHP(tm) Tests * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model * @since CakePHP(tm) v 2.1 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ require_once dirname(__FILE__) . DS . 'ModelTestBase.php'; /** * Class ModelCrossSchemaHabtmTest * * @package Cake.Test.Case.Model */ class ModelCrossSchemaHabtmTest extends BaseModelTest { /** * Fixtures to be used * * @var array */ public $fixtures = array( 'core.player', 'core.guild', 'core.guilds_player', 'core.armor', 'core.armors_player', ); /** * Don't drop tables if they exist * * @var bool */ public $dropTables = false; /** * Don't auto load fixtures * * @var bool */ public $autoFixtures = false; /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->_checkConfigs(); } /** * Check if primary and secondary test databases are configured. * * @return void */ protected function _checkConfigs() { $config = ConnectionManager::enumConnectionObjects(); $this->skipIf($this->db instanceof Sqlite, 'This test is not compatible with Sqlite.'); $this->skipIf( !isset($config['test']) || !isset($config['test2']), 'Primary and secondary test databases not configured, ' . 'skipping cross-database join tests.' . ' To run these tests, you must define $test and $test2 in your database configuration.' ); } /** * testModelDatasources method * * @return void */ public function testModelDatasources() { $this->loadFixtures('Player', 'Guild', 'GuildsPlayer'); $Player = ClassRegistry::init('Player'); $this->assertEquals('test', $Player->useDbConfig); $this->assertEquals('test', $Player->Guild->useDbConfig); $this->assertEquals('test2', $Player->GuildsPlayer->useDbConfig); $this->assertEquals('test', $Player->getDataSource()->configKeyName); $this->assertEquals('test', $Player->Guild->getDataSource()->configKeyName); $this->assertEquals('test2', $Player->GuildsPlayer->getDataSource()->configKeyName); } /** * testHabtmFind method * * @return void */ public function testHabtmFind() { $this->loadFixtures('Player', 'Guild', 'GuildsPlayer'); $Player = ClassRegistry::init('Player'); $players = $Player->find('all', array( 'fields' => array('id', 'name'), 'contain' => array( 'Guild' => array( 'conditions' => array( 'Guild.name' => 'Wizards', ), ), ), )); $this->assertEquals(4, count($players)); $wizards = Hash::extract($players, '{n}.Guild.{n}[name=Wizards]'); $this->assertEquals(1, count($wizards)); $players = $Player->find('all', array( 'fields' => array('id', 'name'), 'conditions' => array( 'Player.id' => 1, ), )); $this->assertEquals(1, count($players)); $wizards = Hash::extract($players, '{n}.Guild.{n}'); $this->assertEquals(2, count($wizards)); } /** * testHabtmSave method * * @return void */ public function testHabtmSave() { $this->loadFixtures('Player', 'Guild', 'GuildsPlayer'); $Player = ClassRegistry::init('Player'); $players = $Player->find('count'); $this->assertEquals(4, $players); $player = $Player->create(array( 'name' => 'rchavik', )); $results = $Player->saveAll($player, array('validate' => 'first')); $this->assertNotSame(false, $results); $count = $Player->find('count'); $this->assertEquals(5, $count); $count = $Player->GuildsPlayer->find('count'); $this->assertEquals(3, $count); $player = $Player->findByName('rchavik'); $this->assertEmpty($player['Guild']); $player['Guild']['Guild'] = array(1, 2, 3); $Player->save($player); $player = $Player->findByName('rchavik'); $this->assertEquals(3, count($player['Guild'])); $players = $Player->find('all', array( 'contain' => array( 'conditions' => array( 'Guild.name' => 'Rangers', ), ), )); $rangers = Hash::extract($players, '{n}.Guild.{n}[name=Rangers]'); $this->assertEquals(2, count($rangers)); } /** * testHabtmWithThreeDatabases method * * @return void */ public function testHabtmWithThreeDatabases() { $config = ConnectionManager::enumConnectionObjects(); $this->skipIf( !isset($config['test']) || !isset($config['test2']) || !isset($config['test_database_three']), 'Primary, secondary, and tertiary test databases not configured,' . ' skipping test. To run these tests, you must define ' . '$test, $test2, and $test_database_three in your database configuration.' ); $this->loadFixtures('Player', 'Guild', 'GuildsPlayer', 'Armor', 'ArmorsPlayer'); $Player = ClassRegistry::init('Player'); $Player->bindModel(array( 'hasAndBelongsToMany' => array( 'Armor' => array( 'with' => 'ArmorsPlayer', 'unique' => true, ), ), ), false); $this->assertEquals('test', $Player->useDbConfig); $this->assertEquals('test2', $Player->Armor->useDbConfig); $this->assertEquals('test_database_three', $Player->ArmorsPlayer->useDbConfig); $players = $Player->find('count'); $this->assertEquals(4, $players); $spongebob = $Player->create(array( 'id' => 10, 'name' => 'spongebob', )); $spongebob['Armor'] = array('Armor' => array(1, 2, 3, 4)); $result = $Player->save($spongebob); $expected = array( 'Player' => array( 'id' => 10, 'name' => 'spongebob', ), 'Armor' => array( 'Armor' => array( 1, 2, 3, 4, ), ), ); unset($result['Player']['created']); unset($result['Player']['updated']); $this->assertEquals($expected, $result); $spongebob = $Player->find('all', array( 'conditions' => array( 'Player.id' => 10, ) )); $spongeBobsArmors = Hash::extract($spongebob, '{n}.Armor.{n}'); $this->assertEquals(4, count($spongeBobsArmors)); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/ModelDeleteTest.php000066400000000000000000000606661265552240500231570ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ require_once dirname(__FILE__) . DS . 'ModelTestBase.php'; /** * ModelDeleteTest * * @package Cake.Test.Case.Model */ class ModelDeleteTest extends BaseModelTest { /** * testDeleteHabtmReferenceWithConditions method * * @return void */ public function testDeleteHabtmReferenceWithConditions() { $this->loadFixtures('Portfolio', 'Item', 'ItemsPortfolio', 'Syfile', 'Image'); $Portfolio = new Portfolio(); $Portfolio->hasAndBelongsToMany['Item']['conditions'] = array('ItemsPortfolio.item_id >' => 1); $result = $Portfolio->find('first', array( 'conditions' => array('Portfolio.id' => 1) )); $expected = array( array( 'id' => 3, 'syfile_id' => 3, 'published' => false, 'name' => 'Item 3', 'ItemsPortfolio' => array( 'id' => 3, 'item_id' => 3, 'portfolio_id' => 1 )), array( 'id' => 4, 'syfile_id' => 4, 'published' => false, 'name' => 'Item 4', 'ItemsPortfolio' => array( 'id' => 4, 'item_id' => 4, 'portfolio_id' => 1 )), array( 'id' => 5, 'syfile_id' => 5, 'published' => false, 'name' => 'Item 5', 'ItemsPortfolio' => array( 'id' => 5, 'item_id' => 5, 'portfolio_id' => 1 ))); $this->assertEquals($expected, $result['Item']); $result = $Portfolio->ItemsPortfolio->find('all', array( 'conditions' => array('ItemsPortfolio.portfolio_id' => 1) )); $expected = array( array( 'ItemsPortfolio' => array( 'id' => 1, 'item_id' => 1, 'portfolio_id' => 1 )), array( 'ItemsPortfolio' => array( 'id' => 3, 'item_id' => 3, 'portfolio_id' => 1 )), array( 'ItemsPortfolio' => array( 'id' => 4, 'item_id' => 4, 'portfolio_id' => 1 )), array( 'ItemsPortfolio' => array( 'id' => 5, 'item_id' => 5, 'portfolio_id' => 1 ))); $this->assertEquals($expected, $result); $Portfolio->delete(1); $result = $Portfolio->find('first', array( 'conditions' => array('Portfolio.id' => 1) )); $this->assertSame(array(), $result); $result = $Portfolio->ItemsPortfolio->find('all', array( 'conditions' => array('ItemsPortfolio.portfolio_id' => 1) )); $this->assertSame(array(), $result); } /** * testDeleteArticleBLinks method * * @return void */ public function testDeleteArticleBLinks() { $this->loadFixtures('Article', 'ArticlesTag', 'Tag', 'User'); $TestModel = new ArticleB(); $result = $TestModel->ArticlesTag->find('all'); $expected = array( array('ArticlesTag' => array('article_id' => '1', 'tag_id' => '1')), array('ArticlesTag' => array('article_id' => '1', 'tag_id' => '2')), array('ArticlesTag' => array('article_id' => '2', 'tag_id' => '1')), array('ArticlesTag' => array('article_id' => '2', 'tag_id' => '3')) ); $this->assertEquals($expected, $result); $TestModel->delete(1); $result = $TestModel->ArticlesTag->find('all'); $expected = array( array('ArticlesTag' => array('article_id' => '2', 'tag_id' => '1')), array('ArticlesTag' => array('article_id' => '2', 'tag_id' => '3')) ); $this->assertEquals($expected, $result); } /** * testDeleteDependentWithConditions method * * @return void */ public function testDeleteDependentWithConditions() { $this->loadFixtures('Cd', 'Book', 'OverallFavorite'); $Cd = new Cd(); $Book = new Book(); $OverallFavorite = new OverallFavorite(); $Cd->delete(1); $result = $OverallFavorite->find('all', array( 'fields' => array('model_type', 'model_id', 'priority') )); $expected = array( array( 'OverallFavorite' => array( 'model_type' => 'Book', 'model_id' => 1, 'priority' => 2 ))); $this->assertTrue(is_array($result)); $this->assertEquals($expected, $result); $Book->delete(1); $result = $OverallFavorite->find('all', array( 'fields' => array('model_type', 'model_id', 'priority') )); $expected = array(); $this->assertTrue(is_array($result)); $this->assertEquals($expected, $result); } /** * testDel method * * @return void */ public function testDelete() { $this->loadFixtures('Article', 'Comment', 'Attachment'); $TestModel = new Article(); $result = $TestModel->delete(2); $this->assertTrue($result); $result = $TestModel->read(null, 2); $this->assertSame(array(), $result); $TestModel->recursive = -1; $result = $TestModel->find('all', array( 'fields' => array('id', 'title') )); $expected = array( array('Article' => array( 'id' => 1, 'title' => 'First Article' )), array('Article' => array( 'id' => 3, 'title' => 'Third Article' ))); $this->assertEquals($expected, $result); $result = $TestModel->delete(3); $this->assertTrue($result); $result = $TestModel->read(null, 3); $this->assertSame(array(), $result); $TestModel->recursive = -1; $result = $TestModel->find('all', array( 'fields' => array('id', 'title') )); $expected = array( array('Article' => array( 'id' => 1, 'title' => 'First Article' ))); $this->assertEquals($expected, $result); // make sure deleting a non-existent record doesn't break save() // ticket #6293 $this->loadFixtures('Uuid'); $Uuid = new Uuid(); $data = array( 'B607DAB9-88A2-46CF-B57C-842CA9E3B3B3', '52C8865C-10EE-4302-AE6C-6E7D8E12E2C8', '8208C7FE-E89C-47C5-B378-DED6C271F9B8'); foreach ($data as $id) { $Uuid->save(array('id' => $id)); } $Uuid->delete('52C8865C-10EE-4302-AE6C-6E7D8E12E2C8'); $Uuid->delete('52C8865C-10EE-4302-AE6C-6E7D8E12E2C8'); foreach ($data as $id) { $Uuid->save(array('id' => $id)); } $result = $Uuid->find('all', array( 'conditions' => array('id' => $data), 'fields' => array('id'), 'order' => 'id')); $expected = array( array('Uuid' => array( 'id' => '52C8865C-10EE-4302-AE6C-6E7D8E12E2C8')), array('Uuid' => array( 'id' => '8208C7FE-E89C-47C5-B378-DED6C271F9B8')), array('Uuid' => array( 'id' => 'B607DAB9-88A2-46CF-B57C-842CA9E3B3B3'))); $this->assertEquals($expected, $result); } /** * test that delete() updates the correct records counterCache() records. * * @return void */ public function testDeleteUpdatingCounterCacheCorrectly() { $this->loadFixtures('CounterCacheUser', 'CounterCachePost'); $User = new CounterCacheUser(); $User->Post->delete(3); $result = $User->read(null, 301); $this->assertEquals(0, $result['User']['post_count']); $result = $User->read(null, 66); $this->assertEquals(2, $result['User']['post_count']); } /** * testDeleteAll method * * @return void */ public function testDeleteAll() { $this->loadFixtures('Article'); $TestModel = new Article(); $data = array('Article' => array( 'user_id' => 2, 'id' => 4, 'title' => 'Fourth Article', 'published' => 'N' )); $result = $TestModel->set($data) && $TestModel->save(); $this->assertTrue($result); $data = array('Article' => array( 'user_id' => 2, 'id' => 5, 'title' => 'Fifth Article', 'published' => 'Y' )); $result = $TestModel->set($data) && $TestModel->save(); $this->assertTrue($result); $data = array('Article' => array( 'user_id' => 1, 'id' => 6, 'title' => 'Sixth Article', 'published' => 'N' )); $result = $TestModel->set($data) && $TestModel->save(); $this->assertTrue($result); $TestModel->recursive = -1; $result = $TestModel->find('all', array( 'fields' => array('id', 'user_id', 'title', 'published'), 'order' => array('Article.id' => 'ASC') )); $expected = array( array('Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'published' => 'Y' )), array('Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'published' => 'Y' )), array('Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'published' => 'Y')), array('Article' => array( 'id' => 4, 'user_id' => 2, 'title' => 'Fourth Article', 'published' => 'N' )), array('Article' => array( 'id' => 5, 'user_id' => 2, 'title' => 'Fifth Article', 'published' => 'Y' )), array('Article' => array( 'id' => 6, 'user_id' => 1, 'title' => 'Sixth Article', 'published' => 'N' ))); $this->assertEquals($expected, $result); $result = $TestModel->deleteAll(array('Article.published' => 'N')); $this->assertTrue($result); $TestModel->recursive = -1; $result = $TestModel->find('all', array( 'fields' => array('id', 'user_id', 'title', 'published'), 'order' => array('Article.id' => 'ASC') )); $expected = array( array('Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'published' => 'Y' )), array('Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'published' => 'Y' )), array('Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'published' => 'Y' )), array('Article' => array( 'id' => 5, 'user_id' => 2, 'title' => 'Fifth Article', 'published' => 'Y' ))); $this->assertEquals($expected, $result); $data = array('Article.user_id' => array(2, 3)); $result = $TestModel->deleteAll($data, true, true); $this->assertTrue($result); $TestModel->recursive = -1; $result = $TestModel->find('all', array( 'fields' => array('id', 'user_id', 'title', 'published'), 'order' => array('Article.id' => 'ASC') )); $expected = array( array('Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'published' => 'Y' )), array('Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'published' => 'Y' ))); $this->assertEquals($expected, $result); $result = $TestModel->deleteAll(array('Article.user_id' => 999)); $this->assertTrue($result, 'deleteAll returned false when all no records matched conditions. %s'); } /** * testDeleteAllUnknownColumn method * * @expectedException PDOException * @return void */ public function testDeleteAllUnknownColumn() { $this->loadFixtures('Article'); $TestModel = new Article(); $result = $TestModel->deleteAll(array('Article.non_existent_field' => 999)); $this->assertFalse($result, 'deleteAll returned true when find query generated sql error. %s'); } /** * testDeleteAllFailedFind method * * Eg: Behavior callback stops the event, find returns null * * @return void */ public function testDeleteAllFailedFind() { $this->loadFixtures('Article'); $TestModel = $this->getMock('Article', array('find')); $TestModel->expects($this->once()) ->method('find') ->will($this->returnValue(null)); $result = $TestModel->deleteAll(array('Article.user_id' => 999)); $this->assertFalse($result); } /** * testDeleteAllMultipleRowsPerId method * * Ensure find done in deleteAll only returns distinct ids. A wacky combination * of association and conditions can sometimes generate multiple rows per id. * * @return void */ public function testDeleteAllMultipleRowsPerId() { $this->loadFixtures('Article', 'User'); $TestModel = new Article(); $TestModel->unbindModel(array( 'belongsTo' => array('User'), 'hasMany' => array('Comment'), 'hasAndBelongsToMany' => array('Tag') ), false); $TestModel->bindModel(array( 'belongsTo' => array( 'User' => array( 'foreignKey' => false, 'conditions' => array( 'Article.user_id = 1' ) ) ) ), false); $result = $TestModel->deleteAll( array('Article.user_id' => array(1, 3)), true, true ); $this->assertTrue($result); } /** * testDeleteAllWithOrderProperty * * Ensure find done in deleteAll works with models that has $order property set * * @return void */ public function testDeleteAllWithOrderProperty() { $this->loadFixtures('Article', 'User'); $TestModel = new Article(); $TestModel->order = 'Article.published desc'; $TestModel->unbindModel(array( 'belongsTo' => array('User'), 'hasMany' => array('Comment'), 'hasAndBelongsToMany' => array('Tag') ), false); $result = $TestModel->deleteAll( array('Article.user_id' => array(1, 3)), true, true ); $this->assertTrue($result); } /** * testRecursiveDel method * * @return void */ public function testRecursiveDel() { $this->loadFixtures('Article', 'Comment', 'Attachment'); $TestModel = new Article(); $result = $TestModel->delete(2); $this->assertTrue($result); $TestModel->recursive = 2; $result = $TestModel->read(null, 2); $this->assertSame(array(), $result); $result = $TestModel->Comment->read(null, 5); $this->assertSame(array(), $result); $result = $TestModel->Comment->read(null, 6); $this->assertSame(array(), $result); $result = $TestModel->Comment->Attachment->read(null, 1); $this->assertSame(array(), $result); $result = $TestModel->find('count'); $this->assertEquals(2, $result); $result = $TestModel->Comment->find('count'); $this->assertEquals(4, $result); $result = $TestModel->Comment->Attachment->find('count'); $this->assertEquals(0, $result); } /** * testDependentExclusiveDelete method * * @return void */ public function testDependentExclusiveDelete() { $this->loadFixtures('Article', 'Comment'); $TestModel = new Article10(); $result = $TestModel->find('all'); $this->assertEquals(4, count($result[0]['Comment'])); $this->assertEquals(2, count($result[1]['Comment'])); $this->assertEquals(6, $TestModel->Comment->find('count')); $TestModel->delete(1); $this->assertEquals(2, $TestModel->Comment->find('count')); } /** * testDeleteLinks method * * @return void */ public function testDeleteLinks() { $this->loadFixtures('Article', 'ArticlesTag', 'Tag'); $TestModel = new Article(); $result = $TestModel->ArticlesTag->find('all'); $expected = array( array('ArticlesTag' => array( 'article_id' => '1', 'tag_id' => '1' )), array('ArticlesTag' => array( 'article_id' => '1', 'tag_id' => '2' )), array('ArticlesTag' => array( 'article_id' => '2', 'tag_id' => '1' )), array('ArticlesTag' => array( 'article_id' => '2', 'tag_id' => '3' ))); $this->assertEquals($expected, $result); $TestModel->delete(1); $result = $TestModel->ArticlesTag->find('all'); $expected = array( array('ArticlesTag' => array( 'article_id' => '2', 'tag_id' => '1' )), array('ArticlesTag' => array( 'article_id' => '2', 'tag_id' => '3' ))); $this->assertEquals($expected, $result); $result = $TestModel->deleteAll(array('Article.user_id' => 999)); $this->assertTrue($result, 'deleteAll returned false when all no records matched conditions. %s'); } /** * test that a plugin model as the 'with' model doesn't have issues * * @return void */ public function testDeleteLinksWithPLuginJoinModel() { $this->loadFixtures('Article', 'ArticlesTag', 'Tag'); $Article = new Article(); $Article->unbindModel(array('hasAndBelongsToMany' => array('Tag')), false); unset($Article->Tag, $Article->ArticleTags); $Article->bindModel(array('hasAndBelongsToMany' => array( 'Tag' => array('with' => 'TestPlugin.ArticlesTag') )), false); $Article->ArticlesTag->order = null; $this->assertTrue($Article->delete(1)); } /** * testDeleteDependent method * * @return void */ public function testDeleteDependent() { $this->loadFixtures('Bidding', 'BiddingMessage', 'Article', 'ArticlesTag', 'Comment', 'User', 'Attachment' ); $Bidding = new Bidding(); $result = $Bidding->find('all', array('order' => array('Bidding.id' => 'ASC'))); $expected = array( array( 'Bidding' => array('id' => 1, 'bid' => 'One', 'name' => 'Bid 1'), 'BiddingMessage' => array('bidding' => 'One', 'name' => 'Message 1'), ), array( 'Bidding' => array('id' => 2, 'bid' => 'Two', 'name' => 'Bid 2'), 'BiddingMessage' => array('bidding' => 'Two', 'name' => 'Message 2'), ), array( 'Bidding' => array('id' => 3, 'bid' => 'Three', 'name' => 'Bid 3'), 'BiddingMessage' => array('bidding' => 'Three', 'name' => 'Message 3'), ), array( 'Bidding' => array('id' => 4, 'bid' => 'Five', 'name' => 'Bid 5'), 'BiddingMessage' => array('bidding' => '', 'name' => ''), ), ); $this->assertEquals($expected, $result); $Bidding->delete(4, true); $result = $Bidding->find('all', array('order' => array('Bidding.id' => 'ASC'))); $expected = array( array( 'Bidding' => array('id' => 1, 'bid' => 'One', 'name' => 'Bid 1'), 'BiddingMessage' => array('bidding' => 'One', 'name' => 'Message 1'), ), array( 'Bidding' => array('id' => 2, 'bid' => 'Two', 'name' => 'Bid 2'), 'BiddingMessage' => array('bidding' => 'Two', 'name' => 'Message 2'), ), array( 'Bidding' => array('id' => 3, 'bid' => 'Three', 'name' => 'Bid 3'), 'BiddingMessage' => array('bidding' => 'Three', 'name' => 'Message 3'), ), ); $this->assertEquals($expected, $result); $Bidding->delete(2, true); $result = $Bidding->find('all', array('order' => array('Bidding.id' => 'ASC'))); $expected = array( array( 'Bidding' => array('id' => 1, 'bid' => 'One', 'name' => 'Bid 1'), 'BiddingMessage' => array('bidding' => 'One', 'name' => 'Message 1'), ), array( 'Bidding' => array('id' => 3, 'bid' => 'Three', 'name' => 'Bid 3'), 'BiddingMessage' => array('bidding' => 'Three', 'name' => 'Message 3'), ), ); $this->assertEquals($expected, $result); $result = $Bidding->BiddingMessage->find('all', array('order' => array('BiddingMessage.name' => 'ASC'))); $expected = array( array( 'BiddingMessage' => array('bidding' => 'One', 'name' => 'Message 1'), 'Bidding' => array('id' => 1, 'bid' => 'One', 'name' => 'Bid 1'), ), array( 'BiddingMessage' => array('bidding' => 'Three', 'name' => 'Message 3'), 'Bidding' => array('id' => 3, 'bid' => 'Three', 'name' => 'Bid 3'), ), array( 'BiddingMessage' => array('bidding' => 'Four', 'name' => 'Message 4'), 'Bidding' => array('id' => '', 'bid' => '', 'name' => ''), ), ); $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->assertTrue($result); $result = $Article->Comment->find('count', array( 'conditions' => array('Comment.article_id' => 1) )); $this->assertEquals(0, $result); } /** * test deleteLinks with Multiple habtm associations * * @return void */ public function testDeleteLinksWithMultipleHabtmAssociations() { $this->loadFixtures('JoinA', 'JoinB', 'JoinC', 'JoinAB', 'JoinAC'); $JoinA = new JoinA(); //create two new join records to expose the issue. $JoinA->JoinAsJoinC->create(array( 'join_a_id' => 1, 'join_c_id' => 2, )); $JoinA->JoinAsJoinC->save(); $JoinA->JoinAsJoinB->create(array( 'join_a_id' => 1, 'join_b_id' => 2, )); $JoinA->JoinAsJoinB->save(); $result = $JoinA->delete(1); $this->assertTrue($result, 'Delete failed %s'); $joinedBs = $JoinA->JoinAsJoinB->find('count', array( 'conditions' => array('JoinAsJoinB.join_a_id' => 1) )); $this->assertEquals(0, $joinedBs, 'JoinA/JoinB link records left over. %s'); $joinedBs = $JoinA->JoinAsJoinC->find('count', array( 'conditions' => array('JoinAsJoinC.join_a_id' => 1) )); $this->assertEquals(0, $joinedBs, 'JoinA/JoinC link records left over. %s'); } /** * testHabtmDeleteLinksWhenNoPrimaryKeyInJoinTable method * * @return void */ public function testHabtmDeleteLinksWhenNoPrimaryKeyInJoinTable() { $this->loadFixtures('Apple', 'Device', 'ThePaperMonkies'); $ThePaper = new ThePaper(); $ThePaper->id = 1; $ThePaper->save(array('Monkey' => array(2, 3))); $result = $ThePaper->findById(1); $expected = array( array( 'id' => '2', 'device_type_id' => '1', 'name' => 'Device 2', 'typ' => '1' ), array( 'id' => '3', 'device_type_id' => '1', 'name' => 'Device 3', 'typ' => '2' )); $this->assertEquals($expected, $result['Monkey']); $ThePaper = new ThePaper(); $ThePaper->id = 2; $ThePaper->save(array('Monkey' => array(2, 3))); $result = $ThePaper->findById(2); $expected = array( array( 'id' => '2', 'device_type_id' => '1', 'name' => 'Device 2', 'typ' => '1' ), array( 'id' => '3', 'device_type_id' => '1', 'name' => 'Device 3', 'typ' => '2' )); $this->assertEquals($expected, $result['Monkey']); $ThePaper->delete(1); $result = $ThePaper->findById(2); $expected = array( array( 'id' => '2', 'device_type_id' => '1', 'name' => 'Device 2', 'typ' => '1' ), array( 'id' => '3', 'device_type_id' => '1', 'name' => 'Device 3', 'typ' => '2' )); $this->assertEquals($expected, $result['Monkey']); } /** * test that beforeDelete returning false can abort deletion. * * @return void */ public function testBeforeDeleteDeleteAbortion() { $this->loadFixtures('Post'); $Model = new CallbackPostTestModel(); $Model->beforeDeleteReturn = false; $result = $Model->delete(1); $this->assertFalse($result); $exists = $Model->findById(1); $this->assertTrue(is_array($exists)); } /** * test for a habtm deletion error that occurs in postgres but should not. * And should not occur in any dbo. * * @return void */ public function testDeleteHabtmPostgresFailure() { $this->loadFixtures('Article', 'Tag', 'ArticlesTag'); $Article = ClassRegistry::init('Article'); $Article->hasAndBelongsToMany['Tag']['unique'] = true; $Tag = ClassRegistry::init('Tag'); $Tag->bindModel(array('hasAndBelongsToMany' => array( 'Article' => array( 'className' => 'Article', 'unique' => true ) )), true); // Article 1 should have Tag.1 and Tag.2 $before = $Article->find("all", array( "conditions" => array("Article.id" => 1), )); $this->assertEquals(2, count($before[0]['Tag']), 'Tag count for Article.id = 1 is incorrect, should be 2 %s'); // From now on, Tag #1 is only associated with Post #1 $submittedData = array( "Tag" => array("id" => 1, 'tag' => 'tag1'), "Article" => array( "Article" => array(1) ) ); $Tag->save($submittedData); // One more submission (The other way around) to make sure the reverse save looks good. $submittedData = array( "Article" => array("id" => 2, 'title' => 'second article'), "Tag" => array( "Tag" => array(2, 3) ) ); // ERROR: // Postgresql: DELETE FROM "articles_tags" WHERE tag_id IN ('1', '3') // MySQL: DELETE `ArticlesTag` FROM `articles_tags` AS `ArticlesTag` WHERE `ArticlesTag`.`article_id` = 2 AND `ArticlesTag`.`tag_id` IN (1, 3) $Article->save($submittedData); // Want to make sure Article #1 has Tag #1 and Tag #2 still. $after = $Article->find("all", array( "conditions" => array("Article.id" => 1), )); // Removing Article #2 from Tag #1 is all that should have happened. $this->assertEquals(count($before[0]["Tag"]), count($after[0]["Tag"])); } /** * test that deleting records inside the beforeDelete doesn't truncate the table. * * @return void */ public function testBeforeDeleteWipingTable() { $this->loadFixtures('Comment'); $Comment = new BeforeDeleteComment(); // Delete 3 records. $Comment->delete(4); $result = $Comment->find('count'); $this->assertTrue($result > 1, 'Comments are all gone.'); $Comment->create(array( 'article_id' => 1, 'user_id' => 2, 'comment' => 'new record', 'published' => 'Y' )); $Comment->save(); $Comment->delete(5); $result = $Comment->find('count'); $this->assertTrue($result > 1, 'Comments are all gone.'); } /** * test that deleting the same record from the beforeDelete and the delete doesn't truncate the table. * * @return void */ public function testBeforeDeleteWipingTableWithDuplicateDelete() { $this->loadFixtures('Comment'); $Comment = new BeforeDeleteComment(); $Comment->delete(1); $result = $Comment->find('count'); $this->assertTrue($result > 1, 'Comments are all gone.'); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/ModelIntegrationTest.php000066400000000000000000002164101265552240500242260ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ require_once dirname(__FILE__) . DS . 'ModelTestBase.php'; App::uses('DboSource', 'Model/Datasource'); App::uses('DboMock', 'Model/Datasource'); /** * DboMock class * A Dbo Source driver to mock a connection and a identity name() method */ class DboMock extends DboSource { /** * Returns the $field without modifications * * @return string */ public function name($field) { return $field; } /** * Returns true to fake a database connection * * @return bool true */ public function connect() { return true; } } /** * ModelIntegrationTest * * @package Cake.Test.Case.Model */ class ModelIntegrationTest extends BaseModelTest { /** * testAssociationLazyLoading * * @group lazyloading * @return void */ public function testAssociationLazyLoading() { $this->loadFixtures('ArticleFeaturedsTags'); $Article = new ArticleFeatured(); $this->assertTrue(isset($Article->belongsTo['User'])); $this->assertFalse(property_exists($Article, 'User')); $this->assertInstanceOf('User', $Article->User); $this->assertTrue(isset($Article->belongsTo['Category'])); $this->assertFalse(property_exists($Article, 'Category')); $this->assertTrue(isset($Article->Category)); $this->assertInstanceOf('Category', $Article->Category); $this->assertTrue(isset($Article->hasMany['Comment'])); $this->assertFalse(property_exists($Article, 'Comment')); $this->assertTrue(isset($Article->Comment)); $this->assertInstanceOf('Comment', $Article->Comment); $this->assertTrue(isset($Article->hasAndBelongsToMany['Tag'])); //There was not enough information to setup the association (joinTable and associationForeignKey) //so the model was not lazy loaded $this->assertTrue(property_exists($Article, 'Tag')); $this->assertTrue(isset($Article->Tag)); $this->assertInstanceOf('Tag', $Article->Tag); $this->assertFalse(property_exists($Article, 'ArticleFeaturedsTag')); $this->assertInstanceOf('AppModel', $Article->ArticleFeaturedsTag); $this->assertEquals('article_featureds_tags', $Article->hasAndBelongsToMany['Tag']['joinTable']); $this->assertEquals('tag_id', $Article->hasAndBelongsToMany['Tag']['associationForeignKey']); } /** * testAssociationLazyLoadWithHABTM * * @group lazyloading * @return void */ public function testAssociationLazyLoadWithHABTM() { $this->loadFixtures('FruitsUuidTag', 'ArticlesTag'); $this->db->cacheSources = false; $Article = new ArticleB(); $this->assertTrue(isset($Article->hasAndBelongsToMany['TagB'])); $this->assertFalse(property_exists($Article, 'TagB')); $this->assertInstanceOf('TagB', $Article->TagB); $this->assertFalse(property_exists($Article, 'ArticlesTag')); $this->assertInstanceOf('AppModel', $Article->ArticlesTag); $UuidTag = new UuidTag(); $this->assertTrue(isset($UuidTag->hasAndBelongsToMany['Fruit'])); $this->assertFalse(property_exists($UuidTag, 'Fruit')); $this->assertFalse(property_exists($UuidTag, 'FruitsUuidTag')); $this->assertTrue(isset($UuidTag->Fruit)); $this->assertFalse(property_exists($UuidTag, 'FruitsUuidTag')); $this->assertTrue(isset($UuidTag->FruitsUuidTag)); $this->assertInstanceOf('FruitsUuidTag', $UuidTag->FruitsUuidTag); } /** * testAssociationLazyLoadWithBindModel * * @group lazyloading * @return void */ public function testAssociationLazyLoadWithBindModel() { $this->loadFixtures('Article', 'User'); $Article = new ArticleB(); $this->assertFalse(isset($Article->belongsTo['User'])); $this->assertFalse(property_exists($Article, 'User')); $Article->bindModel(array('belongsTo' => array('User'))); $this->assertTrue(isset($Article->belongsTo['User'])); $this->assertFalse(property_exists($Article, 'User')); $this->assertInstanceOf('User', $Article->User); } /** * Tests that creating a model with no existent database table associated will throw an exception * * @expectedException MissingTableException * @return void */ public function testMissingTable() { $Article = new ArticleB(false, uniqid()); $Article->schema(); } /** * testPkInHAbtmLinkModelArticleB * * @return void */ public function testPkInHabtmLinkModelArticleB() { $this->loadFixtures('Article', 'Tag', 'ArticlesTag'); $TestModel = new ArticleB(); $this->assertEquals('article_id', $TestModel->ArticlesTag->primaryKey); } /** * Tests that $cacheSources is restored despite the settings on the model. * * @return void */ public function testCacheSourcesRestored() { $this->loadFixtures('JoinA', 'JoinB', 'JoinAB', 'JoinC', 'JoinAC'); $this->db->cacheSources = true; $TestModel = new JoinA(); $TestModel->cacheSources = false; $TestModel->setSource('join_as'); $this->assertTrue($this->db->cacheSources); $this->db->cacheSources = false; $TestModel = new JoinA(); $TestModel->cacheSources = true; $TestModel->setSource('join_as'); $this->assertFalse($this->db->cacheSources); } /** * testPkInHabtmLinkModel method * * @return void */ public function testPkInHabtmLinkModel() { //Test Nonconformant Models $this->loadFixtures('Content', 'ContentAccount', 'Account', 'JoinC', 'JoinAC', 'ItemsPortfolio'); $TestModel = new Content(); $this->assertEquals('iContentAccountsId', $TestModel->ContentAccount->primaryKey); //test conformant models with no PK in the join table $this->loadFixtures('Article', 'Tag'); $TestModel = new Article(); $this->assertEquals('article_id', $TestModel->ArticlesTag->primaryKey); //test conformant models with PK in join table $TestModel = new Portfolio(); $this->assertEquals('id', $TestModel->ItemsPortfolio->primaryKey); //test conformant models with PK in join table - join table contains extra field $this->loadFixtures('JoinA', 'JoinB', 'JoinAB'); $TestModel = new JoinA(); $this->assertEquals('id', $TestModel->JoinAsJoinB->primaryKey); } /** * testDynamicBehaviorAttachment method * * @return void */ public function testDynamicBehaviorAttachment() { $this->loadFixtures('Apple', 'Sample', 'Author'); $TestModel = new Apple(); $this->assertEquals(array(), $TestModel->Behaviors->loaded()); $TestModel->Behaviors->load('Tree', array('left' => 'left_field', 'right' => 'right_field')); $this->assertTrue(is_object($TestModel->Behaviors->Tree)); $this->assertEquals(array('Tree'), $TestModel->Behaviors->loaded()); $expected = array( 'parent' => 'parent_id', 'left' => 'left_field', 'right' => 'right_field', 'scope' => '1 = 1', 'type' => 'nested', '__parentChange' => false, 'recursive' => -1, 'level' => null ); $this->assertEquals($expected, $TestModel->Behaviors->Tree->settings['Apple']); $TestModel->Behaviors->load('Tree', array('enabled' => false)); $this->assertEquals($expected, $TestModel->Behaviors->Tree->settings['Apple']); $this->assertEquals(array('Tree'), $TestModel->Behaviors->loaded()); $TestModel->Behaviors->unload('Tree'); $this->assertEquals(array(), $TestModel->Behaviors->loaded()); $this->assertFalse(isset($TestModel->Behaviors->Tree)); } /** * testTreeWithContainable method * * @return void */ public function testTreeWithContainable() { $this->loadFixtures('Ad', 'Campaign'); $TestModel = new Ad(); $TestModel->Behaviors->load('Tree'); $TestModel->Behaviors->load('Containable'); $node = $TestModel->findById(2); $node['Ad']['parent_id'] = 1; $TestModel->save($node); $result = $TestModel->getParentNode(array('id' => 2, 'contain' => 'Campaign')); $this->assertTrue(array_key_exists('Campaign', $result)); $result = $TestModel->children(array('id' => 1, 'contain' => 'Campaign')); $this->assertTrue(array_key_exists('Campaign', $result[0])); $result = $TestModel->getPath(array('id' => 2, 'contain' => 'Campaign')); $this->assertTrue(array_key_exists('Campaign', $result[0])); $this->assertTrue(array_key_exists('Campaign', $result[1])); } /** * testFindWithJoinsOption method * * @return void */ public function testFindWithJoinsOption() { $this->loadFixtures('Article', 'User'); $TestUser = new User(); $options = array( 'fields' => array( 'user', 'Article.published', ), 'joins' => array( array( 'table' => 'articles', 'alias' => 'Article', 'type' => 'LEFT', 'conditions' => array( 'User.id = Article.user_id', ), ), ), 'group' => array('User.user', 'Article.published'), 'recursive' => -1, 'order' => array('User.user') ); $result = $TestUser->find('all', $options); $expected = array( array('User' => array('user' => 'garrett'), 'Article' => array('published' => '')), array('User' => array('user' => 'larry'), 'Article' => array('published' => 'Y')), array('User' => array('user' => 'mariano'), 'Article' => array('published' => 'Y')), array('User' => array('user' => 'nate'), 'Article' => array('published' => '')) ); $this->assertEquals($expected, $result); } /** * Tests cross database joins. Requires $test and $test2 to both be set in DATABASE_CONFIG * NOTE: When testing on MySQL, you must set 'persistent' => false on *both* database connections, * or one connection will step on the other. * * @return void */ public function testCrossDatabaseJoins() { $config = ConnectionManager::enumConnectionObjects(); $skip = (!isset($config['test']) || !isset($config['test2'])); if ($skip) { $this->markTestSkipped('Primary and secondary test databases not configured, skipping cross-database join tests. To run theses tests defined $test and $test2 in your database configuration.' ); } $this->loadFixtures('Article', 'Tag', 'ArticlesTag', 'User', 'Comment'); $TestModel = new Article(); $expected = array( array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Comment' => array( array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), array( 'id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31' ), array( 'id' => '3', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), array( 'id' => '4', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' )), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ))), array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'Comment' => array( array( 'id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ), array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' )), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ))), array( 'Article' => array( 'id' => '3', 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Comment' => array(), 'Tag' => array() )); $this->assertEquals($expected, $TestModel->find('all')); $db2 = ConnectionManager::getDataSource('test2'); $this->fixtureManager->loadSingle('User', $db2); $this->fixtureManager->loadSingle('Comment', $db2); $this->assertEquals(3, $TestModel->find('count')); $TestModel->User->setDataSource('test2'); $TestModel->Comment->setDataSource('test2'); foreach ($expected as $key => $value) { unset($value['Comment'], $value['Tag']); $expected[$key] = $value; } $TestModel->recursive = 0; $result = $TestModel->find('all'); $this->assertEquals($expected, $result); foreach ($expected as $key => $value) { unset($value['Comment'], $value['Tag']); $expected[$key] = $value; } $TestModel->recursive = 0; $result = $TestModel->find('all'); $this->assertEquals($expected, $result); $result = Hash::extract($TestModel->User->find('all'), '{n}.User.id'); $this->assertEquals(array('1', '2', '3', '4'), $result); $this->assertEquals($expected, $TestModel->find('all')); $TestModel->Comment->unbindModel(array('hasOne' => array('Attachment'))); $expected = array( array( 'Comment' => array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), 'User' => array( 'id' => '2', 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' )), array( 'Comment' => array( 'id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31' ), 'User' => array( 'id' => '4', 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ), 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' )), array( 'Comment' => array( 'id' => '3', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' )), array( 'Comment' => array( 'id' => '4', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ), 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' )), array( 'Comment' => array( 'id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ), 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' )), array( 'Comment' => array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' ), 'User' => array( 'id' => '2', 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ))); $this->assertEquals($expected, $TestModel->Comment->find('all')); } /** * test HABM operations without clobbering existing records #275 * * @return void */ public function testHABTMKeepExisting() { $this->loadFixtures('Site', 'Domain', 'DomainsSite'); $Site = new Site(); $results = $Site->find('count'); $expected = 3; $this->assertEquals($expected, $results); $data = $Site->findById(1); // include api.cakephp.org $data['Domain'] = array('Domain' => array(1, 2, 3)); $Site->save($data); $Site->id = 1; $results = $Site->read(); $expected = 3; // 3 domains belonging to cakephp $this->assertEquals($expected, count($results['Domain'])); $Site->id = 2; $results = $Site->read(); $expected = 2; // 2 domains belonging to markstory $this->assertEquals($expected, count($results['Domain'])); $Site->id = 3; $results = $Site->read(); $expected = 2; $this->assertEquals($expected, count($results['Domain'])); $results['Domain'] = array('Domain' => array(7)); $Site->save($results); // remove association from domain 6 $results = $Site->read(); $expected = 1; // only 1 domain left belonging to rchavik $this->assertEquals($expected, count($results['Domain'])); // add deleted domain back $results['Domain'] = array('Domain' => array(6, 7)); $Site->save($results); $results = $Site->read(); $expected = 2; // 2 domains belonging to rchavik $this->assertEquals($expected, count($results['Domain'])); $Site->DomainsSite->id = $results['Domain'][0]['DomainsSite']['id']; $Site->DomainsSite->saveField('active', true); $results = $Site->Domain->DomainsSite->find('count', array( 'conditions' => array( 'DomainsSite.active' => true, ), )); $expected = 5; $this->assertEquals($expected, $results); // activate api.cakephp.org $activated = $Site->DomainsSite->findByDomainId(3); $activated['DomainsSite']['active'] = true; $Site->DomainsSite->save($activated); $results = $Site->DomainsSite->find('count', array( 'conditions' => array( 'DomainsSite.active' => true, ), )); $expected = 6; $this->assertEquals($expected, $results); // remove 2 previously active domains, and leave $activated alone $data = array( 'Site' => array('id' => 1, 'name' => 'cakephp (modified)'), 'Domain' => array( 'Domain' => array(3), ) ); $Site->create($data); $Site->save($data); // tests that record is still identical prior to removal $Site->id = 1; $results = $Site->read(); unset($results['Domain'][0]['DomainsSite']['updated']); unset($activated['DomainsSite']['updated']); $this->assertEquals($activated['DomainsSite'], $results['Domain'][0]['DomainsSite']); } /** * testHABTMKeepExistingAlternateDataFormat * * @return void */ public function testHABTMKeepExistingAlternateDataFormat() { $this->loadFixtures('Site', 'Domain', 'DomainsSite'); $Site = new Site(); $expected = array( array( 'DomainsSite' => array( 'id' => 1, 'site_id' => 1, 'domain_id' => 1, 'active' => true, 'created' => '2007-03-17 01:16:23' ) ), array( 'DomainsSite' => array( 'id' => 2, 'site_id' => 1, 'domain_id' => 2, 'active' => true, 'created' => '2007-03-17 01:16:23' ) ) ); $result = $Site->DomainsSite->find('all', array( 'conditions' => array('DomainsSite.site_id' => 1), 'fields' => array( 'DomainsSite.id', 'DomainsSite.site_id', 'DomainsSite.domain_id', 'DomainsSite.active', 'DomainsSite.created' ), 'order' => 'DomainsSite.id' )); $this->assertEquals($expected, $result); $time = date('Y-m-d H:i:s'); $data = array( 'Site' => array( 'id' => 1 ), 'Domain' => array( array( 'site_id' => 1, 'domain_id' => 3, 'created' => $time, ), array( 'id' => 2, 'site_id' => 1, 'domain_id' => 2 ), ) ); $Site->save($data); $expected = array( array( 'DomainsSite' => array( 'id' => 2, 'site_id' => 1, 'domain_id' => 2, 'active' => true, 'created' => '2007-03-17 01:16:23' ) ), array( 'DomainsSite' => array( 'id' => 7, 'site_id' => 1, 'domain_id' => 3, 'active' => false, 'created' => $time ) ) ); $result = $Site->DomainsSite->find('all', array( 'conditions' => array('DomainsSite.site_id' => 1), 'fields' => array( 'DomainsSite.id', 'DomainsSite.site_id', 'DomainsSite.domain_id', 'DomainsSite.active', 'DomainsSite.created' ), 'order' => 'DomainsSite.id' )); $this->assertEquals($expected, $result); } /** * test HABM operations without clobbering existing records #275 * * @return void */ public function testHABTMKeepExistingWithThreeDbs() { $config = ConnectionManager::enumConnectionObjects(); $this->skipIf($this->db instanceof Sqlite, 'This test is not compatible with Sqlite.'); $this->skipIf( !isset($config['test']) || !isset($config['test2']) || !isset($config['test_database_three']), 'Primary, secondary, and tertiary test databases not configured, skipping test. To run this test define $test, $test2, and $test_database_three in your database configuration.' ); $this->loadFixtures('Player', 'Guild', 'GuildsPlayer', 'Armor', 'ArmorsPlayer'); $Player = ClassRegistry::init('Player'); $Player->bindModel(array( 'hasAndBelongsToMany' => array( 'Armor' => array( 'with' => 'ArmorsPlayer', 'unique' => 'keepExisting', ), ), ), false); $this->assertEquals('test', $Player->useDbConfig); $this->assertEquals('test', $Player->Guild->useDbConfig); $this->assertEquals('test2', $Player->Guild->GuildsPlayer->useDbConfig); $this->assertEquals('test2', $Player->Armor->useDbConfig); $this->assertEquals('test_database_three', $Player->ArmorsPlayer->useDbConfig); $players = $Player->find('all'); $this->assertEquals(4, count($players)); $playersGuilds = Hash::extract($players, '{n}.Guild.{n}.GuildsPlayer'); $this->assertEquals(3, count($playersGuilds)); $playersArmors = Hash::extract($players, '{n}.Armor.{n}.ArmorsPlayer'); $this->assertEquals(3, count($playersArmors)); unset($players); $larry = $Player->findByName('larry'); $larrysArmor = Hash::extract($larry, 'Armor.{n}.ArmorsPlayer'); $this->assertEquals(1, count($larrysArmor)); $larry['Guild']['Guild'] = array(1, 3); // larry joins another guild $larry['Armor']['Armor'] = array(2, 3); // purchases chainmail $Player->save($larry); unset($larry); $larry = $Player->findByName('larry'); $larrysGuild = Hash::extract($larry, 'Guild.{n}.GuildsPlayer'); $this->assertEquals(2, count($larrysGuild)); $larrysArmor = Hash::extract($larry, 'Armor.{n}.ArmorsPlayer'); $this->assertEquals(2, count($larrysArmor)); $Player->ArmorsPlayer->id = 3; $Player->ArmorsPlayer->saveField('broken', true); // larry's cloak broke $larry = $Player->findByName('larry'); $larrysCloak = Hash::extract($larry, 'Armor.{n}.ArmorsPlayer[armor_id=3]', $larry); $this->assertNotEmpty($larrysCloak); $this->assertTrue($larrysCloak[0]['broken']); // still broken } /** * testDisplayField method * * @return void */ public function testDisplayField() { $this->loadFixtures('Post', 'Comment', 'Person', 'User'); $Post = new Post(); $Comment = new Comment(); $Person = new Person(); $this->assertEquals('title', $Post->displayField); $this->assertEquals('name', $Person->displayField); $this->assertEquals('id', $Comment->displayField); } /** * testSchema method * * @return void */ public function testSchema() { $Post = new Post(); $result = $Post->schema(); $columns = array('id', 'author_id', 'title', 'body', 'published', 'created', 'updated'); $this->assertEquals($columns, array_keys($result)); $types = array('integer', 'integer', 'string', 'text', 'string', 'datetime', 'datetime'); $this->assertEquals(Hash::extract(array_values($result), '{n}.type'), $types); $result = $Post->schema('body'); $this->assertEquals('text', $result['type']); $this->assertNull($Post->schema('foo')); $this->assertEquals($Post->getColumnTypes(), array_combine($columns, $types)); } /** * Check schema() on a model with useTable = false; * * @return void */ public function testSchemaUseTableFalse() { $model = new TheVoid(); $result = $model->schema(); $this->assertNull($result); $result = $model->create(); $this->assertEmpty($result); } /** * data provider for time tests. * * @return array */ public static function timeProvider() { $db = ConnectionManager::getDataSource('test'); $now = $db->expression('NOW()'); return array( // blank array( array('hour' => '', 'min' => '', 'meridian' => ''), '' ), // missing hour array( array('hour' => '', 'min' => '00', 'meridian' => 'pm'), '' ), // all blank array( array('hour' => '', 'min' => '', 'sec' => ''), '' ), // set and empty merdian array( array('hour' => '1', 'min' => '00', 'meridian' => ''), '' ), // midnight array( array('hour' => '12', 'min' => '0', 'meridian' => 'am'), '00:00:00' ), array( array('hour' => '00', 'min' => '00'), '00:00:00' ), // 3am array( array('hour' => '03', 'min' => '04', 'sec' => '04'), '03:04:04' ), array( array('hour' => '3', 'min' => '4', 'sec' => '4'), '03:04:04' ), array( array('hour' => '03', 'min' => '4', 'sec' => '4'), '03:04:04' ), array( $now, $now ) ); } /** * test deconstruct with time fields. * * @dataProvider timeProvider * @return void */ public function testDeconstructFieldsTime($input, $result) { $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.'); $this->loadFixtures('Apple'); $TestModel = new Apple(); $data = array( 'Apple' => array( 'mytime' => $input ) ); $TestModel->data = null; $TestModel->set($data); $expected = array('Apple' => array('mytime' => $result)); $this->assertEquals($expected, $TestModel->data); } /** * testDeconstructFields with datetime, timestamp, and date fields * * @return void */ public function testDeconstructFieldsDateTime() { $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.'); $this->loadFixtures('Apple'); $TestModel = new Apple(); //test null/empty values first $data['Apple']['created']['year'] = ''; $data['Apple']['created']['month'] = ''; $data['Apple']['created']['day'] = ''; $data['Apple']['created']['hour'] = ''; $data['Apple']['created']['min'] = ''; $data['Apple']['created']['sec'] = ''; $TestModel->data = null; $TestModel->set($data); $expected = array('Apple' => array('created' => '')); $this->assertEquals($expected, $TestModel->data); $data = array(); $data['Apple']['date']['year'] = ''; $data['Apple']['date']['month'] = ''; $data['Apple']['date']['day'] = ''; $TestModel->data = null; $TestModel->set($data); $expected = array('Apple' => array('date' => '')); $this->assertEquals($expected, $TestModel->data); $data = array(); $data['Apple']['created']['year'] = '2007'; $data['Apple']['created']['month'] = '08'; $data['Apple']['created']['day'] = '20'; $data['Apple']['created']['hour'] = ''; $data['Apple']['created']['min'] = ''; $data['Apple']['created']['sec'] = ''; $TestModel->data = null; $TestModel->set($data); $expected = array('Apple' => array('created' => '2007-08-20 00:00:00')); $this->assertEquals($expected, $TestModel->data); $data = array(); $data['Apple']['created']['year'] = '2007'; $data['Apple']['created']['month'] = '08'; $data['Apple']['created']['day'] = '20'; $data['Apple']['created']['hour'] = '10'; $data['Apple']['created']['min'] = '12'; $data['Apple']['created']['sec'] = ''; $TestModel->data = null; $TestModel->set($data); $expected = array('Apple' => array('created' => '2007-08-20 10:12:00')); $this->assertEquals($expected, $TestModel->data); $data = array(); $data['Apple']['created']['year'] = '2007'; $data['Apple']['created']['month'] = ''; $data['Apple']['created']['day'] = '12'; $data['Apple']['created']['hour'] = '20'; $data['Apple']['created']['min'] = ''; $data['Apple']['created']['sec'] = ''; $TestModel->data = null; $TestModel->set($data); $expected = array('Apple' => array('created' => '')); $this->assertEquals($expected, $TestModel->data); $data = array(); $data['Apple']['created']['hour'] = '20'; $data['Apple']['created']['min'] = '33'; $TestModel->data = null; $TestModel->set($data); $expected = array('Apple' => array('created' => '')); $this->assertEquals($expected, $TestModel->data); $data = array(); $data['Apple']['created']['hour'] = '20'; $data['Apple']['created']['min'] = '33'; $data['Apple']['created']['sec'] = '33'; $TestModel->data = null; $TestModel->set($data); $expected = array('Apple' => array('created' => '')); $this->assertEquals($expected, $TestModel->data); $data = array(); $data['Apple']['created']['hour'] = '13'; $data['Apple']['created']['min'] = '00'; $data['Apple']['date']['year'] = '2006'; $data['Apple']['date']['month'] = '12'; $data['Apple']['date']['day'] = '25'; $TestModel->data = null; $TestModel->set($data); $expected = array( 'Apple' => array( 'created' => '', 'date' => '2006-12-25' )); $this->assertEquals($expected, $TestModel->data); $data = array(); $data['Apple']['created']['year'] = '2007'; $data['Apple']['created']['month'] = '08'; $data['Apple']['created']['day'] = '20'; $data['Apple']['created']['hour'] = '10'; $data['Apple']['created']['min'] = '12'; $data['Apple']['created']['sec'] = '09'; $data['Apple']['date']['year'] = '2006'; $data['Apple']['date']['month'] = '12'; $data['Apple']['date']['day'] = '25'; $TestModel->data = null; $TestModel->set($data); $expected = array( 'Apple' => array( 'created' => '2007-08-20 10:12:09', 'date' => '2006-12-25' )); $this->assertEquals($expected, $TestModel->data); $data = array(); $data['Apple']['created']['year'] = '--'; $data['Apple']['created']['month'] = '--'; $data['Apple']['created']['day'] = '--'; $data['Apple']['created']['hour'] = '--'; $data['Apple']['created']['min'] = '--'; $data['Apple']['created']['sec'] = '--'; $data['Apple']['date']['year'] = '--'; $data['Apple']['date']['month'] = '--'; $data['Apple']['date']['day'] = '--'; $TestModel->data = null; $TestModel->set($data); $expected = array('Apple' => array('created' => '', 'date' => '')); $this->assertEquals($expected, $TestModel->data); $data = array(); $data['Apple']['created']['year'] = '2007'; $data['Apple']['created']['month'] = '--'; $data['Apple']['created']['day'] = '20'; $data['Apple']['created']['hour'] = '10'; $data['Apple']['created']['min'] = '12'; $data['Apple']['created']['sec'] = '09'; $data['Apple']['date']['year'] = '2006'; $data['Apple']['date']['month'] = '12'; $data['Apple']['date']['day'] = '25'; $TestModel->data = null; $TestModel->set($data); $expected = array('Apple' => array('created' => '', 'date' => '2006-12-25')); $this->assertEquals($expected, $TestModel->data); $data = array(); $data['Apple']['date']['year'] = '2006'; $data['Apple']['date']['month'] = '12'; $data['Apple']['date']['day'] = '25'; $TestModel->data = null; $TestModel->set($data); $expected = array('Apple' => array('date' => '2006-12-25')); $this->assertEquals($expected, $TestModel->data); $db = ConnectionManager::getDataSource('test'); $data = array(); $data['Apple']['modified'] = $db->expression('NOW()'); $TestModel->data = null; $TestModel->set($data); $this->assertEquals($TestModel->data, $data); } /** * testTablePrefixSwitching method * * @return void */ public function testTablePrefixSwitching() { ConnectionManager::create('database1', array_merge($this->db->config, array('prefix' => 'aaa_') )); ConnectionManager::create('database2', array_merge($this->db->config, array('prefix' => 'bbb_') )); $db1 = ConnectionManager::getDataSource('database1'); $db2 = ConnectionManager::getDataSource('database2'); $TestModel = new Apple(); $TestModel->setDataSource('database1'); $this->assertContains('aaa_apples', $this->db->fullTableName($TestModel)); $this->assertContains('aaa_apples', $db1->fullTableName($TestModel)); $this->assertContains('aaa_apples', $db2->fullTableName($TestModel)); $TestModel->setDataSource('database2'); $this->assertContains('bbb_apples', $this->db->fullTableName($TestModel)); $this->assertContains('bbb_apples', $db1->fullTableName($TestModel)); $this->assertContains('bbb_apples', $db2->fullTableName($TestModel)); $TestModel = new Apple(); $TestModel->tablePrefix = 'custom_'; $this->assertContains('custom_apples', $this->db->fullTableName($TestModel)); $TestModel->setDataSource('database1'); $this->assertContains('custom_apples', $this->db->fullTableName($TestModel)); $this->assertContains('custom_apples', $db1->fullTableName($TestModel)); $TestModel = new Apple(); $TestModel->setDataSource('database1'); $this->assertContains('aaa_apples', $this->db->fullTableName($TestModel)); $TestModel->tablePrefix = ''; $TestModel->setDataSource('database2'); $this->assertContains('apples', $db2->fullTableName($TestModel)); $this->assertContains('apples', $db1->fullTableName($TestModel)); $TestModel->tablePrefix = null; $TestModel->setDataSource('database1'); $this->assertContains('aaa_apples', $db2->fullTableName($TestModel)); $this->assertContains('aaa_apples', $db1->fullTableName($TestModel)); $TestModel->tablePrefix = false; $TestModel->setDataSource('database2'); $this->assertContains('apples', $db2->fullTableName($TestModel)); $this->assertContains('apples', $db1->fullTableName($TestModel)); } /** * Tests validation parameter order in custom validation methods * * @return void */ public function testInvalidAssociation() { $TestModel = new ValidationTest1(); $this->assertNull($TestModel->getAssociated('Foo')); } /** * testLoadModelSecondIteration method * * @return void */ public function testLoadModelSecondIteration() { $this->loadFixtures('Apple', 'Message', 'Thread', 'Bid'); $model = new ModelA(); $this->assertInstanceOf('ModelA', $model); $this->assertInstanceOf('ModelB', $model->ModelB); $this->assertInstanceOf('ModelD', $model->ModelB->ModelD); $this->assertInstanceOf('ModelC', $model->ModelC); $this->assertInstanceOf('ModelD', $model->ModelC->ModelD); } /** * ensure that exists() does not persist between method calls reset on create * * @return void */ public function testResetOfExistsOnCreate() { $this->loadFixtures('Article'); $Article = new Article(); $Article->id = 1; $Article->saveField('title', 'Reset me'); $Article->delete(); $Article->id = 1; $this->assertFalse($Article->exists()); $Article->create(); $this->assertFalse($Article->exists()); $Article->id = 2; $Article->saveField('title', 'Staying alive'); $result = $Article->read(null, 2); $this->assertEquals('Staying alive', $result['Article']['title']); } /** * testUseTableFalseExistsCheck method * * @return void */ public function testUseTableFalseExistsCheck() { $this->loadFixtures('Article'); $Article = new Article(); $Article->id = 1337; $result = $Article->exists(); $this->assertFalse($result); $Article->useTable = false; $Article->id = null; $result = $Article->exists(); $this->assertFalse($result); // An article with primary key of '1' has been loaded by the fixtures. $Article->useTable = false; $Article->id = 1; $result = $Article->exists(); $this->assertFalse($result); } /** * testPluginAssociations method * * @return void */ public function testPluginAssociations() { $this->loadFixtures('TestPluginArticle', 'User', 'TestPluginComment'); $TestModel = new TestPluginArticle(); $result = $TestModel->find('all'); $expected = array( array( 'TestPluginArticle' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Plugin Article', 'body' => 'First Plugin Article Body', 'published' => 'Y', 'created' => '2008-09-24 10:39:23', 'updated' => '2008-09-24 10:41:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'TestPluginComment' => array( array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Plugin Article', 'published' => 'Y', 'created' => '2008-09-24 10:45:23', 'updated' => '2008-09-24 10:47:31' ), array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Plugin Article', 'published' => 'Y', 'created' => '2008-09-24 10:47:23', 'updated' => '2008-09-24 10:49:31' ), array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Plugin Article', 'published' => 'Y', 'created' => '2008-09-24 10:49:23', 'updated' => '2008-09-24 10:51:31' ), array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Plugin Article', 'published' => 'N', 'created' => '2008-09-24 10:51:23', 'updated' => '2008-09-24 10:53:31' ))), array( 'TestPluginArticle' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Plugin Article', 'body' => 'Second Plugin Article Body', 'published' => 'Y', 'created' => '2008-09-24 10:41:23', 'updated' => '2008-09-24 10:43:31' ), 'User' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'TestPluginComment' => array( array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Plugin Article', 'published' => 'Y', 'created' => '2008-09-24 10:53:23', 'updated' => '2008-09-24 10:55:31' ), array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Plugin Article', 'published' => 'Y', 'created' => '2008-09-24 10:55:23', 'updated' => '2008-09-24 10:57:31' ))), array( 'TestPluginArticle' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Plugin Article', 'body' => 'Third Plugin Article Body', 'published' => 'Y', 'created' => '2008-09-24 10:43:23', 'updated' => '2008-09-24 10:45:31' ), 'User' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'TestPluginComment' => array() )); $this->assertEquals($expected, $result); } /** * Tests getAssociated method * * @return void */ public function testGetAssociated() { $this->loadFixtures('Article', 'Tag'); $Article = ClassRegistry::init('Article'); $assocTypes = array('hasMany', 'hasOne', 'belongsTo', 'hasAndBelongsToMany'); foreach ($assocTypes as $type) { $this->assertEquals($Article->getAssociated($type), array_keys($Article->{$type})); } $Article->bindModel(array('hasMany' => array('Category'))); $this->assertEquals(array('Comment', 'Category'), $Article->getAssociated('hasMany')); $results = $Article->getAssociated(); $results = array_keys($results); sort($results); $this->assertEquals(array('Category', 'Comment', 'Tag', 'User'), $results); $Article->unbindModel(array('hasAndBelongsToMany' => array('Tag'))); $this->assertEquals(array(), $Article->getAssociated('hasAndBelongsToMany')); $result = $Article->getAssociated('Category'); $expected = array( 'className' => 'Category', 'foreignKey' => 'article_id', 'conditions' => '', 'fields' => '', 'order' => '', 'limit' => '', 'offset' => '', 'dependent' => '', 'exclusive' => '', 'finderQuery' => '', 'counterQuery' => '', 'association' => 'hasMany', ); $this->assertEquals($expected, $result); } /** * testAutoConstructAssociations method * * @return void */ public function testAutoConstructAssociations() { $this->loadFixtures('User', 'ArticleFeatured', 'Featured', 'ArticleFeaturedsTags'); $TestModel = new AssociationTest1(); $result = $TestModel->hasAndBelongsToMany; $expected = array('AssociationTest2' => array( 'unique' => false, 'joinTable' => 'join_as_join_bs', 'foreignKey' => false, 'className' => 'AssociationTest2', 'with' => 'JoinAsJoinB', 'dynamicWith' => true, 'associationForeignKey' => 'join_b_id', 'conditions' => '', 'fields' => '', 'order' => '', 'limit' => '', 'offset' => '', 'finderQuery' => '' )); $this->assertEquals($expected, $result); $TestModel = new ArticleFeatured(); $TestFakeModel = new ArticleFeatured(array('table' => false)); $expected = array( 'User' => array( 'className' => 'User', 'foreignKey' => 'user_id', 'conditions' => '', 'fields' => '', 'order' => '', 'counterCache' => '' ), 'Category' => array( 'className' => 'Category', 'foreignKey' => 'category_id', 'conditions' => '', 'fields' => '', 'order' => '', 'counterCache' => '' ) ); $this->assertSame($expected, $TestModel->belongsTo); $this->assertSame($expected, $TestFakeModel->belongsTo); $this->assertEquals('User', $TestModel->User->name); $this->assertEquals('User', $TestFakeModel->User->name); $this->assertEquals('Category', $TestModel->Category->name); $this->assertEquals('Category', $TestFakeModel->Category->name); $expected = array( 'Featured' => array( 'className' => 'Featured', 'foreignKey' => 'article_featured_id', 'conditions' => '', 'fields' => '', 'order' => '', 'dependent' => '' )); $this->assertSame($expected, $TestModel->hasOne); $this->assertSame($expected, $TestFakeModel->hasOne); $this->assertEquals('Featured', $TestModel->Featured->name); $this->assertEquals('Featured', $TestFakeModel->Featured->name); $expected = array( 'Comment' => array( 'className' => 'Comment', 'dependent' => true, 'foreignKey' => 'article_featured_id', 'conditions' => '', 'fields' => '', 'order' => '', 'limit' => '', 'offset' => '', 'exclusive' => '', 'finderQuery' => '', 'counterQuery' => '' )); $this->assertSame($expected, $TestModel->hasMany); $this->assertSame($expected, $TestFakeModel->hasMany); $this->assertEquals('Comment', $TestModel->Comment->name); $this->assertEquals('Comment', $TestFakeModel->Comment->name); $expected = array( 'Tag' => array( 'className' => 'Tag', 'joinTable' => 'article_featureds_tags', 'with' => 'ArticleFeaturedsTag', 'dynamicWith' => true, 'foreignKey' => 'article_featured_id', 'associationForeignKey' => 'tag_id', 'conditions' => '', 'fields' => '', 'order' => '', 'limit' => '', 'offset' => '', 'unique' => true, 'finderQuery' => '', )); $this->assertSame($expected, $TestModel->hasAndBelongsToMany); $this->assertSame($expected, $TestFakeModel->hasAndBelongsToMany); $this->assertEquals('Tag', $TestModel->Tag->name); $this->assertEquals('Tag', $TestFakeModel->Tag->name); } /** * test creating associations with plugins. Ensure a double alias isn't created * * @return void */ public function testAutoConstructPluginAssociations() { $Comment = ClassRegistry::init('TestPluginComment'); $this->assertEquals(2, count($Comment->belongsTo), 'Too many associations'); $this->assertFalse(isset($Comment->belongsTo['TestPlugin.User'])); $this->assertTrue(isset($Comment->belongsTo['User']), 'Missing association'); $this->assertTrue(isset($Comment->belongsTo['TestPluginArticle']), 'Missing association'); } /** * test Model::__construct * * ensure that $actsAS and $findMethods are merged. * * @return void */ public function testConstruct() { $this->loadFixtures('Post'); $TestModel = ClassRegistry::init('MergeVarPluginPost'); $this->assertEquals(array('Containable' => null, 'Tree' => null), $TestModel->actsAs); $this->assertTrue(isset($TestModel->Behaviors->Containable)); $this->assertTrue(isset($TestModel->Behaviors->Tree)); $TestModel = ClassRegistry::init('MergeVarPluginComment'); $expected = array('Containable' => array('some_settings')); $this->assertEquals($expected, $TestModel->actsAs); $this->assertTrue(isset($TestModel->Behaviors->Containable)); } /** * test Model::__construct * * ensure that $actsAS and $findMethods are merged. * * @return void */ public function testConstructWithAlternateDataSource() { $TestModel = ClassRegistry::init(array( 'class' => 'DoesntMatter', 'ds' => 'test', 'table' => false )); $this->assertEquals('test', $TestModel->useDbConfig); //deprecated but test it anyway $NewVoid = new TheVoid(null, false, 'other'); $this->assertEquals('other', $NewVoid->useDbConfig); } /** * testColumnTypeFetching method * * @return void */ public function testColumnTypeFetching() { $model = new Test(); $this->assertEquals('integer', $model->getColumnType('id')); $this->assertEquals('text', $model->getColumnType('notes')); $this->assertEquals('datetime', $model->getColumnType('updated')); $this->assertEquals(null, $model->getColumnType('unknown')); $model = new Article(); $this->assertEquals('datetime', $model->getColumnType('User.created')); $this->assertEquals('integer', $model->getColumnType('Tag.id')); $this->assertEquals('integer', $model->getColumnType('Article.id')); } /** * testHabtmUniqueKey method * * @return void */ public function testHabtmUniqueKey() { $model = new Item(); $this->assertFalse($model->hasAndBelongsToMany['Portfolio']['unique']); } /** * testIdentity method * * @return void */ public function testIdentity() { $TestModel = new Test(); $result = $TestModel->alias; $expected = 'Test'; $this->assertEquals($expected, $result); $TestModel = new TestAlias(); $result = $TestModel->alias; $expected = 'TestAlias'; $this->assertEquals($expected, $result); $TestModel = new Test(array('alias' => 'AnotherTest')); $result = $TestModel->alias; $expected = 'AnotherTest'; $this->assertEquals($expected, $result); $TestModel = ClassRegistry::init('Test'); $expected = null; $this->assertEquals($expected, $TestModel->plugin); $TestModel = ClassRegistry::init('TestPlugin.TestPluginComment'); $expected = 'TestPlugin'; $this->assertEquals($expected, $TestModel->plugin); } /** * testWithAssociation method * * @return void */ public function testWithAssociation() { $this->loadFixtures('Something', 'SomethingElse', 'JoinThing'); $TestModel = new Something(); $result = $TestModel->SomethingElse->find('all'); $expected = array( array( 'SomethingElse' => array( 'id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'afterFind' => 'Successfully added by AfterFind' ), 'Something' => array( array( 'id' => '3', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'JoinThing' => array( 'id' => '3', 'something_id' => '3', 'something_else_id' => '1', 'doomed' => true, 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'afterFind' => 'Successfully added by AfterFind' )))), array( 'SomethingElse' => array( 'id' => '2', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'afterFind' => 'Successfully added by AfterFind' ), 'Something' => array( array( 'id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'JoinThing' => array( 'id' => '1', 'something_id' => '1', 'something_else_id' => '2', 'doomed' => true, 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'afterFind' => 'Successfully added by AfterFind' )))), array( 'SomethingElse' => array( 'id' => '3', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'afterFind' => 'Successfully added by AfterFind' ), 'Something' => array( array( 'id' => '2', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'JoinThing' => array( 'id' => '2', 'something_id' => '2', 'something_else_id' => '3', 'doomed' => false, 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'afterFind' => 'Successfully added by AfterFind' ))))); $this->assertEquals($expected, $result); $result = $TestModel->find('all'); $expected = array( array( 'Something' => array( 'id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'SomethingElse' => array( array( 'id' => '2', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'JoinThing' => array( 'doomed' => true, 'something_id' => '1', 'something_else_id' => '2', 'afterFind' => 'Successfully added by AfterFind' ), 'afterFind' => 'Successfully added by AfterFind' ))), array( 'Something' => array( 'id' => '2', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'SomethingElse' => array( array( 'id' => '3', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'JoinThing' => array( 'doomed' => false, 'something_id' => '2', 'something_else_id' => '3', 'afterFind' => 'Successfully added by AfterFind' ), 'afterFind' => 'Successfully added by AfterFind' ))), array( 'Something' => array( 'id' => '3', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'SomethingElse' => array( array( 'id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'JoinThing' => array( 'doomed' => true, 'something_id' => '3', 'something_else_id' => '1', 'afterFind' => 'Successfully added by AfterFind' ), 'afterFind' => 'Successfully added by AfterFind' )))); $this->assertEquals($expected, $result); $result = $TestModel->findById(1); $expected = array( 'Something' => array( 'id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'SomethingElse' => array( array( 'id' => '2', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'JoinThing' => array( 'doomed' => true, 'something_id' => '1', 'something_else_id' => '2', 'afterFind' => 'Successfully added by AfterFind' ), 'afterFind' => 'Successfully added by AfterFind' ))); $this->assertEquals($expected, $result); $expected = $TestModel->findById(1); $TestModel->set($expected); $TestModel->save(); $result = $TestModel->findById(1); $this->assertEquals($expected, $result); $TestModel->hasAndBelongsToMany['SomethingElse']['unique'] = false; $TestModel->create(array( 'Something' => array('id' => 1), 'SomethingElse' => array(3, array( 'something_else_id' => 1, 'doomed' => true )))); $TestModel->save(); $TestModel->hasAndBelongsToMany['SomethingElse']['order'] = 'SomethingElse.id ASC'; $result = $TestModel->findById(1); $expected = array( 'Something' => array( 'id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23' ), 'SomethingElse' => array( array( 'id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'JoinThing' => array( 'doomed' => true, 'something_id' => '1', 'something_else_id' => '1', 'afterFind' => 'Successfully added by AfterFind' ), 'afterFind' => 'Successfully added by AfterFind' ), array( 'id' => '2', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'JoinThing' => array( 'doomed' => true, 'something_id' => '1', 'something_else_id' => '2', 'afterFind' => 'Successfully added by AfterFind' ), 'afterFind' => 'Successfully added by AfterFind' ), array( 'id' => '3', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'JoinThing' => array( 'doomed' => false, 'something_id' => '1', 'something_else_id' => '3', 'afterFind' => 'Successfully added by AfterFind' ), 'afterFind' => 'Successfully added by AfterFind' ) )); $this->assertEquals(static::date(), $result['Something']['updated']); unset($result['Something']['updated']); $this->assertEquals($expected, $result); } /** * testFindSelfAssociations method * * @return void */ public function testFindSelfAssociations() { $this->loadFixtures('Person'); $TestModel = new Person(); $TestModel->recursive = 2; $result = $TestModel->read(null, 1); $expected = array( 'Person' => array( 'id' => 1, 'name' => 'person', 'mother_id' => 2, 'father_id' => 3 ), 'Mother' => array( 'id' => 2, 'name' => 'mother', 'mother_id' => 4, 'father_id' => 5, 'Mother' => array( 'id' => 4, 'name' => 'mother - grand mother', 'mother_id' => 0, 'father_id' => 0 ), 'Father' => array( 'id' => 5, 'name' => 'mother - grand father', 'mother_id' => 0, 'father_id' => 0 )), 'Father' => array( 'id' => 3, 'name' => 'father', 'mother_id' => 6, 'father_id' => 7, 'Father' => array( 'id' => 7, 'name' => 'father - grand father', 'mother_id' => 0, 'father_id' => 0 ), 'Mother' => array( 'id' => 6, 'name' => 'father - grand mother', 'mother_id' => 0, 'father_id' => 0 ))); $this->assertEquals($expected, $result); $TestModel->recursive = 3; $result = $TestModel->read(null, 1); $expected = array( 'Person' => array( 'id' => 1, 'name' => 'person', 'mother_id' => 2, 'father_id' => 3 ), 'Mother' => array( 'id' => 2, 'name' => 'mother', 'mother_id' => 4, 'father_id' => 5, 'Mother' => array( 'id' => 4, 'name' => 'mother - grand mother', 'mother_id' => 0, 'father_id' => 0, 'Mother' => array(), 'Father' => array()), 'Father' => array( 'id' => 5, 'name' => 'mother - grand father', 'mother_id' => 0, 'father_id' => 0, 'Father' => array(), 'Mother' => array() )), 'Father' => array( 'id' => 3, 'name' => 'father', 'mother_id' => 6, 'father_id' => 7, 'Father' => array( 'id' => 7, 'name' => 'father - grand father', 'mother_id' => 0, 'father_id' => 0, 'Father' => array(), 'Mother' => array() ), 'Mother' => array( 'id' => 6, 'name' => 'father - grand mother', 'mother_id' => 0, 'father_id' => 0, 'Mother' => array(), 'Father' => array() ))); $this->assertEquals($expected, $result); } /** * testDynamicAssociations method * * @return void */ public function testDynamicAssociations() { $this->loadFixtures('Article', 'Comment'); $TestModel = new Article(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->hasOne = array(); $TestModel->hasMany['Comment'] = array_merge($TestModel->hasMany['Comment'], array( 'foreignKey' => false, 'conditions' => array('Comment.user_id =' => '2') )); $result = $TestModel->find('all'); $expected = array( array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Comment' => array( array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' ))), array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Comment' => array( array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' ))), array( 'Article' => array( 'id' => '3', 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'Comment' => array( array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' )))); $this->assertEquals($expected, $result); } /** * testCreation method * * @return void */ public function testCreation() { $this->loadFixtures('Article', 'ArticleFeaturedsTags', 'User', 'Featured'); $TestModel = new Test(); $result = $TestModel->create(); $expected = array('Test' => array('notes' => 'write some notes here')); $this->assertEquals($expected, $result); $TestModel = new User(); $result = $TestModel->schema(); if (isset($this->db->columns['primary_key']['length'])) { $intLength = $this->db->columns['primary_key']['length']; } elseif (isset($this->db->columns['integer']['length'])) { $intLength = $this->db->columns['integer']['length']; } else { $intLength = 11; } foreach (array('collate', 'charset', 'comment', 'unsigned') as $type) { foreach ($result as $i => $r) { unset($result[$i][$type]); } } $expected = array( 'id' => array( 'type' => 'integer', 'null' => false, 'default' => null, 'length' => $intLength, 'key' => 'primary' ), 'user' => array( 'type' => 'string', 'null' => true, 'default' => '', 'length' => 255 ), 'password' => array( 'type' => 'string', 'null' => true, 'default' => '', 'length' => 255 ), 'created' => array( 'type' => 'datetime', 'null' => true, 'default' => null, 'length' => null ), 'updated' => array( 'type' => 'datetime', 'null' => true, 'default' => null, 'length' => null )); $this->assertEquals($expected, $result); $TestModel = new Article(); $result = $TestModel->create(); $expected = array('Article' => array('published' => 'N')); $this->assertEquals($expected, $result); $FeaturedModel = new Featured(); $data = array( 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => array( 'year' => 2008, 'month' => 06, 'day' => 11 ), 'end_date' => array( 'year' => 2008, 'month' => 06, 'day' => 20 )); $expected = array( 'Featured' => array( 'article_featured_id' => 1, 'category_id' => 1, 'published_date' => '2008-06-11 00:00:00', 'end_date' => '2008-06-20 00:00:00' )); $this->assertEquals($expected, $FeaturedModel->create($data)); $data = array( 'published_date' => array( 'year' => 2008, 'month' => 06, 'day' => 11 ), 'end_date' => array( 'year' => 2008, 'month' => 06, 'day' => 20 ), 'article_featured_id' => 1, 'category_id' => 1 ); $expected = array( 'Featured' => array( 'published_date' => '2008-06-11 00:00:00', 'end_date' => '2008-06-20 00:00:00', 'article_featured_id' => 1, 'category_id' => 1 )); $this->assertEquals($expected, $FeaturedModel->create($data)); } /** * testEscapeField to prove it escapes the field well even when it has part of the alias on it * * @return void */ public function testEscapeField() { $TestModel = new Test(); $db = $TestModel->getDataSource(); $result = $TestModel->escapeField('test_field'); $expected = $db->name('Test.test_field'); $this->assertEquals($expected, $result); $result = $TestModel->escapeField('TestField'); $expected = $db->name('Test.TestField'); $this->assertEquals($expected, $result); $result = $TestModel->escapeField('DomainHandle', 'Domain'); $expected = $db->name('Domain.DomainHandle'); $this->assertEquals($expected, $result); ConnectionManager::create('mock', array('datasource' => 'DboMock')); $TestModel->setDataSource('mock'); $db = $TestModel->getDataSource(); $result = $TestModel->escapeField('DomainHandle', 'Domain'); $expected = $db->name('Domain.DomainHandle'); $this->assertEquals($expected, $result); ConnectionManager::drop('mock'); } /** * testGetID * * @return void */ public function testGetID() { $TestModel = new Test(); $result = $TestModel->getID(); $this->assertFalse($result); $TestModel->id = 9; $result = $TestModel->getID(); $this->assertEquals(9, $result); $TestModel->id = array(10, 9, 8, 7); $result = $TestModel->getID(2); $this->assertEquals(8, $result); $TestModel->id = array(array(), 1, 2, 3); $result = $TestModel->getID(); $this->assertFalse($result); } /** * test that model->hasMethod checks self and behaviors. * * @return void */ public function testHasMethod() { $Article = new Article(); $Article->Behaviors = $this->getMock('BehaviorCollection'); $Article->Behaviors->expects($this->at(0)) ->method('hasMethod') ->will($this->returnValue(true)); $Article->Behaviors->expects($this->at(1)) ->method('hasMethod') ->will($this->returnValue(false)); $this->assertTrue($Article->hasMethod('find')); $this->assertTrue($Article->hasMethod('pass')); $this->assertFalse($Article->hasMethod('fail')); } /** * testMultischemaFixture * * @return void */ public function testMultischemaFixture() { $config = ConnectionManager::enumConnectionObjects(); $this->skipIf($this->db instanceof Sqlite, 'This test is not compatible with Sqlite.'); $this->skipIf(!isset($config['test']) || !isset($config['test2']), 'Primary and secondary test databases not configured, skipping cross-database join tests. To run these tests define $test and $test2 in your database configuration.' ); $this->loadFixtures('Player', 'Guild', 'GuildsPlayer'); $Player = ClassRegistry::init('Player'); $this->assertEquals('test', $Player->useDbConfig); $this->assertEquals('test', $Player->Guild->useDbConfig); $this->assertEquals('test2', $Player->Guild->GuildsPlayer->useDbConfig); $this->assertEquals('test2', $Player->GuildsPlayer->useDbConfig); $players = $Player->find('all', array('recursive' => -1)); $guilds = $Player->Guild->find('all', array('recursive' => -1)); $guildsPlayers = $Player->GuildsPlayer->find('all', array('recursive' => -1)); $this->assertEquals(true, count($players) > 1); $this->assertEquals(true, count($guilds) > 1); $this->assertEquals(true, count($guildsPlayers) > 1); } /** * testMultischemaFixtureWithThreeDatabases, three databases * * @return void */ public function testMultischemaFixtureWithThreeDatabases() { $config = ConnectionManager::enumConnectionObjects(); $this->skipIf($this->db instanceof Sqlite, 'This test is not compatible with Sqlite.'); $this->skipIf( !isset($config['test']) || !isset($config['test2']) || !isset($config['test_database_three']), 'Primary, secondary, and tertiary test databases not configured, skipping test. To run this test define $test, $test2, and $test_database_three in your database configuration.' ); $this->loadFixtures('Player', 'Guild', 'GuildsPlayer', 'Armor', 'ArmorsPlayer'); $Player = ClassRegistry::init('Player'); $Player->bindModel(array( 'hasAndBelongsToMany' => array( 'Armor' => array( 'with' => 'ArmorsPlayer', ), ), ), false); $this->assertEquals('test', $Player->useDbConfig); $this->assertEquals('test', $Player->Guild->useDbConfig); $this->assertEquals('test2', $Player->Guild->GuildsPlayer->useDbConfig); $this->assertEquals('test2', $Player->GuildsPlayer->useDbConfig); $this->assertEquals('test2', $Player->Armor->useDbConfig); $this->assertEquals('test_database_three', $Player->Armor->ArmorsPlayer->useDbConfig); $this->assertEquals('test', $Player->getDataSource()->configKeyName); $this->assertEquals('test', $Player->Guild->getDataSource()->configKeyName); $this->assertEquals('test2', $Player->GuildsPlayer->getDataSource()->configKeyName); $this->assertEquals('test2', $Player->Armor->getDataSource()->configKeyName); $this->assertEquals('test_database_three', $Player->Armor->ArmorsPlayer->getDataSource()->configKeyName); $players = $Player->find('all', array('recursive' => -1)); $guilds = $Player->Guild->find('all', array('recursive' => -1)); $guildsPlayers = $Player->GuildsPlayer->find('all', array('recursive' => -1)); $armorsPlayers = $Player->ArmorsPlayer->find('all', array('recursive' => -1)); $this->assertEquals(true, count($players) > 1); $this->assertEquals(true, count($guilds) > 1); $this->assertEquals(true, count($guildsPlayers) > 1); $this->assertEquals(true, count($armorsPlayers) > 1); } /** * Tests that calling schema() on a model that is not supposed to use a table * does not trigger any calls on any datasource * * @return void */ public function testSchemaNoDB() { $model = $this->getMock('Article', array('getDataSource')); $model->useTable = false; $model->expects($this->never())->method('getDataSource'); $this->assertEmpty($model->schema()); } /** * Tests that calling getColumnType() on a model that is not supposed to use a table * does not trigger any calls on any datasource * * @return void */ public function testGetColumnTypeNoDB() { $model = $this->getMock('Example', array('getDataSource')); $model->expects($this->never())->method('getDataSource'); $result = $model->getColumnType('filefield'); $this->assertEquals('string', $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/ModelReadTest.php000066400000000000000000006646451265552240500226370ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ require_once dirname(__FILE__) . DS . 'ModelTestBase.php'; /** * ModelReadTest * * @package Cake.Test.Case.Model */ class ModelReadTest extends BaseModelTest { /** * testExists function * @return void */ public function testExists() { $this->loadFixtures('User'); $TestModel = new User(); $this->assertTrue($TestModel->exists(1)); $TestModel->id = 2; $this->assertTrue($TestModel->exists()); $TestModel->delete(); $this->assertFalse($TestModel->exists()); $this->assertFalse($TestModel->exists(2)); } /** * testFetchingNonUniqueFKJoinTableRecords() * * Tests if the results are properly returned in the case there are non-unique FK's * in the join table but another fields value is different. For example: * something_id | something_else_id | doomed = 1 * something_id | something_else_id | doomed = 0 * Should return both records and not just one. * * @return void */ public function testFetchingNonUniqueFKJoinTableRecords() { $this->loadFixtures('Something', 'SomethingElse', 'JoinThing'); $Something = new Something(); $joinThingData = array( 'JoinThing' => array( 'something_id' => 1, 'something_else_id' => 2, 'doomed' => '0', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ) ); $Something->JoinThing->create($joinThingData); $Something->JoinThing->save(); $result = $Something->JoinThing->find('all', array('conditions' => array('something_else_id' => 2))); $this->assertEquals(true, $result[0]['JoinThing']['doomed']); $this->assertEquals(false, $result[1]['JoinThing']['doomed']); $result = $Something->find('first'); $this->assertEquals(2, count($result['SomethingElse'])); $doomed = Hash::extract($result['SomethingElse'], '{n}.JoinThing.doomed'); $this->assertTrue(in_array(true, $doomed)); $this->assertTrue(in_array(false, $doomed)); } /** * Test IN operator * * @return void */ public function testInOperator() { $this->loadFixtures('Product'); $Product = new Product(); $expected = array( array( 'Product' => array( 'id' => 1, 'name' => "Park's Great Hits", 'type' => 'Music', 'price' => 19 ) ) ); $result = $Product->find('all', array('conditions' => array('Product.id IN' => array(1)))); $this->assertEquals($expected, $result); $expected = array( array( 'Product' => array( 'id' => 2, 'name' => "Silly Puddy", 'type' => 'Toy', 'price' => 3 ) ), array( 'Product' => array( 'id' => 3, 'name' => "Playstation", 'type' => 'Toy', 'price' => 89 ) ), array( 'Product' => array( 'id' => 4, 'name' => "Men's T-Shirt", 'type' => 'Clothing', 'price' => 32 ) ), array( 'Product' => array( 'id' => 5, 'name' => "Blouse", 'type' => 'Clothing', 'price' => 34 ) ), array( 'Product' => array( 'id' => 6, 'name' => "Electronica 2002", 'type' => 'Music', 'price' => 4 ) ), array( 'Product' => array( 'id' => 7, 'name' => "Country Tunes", 'type' => 'Music', 'price' => 21 ) ), array( 'Product' => array( 'id' => 8, 'name' => "Watermelon", 'type' => 'Food', 'price' => 9 ) ) ); $result = $Product->find('all', array('conditions' => array('Product.id NOT IN' => array(1)))); $this->assertEquals($expected, $result); $expected = array( array( 'Product' => array( 'id' => 1, 'name' => "Park's Great Hits", 'type' => 'Music', 'price' => 19 ) ), array( 'Product' => array( 'id' => 2, 'name' => "Silly Puddy", 'type' => 'Toy', 'price' => 3 ) ), ); $result = $Product->find('all', array('conditions' => array('Product.id IN' => array(1, 2)))); $this->assertEquals($expected, $result); } /** * testGroupBy method * * These tests will never pass with Postgres or Oracle as all fields in a select must be * part of an aggregate function or in the GROUP BY statement. * * @return void */ public function testGroupBy() { $isStrictGroupBy = $this->db instanceof Postgres || $this->db instanceof Sqlite || $this->db instanceof Oracle || $this->db instanceof Sqlserver; $message = 'Postgres, Oracle, SQLite and SQL Server have strict GROUP BY and are incompatible with this test.'; $this->skipIf($isStrictGroupBy, $message); $this->loadFixtures('Project', 'Product', 'Thread', 'Message', 'Bid'); $Thread = new Thread(); $Product = new Product(); $result = $Thread->find('all', array( 'group' => 'Thread.project_id', 'order' => 'Thread.id ASC' )); $expected = array( array( 'Thread' => array( 'id' => 1, 'project_id' => 1, 'name' => 'Project 1, Thread 1' ), 'Project' => array( 'id' => 1, 'name' => 'Project 1' ), 'Message' => array( array( 'id' => 1, 'thread_id' => 1, 'name' => 'Thread 1, Message 1' ))), array( 'Thread' => array( 'id' => 3, 'project_id' => 2, 'name' => 'Project 2, Thread 1' ), 'Project' => array( 'id' => 2, 'name' => 'Project 2' ), 'Message' => array( array( 'id' => 3, 'thread_id' => 3, 'name' => 'Thread 3, Message 1' )))); $this->assertEquals($expected, $result); $rows = $Thread->find('all', array( 'group' => 'Thread.project_id', 'fields' => array('Thread.project_id', 'COUNT(*) AS total') )); $result = array(); foreach ($rows as $row) { $result[$row['Thread']['project_id']] = $row[0]['total']; } $expected = array( 1 => 2, 2 => 1 ); $this->assertEquals($expected, $result); $rows = $Thread->find('all', array( 'group' => 'Thread.project_id', 'fields' => array('Thread.project_id', 'COUNT(*) AS total'), 'order' => 'Thread.project_id' )); $result = array(); foreach ($rows as $row) { $result[$row['Thread']['project_id']] = $row[0]['total']; } $expected = array( 1 => 2, 2 => 1 ); $this->assertEquals($expected, $result); $result = $Thread->find('all', array( 'conditions' => array('Thread.project_id' => 1), 'group' => 'Thread.project_id' )); $expected = array( array( 'Thread' => array( 'id' => 1, 'project_id' => 1, 'name' => 'Project 1, Thread 1' ), 'Project' => array( 'id' => 1, 'name' => 'Project 1' ), 'Message' => array( array( 'id' => 1, 'thread_id' => 1, 'name' => 'Thread 1, Message 1' )))); $this->assertEquals($expected, $result); $result = $Thread->find('all', array( 'conditions' => array('Thread.project_id' => 1), 'group' => 'Thread.project_id, Project.id' )); $this->assertEquals($expected, $result); $result = $Thread->find('all', array( 'conditions' => array('Thread.project_id' => 1), 'group' => 'project_id' )); $this->assertEquals($expected, $result); $result = $Thread->find('all', array( 'conditions' => array('Thread.project_id' => 1), 'group' => array('project_id') )); $this->assertEquals($expected, $result); $result = $Thread->find('all', array( 'conditions' => array('Thread.project_id' => 1), 'group' => array('project_id', 'Project.id') )); $this->assertEquals($expected, $result); $result = $Thread->find('all', array( 'conditions' => array('Thread.project_id' => 1), 'group' => array('Thread.project_id', 'Project.id') )); $this->assertEquals($expected, $result); $expected = array( array('Product' => array('type' => 'Clothing'), array('price' => 32)), array('Product' => array('type' => 'Food'), array('price' => 9)), array('Product' => array('type' => 'Music'), array('price' => 4)), array('Product' => array('type' => 'Toy'), array('price' => 3)) ); $result = $Product->find('all', array( 'fields' => array('Product.type', 'MIN(Product.price) as price'), 'group' => 'Product.type', 'order' => 'Product.type ASC' )); $this->assertEquals($expected, $result); $result = $Product->find('all', array( 'fields' => array('Product.type', 'MIN(Product.price) as price'), 'group' => array('Product.type'), 'order' => 'Product.type ASC')); $this->assertEquals($expected, $result); } /** * testOldQuery method * * @return void */ public function testOldQuery() { $this->loadFixtures('Article', 'User', 'Tag', 'ArticlesTag', 'Comment', 'Attachment'); $Article = new Article(); $query = 'SELECT title FROM '; $query .= $this->db->fullTableName('articles'); $query .= ' WHERE ' . $this->db->fullTableName('articles') . '.id IN (1,2)'; $results = $Article->query($query); $this->assertTrue(is_array($results)); $this->assertEquals(2, count($results)); $query = 'SELECT title, body FROM '; $query .= $this->db->fullTableName('articles'); $query .= ' WHERE ' . $this->db->fullTableName('articles') . '.id = 1'; $results = $Article->query($query, false); $this->assertFalse($this->db->getQueryCache($query)); $this->assertTrue(is_array($results)); $query = 'SELECT title, id FROM '; $query .= $this->db->fullTableName('articles'); $query .= ' WHERE ' . $this->db->fullTableName('articles'); $query .= '.published = ' . $this->db->value('Y'); $results = $Article->query($query, true); $result = $this->db->getQueryCache($query); $this->assertFalse(empty($result)); $this->assertTrue(is_array($results)); } /** * testPreparedQuery method * * @return void */ public function testPreparedQuery() { $this->loadFixtures('Article', 'User', 'Tag', 'ArticlesTag'); $Article = new Article(); $query = 'SELECT title, published FROM '; $query .= $this->db->fullTableName('articles'); $query .= ' WHERE ' . $this->db->fullTableName('articles'); $query .= '.id = ? AND ' . $this->db->fullTableName('articles') . '.published = ?'; $params = array(1, 'Y'); $result = $Article->query($query, $params); $expected = array( '0' => array( $this->db->fullTableName('articles', false, false) => array( 'title' => 'First Article', 'published' => 'Y') )); if (isset($result[0][0])) { $expected[0][0] = $expected[0][$this->db->fullTableName('articles', false, false)]; unset($expected[0][$this->db->fullTableName('articles', false, false)]); } $this->assertEquals($expected, $result); $result = $this->db->getQueryCache($query, $params); $this->assertFalse(empty($result)); $query = 'SELECT id, created FROM '; $query .= $this->db->fullTableName('articles'); $query .= ' WHERE ' . $this->db->fullTableName('articles') . '.title = ?'; $params = array('First Article'); $result = $Article->query($query, $params, false); $this->assertTrue(is_array($result)); $this->assertTrue( isset($result[0][$this->db->fullTableName('articles', false, false)]) || isset($result[0][0]) ); $result = $this->db->getQueryCache($query, $params); $this->assertTrue(empty($result)); $query = 'SELECT title FROM '; $query .= $this->db->fullTableName('articles'); $query .= ' WHERE ' . $this->db->fullTableName('articles') . '.title LIKE ?'; $params = array('%First%'); $result = $Article->query($query, $params); $this->assertTrue(is_array($result)); $this->assertTrue( isset($result[0][$this->db->fullTableName('articles', false, false)]['title']) || isset($result[0][0]['title']) ); //related to ticket #5035 $query = 'SELECT title FROM '; $query .= $this->db->fullTableName('articles') . ' WHERE title = ? AND published = ?'; $params = array('First? Article', 'Y'); $Article->query($query, $params); $result = $this->db->getQueryCache($query, $params); $this->assertFalse($result === false); } /** * testParameterMismatch method * * @expectedException PDOException * @return void */ public function testParameterMismatch() { $this->skipIf($this->db instanceof Sqlite, 'Sqlite does not accept real prepared statements, no way to check this'); $this->loadFixtures('Article', 'User', 'Tag', 'ArticlesTag'); $Article = new Article(); $query = 'SELECT * FROM ' . $this->db->fullTableName('articles'); $query .= ' WHERE ' . $this->db->fullTableName('articles'); $query .= '.published = ? AND ' . $this->db->fullTableName('articles') . '.user_id = ?'; $params = array('Y'); $Article->query($query, $params); } /** * testVeryStrangeUseCase method * * @expectedException PDOException * @return void */ public function testVeryStrangeUseCase() { $this->loadFixtures('Article', 'User', 'Tag', 'ArticlesTag'); $Article = new Article(); $query = 'SELECT * FROM ? WHERE ? = ? AND ? = ?'; $param = array( $this->db->fullTableName('articles'), $this->db->fullTableName('articles') . '.user_id', '3', $this->db->fullTableName('articles') . '.published', 'Y' ); $Article->query($query, $param); } /** * testRecursiveUnbind method * * @return void */ public function testRecursiveUnbind() { $this->skipIf($this->db instanceof Sqlserver, 'The test of testRecursiveUnbind test is not compatible with SQL Server, because it check for time columns.'); $this->loadFixtures('Apple', 'Sample'); $TestModel = new Apple(); $TestModel->recursive = 2; $result = $TestModel->find('all'); $expected = array( array( 'Apple' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' ), 'Child' => array( array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))))), array( 'Apple' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Sample' => array(), 'Child' => array( array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2', 'Apple' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' )), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Sample' => array(), 'Child' => array( array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ))), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 1, 'apple_id' => 3, 'name' => 'sample1' )), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 3, 'apple_id' => 4, 'name' => 'sample3' ), 'Child' => array( array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ))))), array( 'Apple' => array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 1, 'apple_id' => 3, 'name' => 'sample1', 'Apple' => array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' )), 'Child' => array() ), array( 'Apple' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17'), 'Sample' => array('id' => 2, 'apple_id' => 2, 'name' => 'sample2'), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 3, 'apple_id' => 4, 'name' => 'sample3', 'Apple' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' )), 'Child' => array( array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ), 'Sample' => array(), 'Child' => array( array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ))))), array( 'Apple' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 4, 'apple_id' => 5, 'name' => 'sample4' ), 'Child' => array( array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 4, 'apple_id' => 5, 'name' => 'sample4', 'Apple' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' )), 'Child' => array( array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 4, 'apple_id' => 5, 'name' => 'sample4' ), 'Child' => array( array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ))))), array( 'Apple' => array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 3, 'apple_id' => 4, 'name' => 'sample3' ), 'Child' => array( array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' ), 'Child' => array( array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ), 'Sample' => array() ))), array( 'Apple' => array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ), 'Sample' => array(), 'Child' => array( array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' ), 'Child' => array())); $this->assertEquals($expected, $result); $result = $TestModel->Parent->unbindModel(array('hasOne' => array('Sample'))); $this->assertTrue($result); $result = $TestModel->find('all'); $expected = array( array( 'Apple' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17'), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' ), 'Child' => array( array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))))), array( 'Apple' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2', 'Apple' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' )), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Sample' => array(), 'Child' => array( array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ))), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 1, 'apple_id' => 3, 'name' => 'sample1' )), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 3, 'apple_id' => 4, 'name' => 'sample3' ), 'Child' => array( array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ))))), array( 'Apple' => array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 1, 'apple_id' => 3, 'name' => 'sample1', 'Apple' => array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' )), 'Child' => array() ), array( 'Apple' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 3, 'apple_id' => 4, 'name' => 'sample3', 'Apple' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' )), 'Child' => array( array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ), 'Sample' => array(), 'Child' => array( array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ))))), array( 'Apple' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 4, 'apple_id' => 5, 'name' => 'sample4', 'Apple' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' )), 'Child' => array( array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 4, 'apple_id' => 5, 'name' => 'sample4' ), 'Child' => array( array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ))))), array( 'Apple' => array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' ), 'Child' => array( array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ), 'Sample' => array() ))), array( 'Apple' => array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' ), 'Child' => array() )); $this->assertEquals($expected, $result); $result = $TestModel->Parent->unbindModel(array('hasOne' => array('Sample'))); $this->assertTrue($result); $result = $TestModel->unbindModel(array('hasMany' => array('Child'))); $this->assertTrue($result); $result = $TestModel->find('all'); $expected = array( array( 'Apple' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' )), array( 'Apple' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2', 'Apple' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ))), array( 'Apple' => array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 1, 'apple_id' => 3, 'name' => 'sample1', 'Apple' => array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ))), array( 'Apple' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 3, 'apple_id' => 4, 'name' => 'sample3', 'Apple' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), array( 'Apple' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 4, 'apple_id' => 5, 'name' => 'sample4', 'Apple' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ))), array( 'Apple' => array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' )), array( 'Apple' => array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ), 'Child' => array( array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' ))); $this->assertEquals($expected, $result); $result = $TestModel->unbindModel(array('hasMany' => 'Child')); $this->assertTrue($result); $result = $TestModel->Sample->unbindModel(array('belongsTo' => 'Apple')); $this->assertTrue($result); $result = $TestModel->find('all'); $expected = array( array( 'Apple' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' )), array( 'Apple' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Sample' => array(), 'Child' => array( array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2' )), array( 'Apple' => array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 1, 'apple_id' => 3, 'name' => 'sample1' )), array( 'Apple' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 3, 'apple_id' => 4, 'name' => 'sample3' )), array( 'Apple' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 4, 'apple_id' => 5, 'name' => 'sample4' ), 'Child' => array( array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 4, 'apple_id' => 5, 'name' => 'sample4' )), array( 'Apple' => array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => 3, 'apple_id' => 4, 'name' => 'sample3' ), 'Child' => array( array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' )), array( 'Apple' => array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17', 'Parent' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ), 'Sample' => array(), 'Child' => array( array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' ))); $this->assertEquals($expected, $result); $result = $TestModel->Parent->unbindModel(array('belongsTo' => array('Parent'))); $this->assertTrue($result); $result = $TestModel->unbindModel(array('hasMany' => array('Child'))); $this->assertTrue($result); $result = $TestModel->find('all'); $expected = array( array( 'Apple' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' )), array( 'Apple' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17', 'Sample' => array(), 'Child' => array( array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2', 'Apple' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ))), array( 'Apple' => array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 1, 'apple_id' => 3, 'name' => 'sample1', 'Apple' => array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ))), array( 'Apple' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 2, 'apple_id' => 1, 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17', 'Sample' => array( 'id' => 2, 'apple_id' => 2, 'name' => 'sample2' ), 'Child' => array( array( 'id' => 1, 'apple_id' => 2, 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => 3, 'apple_id' => 2, 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 3, 'apple_id' => 4, 'name' => 'sample3', 'Apple' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), array( 'Apple' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17', 'Sample' => array( 'id' => 4, 'apple_id' => 5, 'name' => 'sample4' ), 'Child' => array( array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => 4, 'apple_id' => 5, 'name' => 'sample4', 'Apple' => array( 'id' => 5, 'apple_id' => 5, 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ))), array( 'Apple' => array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17'), 'Parent' => array( 'id' => 4, 'apple_id' => 2, 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17', 'Sample' => array( 'id' => 3, 'apple_id' => 4, 'name' => 'sample3' ), 'Child' => array( array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' )), array( 'Apple' => array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => 6, 'apple_id' => 4, 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17', 'Sample' => array(), 'Child' => array( array( 'id' => 7, 'apple_id' => 6, 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ))), 'Sample' => array( 'id' => '', 'apple_id' => '', 'name' => '' ))); $this->assertEquals($expected, $result); } /** * testSelfAssociationAfterFind method * * @return void */ public function testSelfAssociationAfterFind() { $this->loadFixtures('Apple', 'Sample'); $afterFindModel = new NodeAfterFind(); $afterFindModel->recursive = 3; $afterFindData = $afterFindModel->find('all'); $duplicateModel = new NodeAfterFind(); $duplicateModel->recursive = 3; $noAfterFindModel = new NodeNoAfterFind(); $noAfterFindModel->recursive = 3; $noAfterFindData = $noAfterFindModel->find('all'); $this->assertFalse($afterFindModel == $noAfterFindModel); $this->assertEquals($afterFindData, $noAfterFindData); } /** * Test that afterFind can completely unset data. * * @return void */ public function testAfterFindUnset() { $this->loadFixtures('Article', 'Comment', 'User'); $model = new CustomArticle(); $model->bindModel(array( 'hasMany' => array( 'ModifiedComment' => array( 'className' => 'ModifiedComment', 'foreignKey' => 'article_id', ) ) )); $model->ModifiedComment->remove = true; $result = $model->find('all'); $this->assertTrue( empty($result[0]['ModifiedComment']), 'Zeroith row should be removed by afterFind' ); } /** * testFindThreadedNoParent method * * @return void */ public function testFindThreadedNoParent() { $this->loadFixtures('Apple', 'Sample'); $Apple = new Apple(); $result = $Apple->find('threaded'); $result = Hash::extract($result, '{n}.children'); $expected = array(array(), array(), array(), array(), array(), array(), array()); $this->assertEquals($expected, $result); } /** * testFindThreaded method * * @return void */ public function testFindThreaded() { $this->loadFixtures('Person'); $Model = new Person(); $Model->recursive = -1; $result = $Model->find('threaded'); $result = Hash::extract($result, '{n}.children'); $expected = array(array(), array(), array(), array(), array(), array(), array()); $this->assertEquals($expected, $result); $result = $Model->find('threaded', array('parent' => 'mother_id')); $expected = array( array( 'Person' => array( 'id' => '4', 'name' => 'mother - grand mother', 'mother_id' => '0', 'father_id' => '0' ), 'children' => array( array( 'Person' => array( 'id' => '2', 'name' => 'mother', 'mother_id' => '4', 'father_id' => '5' ), 'children' => array( array( 'Person' => array( 'id' => '1', 'name' => 'person', 'mother_id' => '2', 'father_id' => '3' ), 'children' => array() ) ) ) ) ), array( 'Person' => array( 'id' => '5', 'name' => 'mother - grand father', 'mother_id' => '0', 'father_id' => '0' ), 'children' => array() ), array( 'Person' => array( 'id' => '6', 'name' => 'father - grand mother', 'mother_id' => '0', 'father_id' => '0' ), 'children' => array( array( 'Person' => array( 'id' => '3', 'name' => 'father', 'mother_id' => '6', 'father_id' => '7' ), 'children' => array() ) ) ), array( 'Person' => array( 'id' => '7', 'name' => 'father - grand father', 'mother_id' => '0', 'father_id' => '0' ), 'children' => array() ) ); $this->assertEquals($expected, $result); } /** * testFindAllThreaded method * * @return void */ public function testFindAllThreaded() { $this->loadFixtures('Category'); $TestModel = new Category(); $result = $TestModel->find('threaded'); $expected = array( array( 'Category' => array( 'id' => '1', 'parent_id' => '0', 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array( array( 'Category' => array( 'id' => '2', 'parent_id' => '1', 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array( array('Category' => array( 'id' => '7', 'parent_id' => '2', 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'), 'children' => array()), array('Category' => array( 'id' => '8', 'parent_id' => '2', 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'), 'children' => array())) ), array( 'Category' => array( 'id' => '3', 'parent_id' => '1', 'name' => 'Category 1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array() ) ) ), array( 'Category' => array( 'id' => '4', 'parent_id' => '0', 'name' => 'Category 2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array() ), array( 'Category' => array( 'id' => '5', 'parent_id' => '0', 'name' => 'Category 3', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array( array( 'Category' => array( 'id' => '6', 'parent_id' => '5', 'name' => 'Category 3.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array() ) ) ) ); $this->assertEquals($expected, $result); $result = $TestModel->find('threaded', array( 'conditions' => array('Category.name LIKE' => 'Category 1%') )); $expected = array( array( 'Category' => array( 'id' => '1', 'parent_id' => '0', 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array( array( 'Category' => array( 'id' => '2', 'parent_id' => '1', 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array( array('Category' => array( 'id' => '7', 'parent_id' => '2', 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'), 'children' => array()), array('Category' => array( 'id' => '8', 'parent_id' => '2', 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'), 'children' => array())) ), array( 'Category' => array( 'id' => '3', 'parent_id' => '1', 'name' => 'Category 1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array() ) ) ) ); $this->assertEquals($expected, $result); $result = $TestModel->find('threaded', array( 'fields' => 'id, parent_id, name' )); $expected = array( array( 'Category' => array( 'id' => '1', 'parent_id' => '0', 'name' => 'Category 1' ), 'children' => array( array( 'Category' => array( 'id' => '2', 'parent_id' => '1', 'name' => 'Category 1.1' ), 'children' => array( array('Category' => array( 'id' => '7', 'parent_id' => '2', 'name' => 'Category 1.1.1'), 'children' => array()), array('Category' => array( 'id' => '8', 'parent_id' => '2', 'name' => 'Category 1.1.2'), 'children' => array())) ), array( 'Category' => array( 'id' => '3', 'parent_id' => '1', 'name' => 'Category 1.2' ), 'children' => array() ) ) ), array( 'Category' => array( 'id' => '4', 'parent_id' => '0', 'name' => 'Category 2' ), 'children' => array() ), array( 'Category' => array( 'id' => '5', 'parent_id' => '0', 'name' => 'Category 3' ), 'children' => array( array( 'Category' => array( 'id' => '6', 'parent_id' => '5', 'name' => 'Category 3.1' ), 'children' => array() ) ) ) ); $this->assertEquals($expected, $result); $result = $TestModel->find('threaded', array('order' => 'id DESC')); $expected = array( array( 'Category' => array( 'id' => 5, 'parent_id' => 0, 'name' => 'Category 3', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array( array( 'Category' => array( 'id' => 6, 'parent_id' => 5, 'name' => 'Category 3.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array() ) ) ), array( 'Category' => array( 'id' => 4, 'parent_id' => 0, 'name' => 'Category 2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array() ), array( 'Category' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array( array( 'Category' => array( 'id' => 3, 'parent_id' => 1, 'name' => 'Category 1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array() ), array( 'Category' => array( 'id' => 2, 'parent_id' => 1, 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array( array('Category' => array( 'id' => '8', 'parent_id' => '2', 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'), 'children' => array()), array('Category' => array( 'id' => '7', 'parent_id' => '2', 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'), 'children' => array())) ) ) ) ); $this->assertEquals($expected, $result); $result = $TestModel->find('threaded', array( 'conditions' => array('Category.name LIKE' => 'Category 3%') )); $expected = array( array( 'Category' => array( 'id' => '5', 'parent_id' => '0', 'name' => 'Category 3', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array( array( 'Category' => array( 'id' => '6', 'parent_id' => '5', 'name' => 'Category 3.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'children' => array() ) ) ) ); $this->assertEquals($expected, $result); $result = $TestModel->find('threaded', array( 'conditions' => array('Category.name LIKE' => 'Category 1.1%') )); $expected = array( array('Category' => array( 'id' => '2', 'parent_id' => '1', 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'), 'children' => array( array('Category' => array( 'id' => '7', 'parent_id' => '2', 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'), 'children' => array()), array('Category' => array( 'id' => '8', 'parent_id' => '2', 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31'), 'children' => array())))); $this->assertEquals($expected, $result); $result = $TestModel->find('threaded', array( 'fields' => 'id, parent_id, name', 'conditions' => array('Category.id !=' => 2) )); $expected = array( array( 'Category' => array( 'id' => '1', 'parent_id' => '0', 'name' => 'Category 1' ), 'children' => array( array( 'Category' => array( 'id' => '3', 'parent_id' => '1', 'name' => 'Category 1.2' ), 'children' => array() ) ) ), array( 'Category' => array( 'id' => '4', 'parent_id' => '0', 'name' => 'Category 2' ), 'children' => array() ), array( 'Category' => array( 'id' => '5', 'parent_id' => '0', 'name' => 'Category 3' ), 'children' => array( array( 'Category' => array( 'id' => '6', 'parent_id' => '5', 'name' => 'Category 3.1' ), 'children' => array() ) ) ) ); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array( 'fields' => 'id, name, parent_id', 'conditions' => array('Category.id !=' => 1) )); $expected = array( array('Category' => array( 'id' => '2', 'name' => 'Category 1.1', 'parent_id' => '1' )), array('Category' => array( 'id' => '3', 'name' => 'Category 1.2', 'parent_id' => '1' )), array('Category' => array( 'id' => '4', 'name' => 'Category 2', 'parent_id' => '0' )), array('Category' => array( 'id' => '5', 'name' => 'Category 3', 'parent_id' => '0' )), array('Category' => array( 'id' => '6', 'name' => 'Category 3.1', 'parent_id' => '5' )), array('Category' => array( 'id' => '7', 'name' => 'Category 1.1.1', 'parent_id' => '2' )), array('Category' => array( 'id' => '8', 'name' => 'Category 1.1.2', 'parent_id' => '2' ))); $this->assertEquals($expected, $result); $result = $TestModel->find('threaded', array( 'fields' => 'id, parent_id, name', 'conditions' => array('Category.id !=' => 1) )); $expected = array( array( 'Category' => array( 'id' => '2', 'parent_id' => '1', 'name' => 'Category 1.1' ), 'children' => array( array('Category' => array( 'id' => '7', 'parent_id' => '2', 'name' => 'Category 1.1.1'), 'children' => array()), array('Category' => array( 'id' => '8', 'parent_id' => '2', 'name' => 'Category 1.1.2'), 'children' => array())) ), array( 'Category' => array( 'id' => '3', 'parent_id' => '1', 'name' => 'Category 1.2' ), 'children' => array() ) ); $this->assertEquals($expected, $result); } /** * test find('neighbors') * * @return void */ public function testFindNeighbors() { $this->loadFixtures('User', 'Article', 'Comment', 'Tag', 'ArticlesTag', 'Attachment'); $TestModel = new Article(); $TestModel->id = 1; $result = $TestModel->find('neighbors', array('fields' => array('id'))); $this->assertNull($result['prev']); $this->assertEquals(array('id' => 2), $result['next']['Article']); $this->assertEquals(2, count($result['next']['Comment'])); $this->assertEquals(2, count($result['next']['Tag'])); $TestModel->id = 2; $TestModel->recursive = 0; $result = $TestModel->find('neighbors', array( 'fields' => array('id') )); $expected = array( 'prev' => array( 'Article' => array( 'id' => 1 )), 'next' => array( 'Article' => array( 'id' => 3 ))); $this->assertEquals($expected, $result); $TestModel->id = 3; $TestModel->recursive = 1; $result = $TestModel->find('neighbors', array('fields' => array('id'))); $this->assertNull($result['next']); $this->assertEquals(array('id' => 2), $result['prev']['Article']); $this->assertEquals(2, count($result['prev']['Comment'])); $this->assertEquals(2, count($result['prev']['Tag'])); $TestModel->id = 1; $result = $TestModel->find('neighbors', array('recursive' => -1)); $expected = array( 'prev' => null, 'next' => array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ) ); $this->assertEquals($expected, $result); $TestModel->id = 2; $result = $TestModel->find('neighbors', array('recursive' => -1)); $expected = array( 'prev' => array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ) ), 'next' => array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ); $this->assertEquals($expected, $result); $TestModel->id = 3; $result = $TestModel->find('neighbors', array('recursive' => -1)); $expected = array( 'prev' => array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ), 'next' => null ); $this->assertEquals($expected, $result); $TestModel->recursive = 0; $TestModel->id = 1; $one = $TestModel->read(); $TestModel->id = 2; $two = $TestModel->read(); $TestModel->id = 3; $three = $TestModel->read(); $TestModel->id = 1; $result = $TestModel->find('neighbors'); $expected = array('prev' => null, 'next' => $two); $this->assertEquals($expected, $result); $TestModel->id = 2; $result = $TestModel->find('neighbors'); $expected = array('prev' => $one, 'next' => $three); $this->assertEquals($expected, $result); $TestModel->id = 3; $result = $TestModel->find('neighbors'); $expected = array('prev' => $two, 'next' => null); $this->assertEquals($expected, $result); $TestModel->recursive = 2; $TestModel->id = 1; $one = $TestModel->read(); $TestModel->id = 2; $two = $TestModel->read(); $TestModel->id = 3; $three = $TestModel->read(); $TestModel->id = 1; $result = $TestModel->find('neighbors', array('recursive' => 2)); $expected = array('prev' => null, 'next' => $two); $this->assertEquals($expected, $result); $TestModel->id = 2; $result = $TestModel->find('neighbors', array('recursive' => 2)); $expected = array('prev' => $one, 'next' => $three); $this->assertEquals($expected, $result); $TestModel->id = 3; $result = $TestModel->find('neighbors', array('recursive' => 2)); $expected = array('prev' => $two, 'next' => null); $this->assertEquals($expected, $result); } /** * Test find(neighbors) with missing fields so no neighbors are found. * * @return void */ public function testFindNeighborsNoPrev() { $this->loadFixtures('User', 'Article', 'Comment', 'Tag', 'ArticlesTag', 'Attachment'); $Article = new Article(); $result = $Article->find('neighbors', array( 'field' => 'Article.title', 'value' => 'Second Article', 'fields' => array('id'), 'conditions' => array( 'Article.title LIKE' => '%Article%' ), 'recursive' => 0, )); $expected = array( 'prev' => null, 'next' => null ); $this->assertEquals($expected, $result); } /** * testFindCombinedRelations method * * @return void */ public function testFindCombinedRelations() { $this->skipIf($this->db instanceof Sqlserver, 'The test of testRecursiveUnbind test is not compatible with SQL Server, because it check for time columns.'); $this->loadFixtures('Apple', 'Sample'); $TestModel = new Apple(); $result = $TestModel->find('all'); $expected = array( array( 'Apple' => array( 'id' => '1', 'apple_id' => '2', 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => '2', 'apple_id' => '1', 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => null, 'apple_id' => null, 'name' => null ), 'Child' => array( array( 'id' => '2', 'apple_id' => '1', 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ))), array( 'Apple' => array( 'id' => '2', 'apple_id' => '1', 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => '1', 'apple_id' => '2', 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => '2', 'apple_id' => '2', 'name' => 'sample2' ), 'Child' => array( array( 'id' => '1', 'apple_id' => '2', 'color' => 'Red 1', 'name' => 'Red Apple 1', 'created' => '2006-11-22 10:38:58', 'date' => '1951-01-04', 'modified' => '2006-12-01 13:31:26', 'mytime' => '22:57:17' ), array( 'id' => '3', 'apple_id' => '2', 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), array( 'id' => '4', 'apple_id' => '2', 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ))), array( 'Apple' => array( 'id' => '3', 'apple_id' => '2', 'color' => 'blue green', 'name' => 'green blue', 'created' => '2006-12-25 05:13:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:24', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => '2', 'apple_id' => '1', 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => '1', 'apple_id' => '3', 'name' => 'sample1' ), 'Child' => array() ), array( 'Apple' => array( 'id' => '4', 'apple_id' => '2', 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => '2', 'apple_id' => '1', 'color' => 'Bright Red 1', 'name' => 'Bright Red Apple', 'created' => '2006-11-22 10:43:13', 'date' => '2014-01-01', 'modified' => '2006-11-30 18:38:10', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => '3', 'apple_id' => '4', 'name' => 'sample3' ), 'Child' => array( array( 'id' => '6', 'apple_id' => '4', 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ))), array( 'Apple' => array( 'id' => '5', 'apple_id' => '5', 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => '5', 'apple_id' => '5', 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => '4', 'apple_id' => '5', 'name' => 'sample4' ), 'Child' => array( array( 'id' => '5', 'apple_id' => '5', 'color' => 'Green', 'name' => 'Blue Green', 'created' => '2006-12-25 05:24:06', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:16', 'mytime' => '22:57:17' ))), array( 'Apple' => array( 'id' => '6', 'apple_id' => '4', 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => '4', 'apple_id' => '2', 'color' => 'Blue Green', 'name' => 'Test Name', 'created' => '2006-12-25 05:23:36', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:23:36', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => null, 'apple_id' => null, 'name' => null ), 'Child' => array( array( 'id' => '7', 'apple_id' => '6', 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ))), array( 'Apple' => array( 'id' => '7', 'apple_id' => '6', 'color' => 'Some wierd color', 'name' => 'Some odd color', 'created' => '2006-12-25 05:34:21', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:34:21', 'mytime' => '22:57:17' ), 'Parent' => array( 'id' => '6', 'apple_id' => '4', 'color' => 'My new appleOrange', 'name' => 'My new apple', 'created' => '2006-12-25 05:29:39', 'date' => '2006-12-25', 'modified' => '2006-12-25 05:29:39', 'mytime' => '22:57:17' ), 'Sample' => array( 'id' => null, 'apple_id' => null, 'name' => null ), 'Child' => array() )); $this->assertEquals($expected, $result); } /** * testSaveEmpty method * * @return void */ public function testSaveEmpty() { $this->loadFixtures('Thread'); $TestModel = new Thread(); $data = array(); $expected = $TestModel->save($data); $this->assertFalse($expected); } /** * testFindAllWithConditionInChildQuery * * @return void */ public function testFindAllWithConditionInChildQuery() { $this->loadFixtures('Basket', 'FilmFile'); $TestModel = new Basket(); $recursive = 3; $result = $TestModel->find('all', compact('recursive')); $expected = array( array( 'Basket' => array( 'id' => 1, 'type' => 'nonfile', 'name' => 'basket1', 'object_id' => 1, 'user_id' => 1, ), 'FilmFile' => array( 'id' => '', 'name' => '', ) ), array( 'Basket' => array( 'id' => 2, 'type' => 'file', 'name' => 'basket2', 'object_id' => 2, 'user_id' => 1, ), 'FilmFile' => array( 'id' => 2, 'name' => 'two', ) ), ); $this->assertEquals($expected, $result); } /** * testFindAllWithConditionsHavingMixedDataTypes method * * @return void */ public function testFindAllWithConditionsHavingMixedDataTypes() { $this->loadFixtures('Article', 'User', 'Tag', 'ArticlesTag'); $TestModel = new Article(); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ) ); $conditions = array('id' => array('1', 2)); $recursive = -1; $order = 'Article.id ASC'; $result = $TestModel->find('all', compact('conditions', 'recursive', 'order')); $this->assertEquals($expected, $result); $this->skipIf($this->db instanceof Postgres, 'The rest of testFindAllWithConditionsHavingMixedDataTypes test is not compatible with Postgres.'); $conditions = array('id' => array('1', 2, '3.0')); $order = 'Article.id ASC'; $result = $TestModel->find('all', compact('recursive', 'conditions', 'order')); $expected = array( array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ) ), array( 'Article' => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ), array( 'Article' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ); $this->assertEquals($expected, $result); } /** * testBindUnbind method * * @return void */ public function testBindUnbind() { $this->loadFixtures( 'User', 'Comment', 'FeatureSet', 'DeviceType', 'DeviceTypeCategory', 'ExteriorTypeCategory', 'Device', 'Document', 'DocumentDirectory' ); $TestModel = new User(); $result = $TestModel->hasMany; $expected = array(); $this->assertEquals($expected, $result); $result = $TestModel->bindModel(array('hasMany' => array('Comment'))); $this->assertTrue($result); $result = $TestModel->find('all', array( 'fields' => 'User.id, User.user', 'order' => array('User.id' => 'ASC'), )); $expected = array( array( 'User' => array( 'id' => '1', 'user' => 'mariano' ), 'Comment' => array( array( 'id' => '3', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), array( 'id' => '4', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ), array( 'id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ))), array( 'User' => array( 'id' => '2', 'user' => 'nate' ), 'Comment' => array( array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' ))), array( 'User' => array( 'id' => '3', 'user' => 'larry' ), 'Comment' => array() ), array( 'User' => array( 'id' => '4', 'user' => 'garrett' ), 'Comment' => array( array( 'id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31' )))); $this->assertEquals($expected, $result); $TestModel->resetAssociations(); $result = $TestModel->hasMany; $this->assertSame(array(), $result); $result = $TestModel->bindModel(array('hasMany' => array('Comment')), false); $this->assertTrue($result); $result = $TestModel->find('all', array( 'fields' => 'User.id, User.user', 'order' => array('User.id' => 'ASC'), )); $expected = array( array( 'User' => array( 'id' => '1', 'user' => 'mariano' ), 'Comment' => array( array( 'id' => '3', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), array( 'id' => '4', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ), array( 'id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ))), array( 'User' => array( 'id' => '2', 'user' => 'nate' ), 'Comment' => array( array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' ))), array( 'User' => array( 'id' => '3', 'user' => 'larry' ), 'Comment' => array() ), array( 'User' => array( 'id' => '4', 'user' => 'garrett' ), 'Comment' => array( array( 'id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31' )))); $this->assertEquals($expected, $result); $result = $TestModel->hasMany; $expected = array( 'Comment' => array( 'className' => 'Comment', 'foreignKey' => 'user_id', 'conditions' => null, 'fields' => null, 'order' => null, 'limit' => null, 'offset' => null, 'dependent' => null, 'exclusive' => null, 'finderQuery' => null, 'counterQuery' => null )); $this->assertEquals($expected, $result); $result = $TestModel->unbindModel(array('hasMany' => array('Comment'))); $this->assertTrue($result); $result = $TestModel->hasMany; $expected = array(); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array( 'fields' => 'User.id, User.user', 'order' => array('User.id' => 'ASC'), )); $expected = array( array('User' => array('id' => '1', 'user' => 'mariano')), array('User' => array('id' => '2', 'user' => 'nate')), array('User' => array('id' => '3', 'user' => 'larry')), array('User' => array('id' => '4', 'user' => 'garrett'))); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array( 'fields' => 'User.id, User.user', 'order' => array('User.id' => 'ASC'), )); $expected = array( array( 'User' => array( 'id' => '1', 'user' => 'mariano' ), 'Comment' => array( array( 'id' => '3', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), array( 'id' => '4', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ), array( 'id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ))), array( 'User' => array( 'id' => '2', 'user' => 'nate' ), 'Comment' => array( array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' ))), array( 'User' => array( 'id' => '3', 'user' => 'larry' ), 'Comment' => array() ), array( 'User' => array( 'id' => '4', 'user' => 'garrett' ), 'Comment' => array( array( 'id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31' )))); $this->assertEquals($expected, $result); $result = $TestModel->unbindModel(array('hasMany' => array('Comment')), false); $this->assertTrue($result); $result = $TestModel->find('all', array( 'fields' => 'User.id, User.user', 'order' => array('User.id' => 'ASC'), )); $expected = array( array('User' => array('id' => '1', 'user' => 'mariano')), array('User' => array('id' => '2', 'user' => 'nate')), array('User' => array('id' => '3', 'user' => 'larry')), array('User' => array('id' => '4', 'user' => 'garrett'))); $this->assertEquals($expected, $result); $result = $TestModel->hasMany; $expected = array(); $this->assertEquals($expected, $result); $result = $TestModel->bindModel(array('hasMany' => array( 'Comment' => array('className' => 'Comment', 'conditions' => 'Comment.published = \'Y\'') ))); $this->assertTrue($result); $result = $TestModel->find('all', array( 'fields' => 'User.id, User.user', 'order' => array('User.id' => 'ASC'), )); $expected = array( array( 'User' => array( 'id' => '1', 'user' => 'mariano' ), 'Comment' => array( array( 'id' => '3', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), array( 'id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ))), array( 'User' => array( 'id' => '2', 'user' => 'nate' ), 'Comment' => array( array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' ))), array( 'User' => array( 'id' => '3', 'user' => 'larry' ), 'Comment' => array() ), array( 'User' => array( 'id' => '4', 'user' => 'garrett' ), 'Comment' => array( array( 'id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31' )))); $this->assertEquals($expected, $result); $TestModel2 = new DeviceType(); $expected = array( 'className' => 'FeatureSet', 'foreignKey' => 'feature_set_id', 'conditions' => '', 'fields' => '', 'order' => '', 'counterCache' => '' ); $this->assertEquals($expected, $TestModel2->belongsTo['FeatureSet']); $TestModel2->bindModel(array( 'belongsTo' => array( 'FeatureSet' => array( 'className' => 'FeatureSet', 'conditions' => array('active' => true) ) ) )); $expected['conditions'] = array('active' => true); $this->assertEquals($expected, $TestModel2->belongsTo['FeatureSet']); $TestModel2->bindModel(array( 'belongsTo' => array( 'FeatureSet' => array( 'className' => 'FeatureSet', 'foreignKey' => false, 'conditions' => array('Feature.name' => 'DeviceType.name') ) ) )); $expected['conditions'] = array('Feature.name' => 'DeviceType.name'); $expected['foreignKey'] = false; $this->assertEquals($expected, $TestModel2->belongsTo['FeatureSet']); $TestModel2->bindModel(array( 'hasMany' => array( 'NewFeatureSet' => array( 'className' => 'FeatureSet', 'conditions' => array('active' => true) ) ) )); $expected = array( 'className' => 'FeatureSet', 'conditions' => array('active' => true), 'foreignKey' => 'device_type_id', 'fields' => '', 'order' => '', 'limit' => '', 'offset' => '', 'dependent' => '', 'exclusive' => '', 'finderQuery' => '', 'counterQuery' => '' ); $this->assertEquals($expected, $TestModel2->hasMany['NewFeatureSet']); $this->assertTrue(is_object($TestModel2->NewFeatureSet)); } /** * testBindMultipleTimes method * * @return void */ public function testBindMultipleTimes() { $this->loadFixtures('User', 'Comment', 'Article', 'Tag', 'ArticlesTag'); $TestModel = new User(); $result = $TestModel->hasMany; $expected = array(); $this->assertEquals($expected, $result); $result = $TestModel->bindModel(array( 'hasMany' => array( 'Items' => array('className' => 'Comment') ))); $this->assertTrue($result); $result = $TestModel->find('all', array( 'fields' => 'User.id, User.user' )); $expected = array( array( 'User' => array( 'id' => '1', 'user' => 'mariano' ), 'Items' => array( array( 'id' => '3', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), array( 'id' => '4', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ), array( 'id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ))), array( 'User' => array( 'id' => '2', 'user' => 'nate' ), 'Items' => array( array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' ))), array( 'User' => array( 'id' => '3', 'user' => 'larry' ), 'Items' => array() ), array( 'User' => array( 'id' => '4', 'user' => 'garrett' ), 'Items' => array( array( 'id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31' )))); $this->assertEquals($expected, $result); $result = $TestModel->bindModel(array( 'hasMany' => array( 'Items' => array('className' => 'Article') ))); $this->assertTrue($result); $result = $TestModel->find('all', array( 'fields' => 'User.id, User.user' )); $expected = array( array( 'User' => array( 'id' => '1', 'user' => 'mariano' ), 'Items' => array( array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ))), array( 'User' => array( 'id' => '2', 'user' => 'nate' ), 'Items' => array() ), array( 'User' => array( 'id' => '3', 'user' => 'larry' ), 'Items' => array( array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ))), array( 'User' => array( 'id' => '4', 'user' => 'garrett' ), 'Items' => array() )); $this->assertEquals($expected, $result); } /** * test that multiple reset = true calls to bindModel() result in the original associations. * * @return void */ public function testBindModelMultipleTimesResetCorrectly() { $this->loadFixtures('User', 'Comment', 'Article'); $TestModel = new User(); $TestModel->bindModel(array('hasMany' => array('Comment'))); $TestModel->bindModel(array('hasMany' => array('Comment'))); $TestModel->resetAssociations(); $this->assertFalse(isset($TestModel->hasMany['Comment']), 'Association left behind'); } /** * testBindMultipleTimes method with different reset settings * * @return void */ public function testBindMultipleTimesWithDifferentResetSettings() { $this->loadFixtures('User', 'Comment', 'Article'); $TestModel = new User(); $result = $TestModel->hasMany; $expected = array(); $this->assertEquals($expected, $result); $result = $TestModel->bindModel(array( 'hasMany' => array('Comment') )); $this->assertTrue($result); $result = $TestModel->bindModel( array('hasMany' => array('Article')), false ); $this->assertTrue($result); $result = array_keys($TestModel->hasMany); $expected = array('Comment', 'Article'); $this->assertEquals($expected, $result); $TestModel->resetAssociations(); $result = array_keys($TestModel->hasMany); $expected = array('Article'); $this->assertEquals($expected, $result); } /** * test that bindModel behaves with Custom primary Key associations * * @return void */ public function testBindWithCustomPrimaryKey() { $this->loadFixtures('Story', 'StoriesTag', 'Tag'); $Model = ClassRegistry::init('StoriesTag'); $Model->bindModel(array( 'belongsTo' => array( 'Tag' => array( 'className' => 'Tag', 'foreignKey' => 'story' )))); $result = $Model->find('all'); $this->assertFalse(empty($result)); } /** * test that calling unbindModel() with reset == true multiple times * leaves associations in the correct state. * * @return void */ public function testUnbindMultipleTimesResetCorrectly() { $this->loadFixtures('User', 'Comment', 'Article'); $TestModel = new Article10(); $TestModel->unbindModel(array('hasMany' => array('Comment'))); $TestModel->unbindModel(array('hasMany' => array('Comment'))); $TestModel->resetAssociations(); $this->assertTrue(isset($TestModel->hasMany['Comment']), 'Association permanently removed'); } /** * testBindMultipleTimes method with different reset settings * * @return void */ public function testUnBindMultipleTimesWithDifferentResetSettings() { $this->loadFixtures('User', 'Comment', 'Article'); $TestModel = new Comment(); $result = array_keys($TestModel->belongsTo); $expected = array('Article', 'User'); $this->assertEquals($expected, $result); $result = $TestModel->unbindModel(array( 'belongsTo' => array('User') )); $this->assertTrue($result); $result = $TestModel->unbindModel( array('belongsTo' => array('Article')), false ); $this->assertTrue($result); $result = array_keys($TestModel->belongsTo); $expected = array(); $this->assertEquals($expected, $result); $TestModel->resetAssociations(); $result = array_keys($TestModel->belongsTo); $expected = array('User'); $this->assertEquals($expected, $result); } /** * testAssociationAfterFind method * * @return void */ public function testAssociationAfterFind() { $this->loadFixtures('Post', 'Author', 'Comment'); $TestModel = new Post(); $result = $TestModel->find('all', array( 'order' => array('Post.id' => 'ASC') )); $expected = array( array( 'Post' => array( 'id' => '1', 'author_id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Author' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'test' => 'working' )), array( 'Post' => array( 'id' => '2', 'author_id' => '3', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Author' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31', 'test' => 'working' )), array( 'Post' => array( 'id' => '3', 'author_id' => '1', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'Author' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'test' => 'working' ))); $this->assertEquals($expected, $result); unset($TestModel); $Author = new Author(); $Author->Post->bindModel(array( 'hasMany' => array( 'Comment' => array( 'className' => 'ModifiedComment', 'foreignKey' => 'article_id', ) ))); $result = $Author->find('all', array( 'conditions' => array('Author.id' => 1), 'order' => array('Author.id' => 'ASC'), 'recursive' => 2 )); $expected = array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31', 'callback' => 'Fire' ); $this->assertEquals($expected, $result[0]['Post'][0]['Comment'][0]); } /** * testDeeperAssociationAfterFind method * * @return void */ public function testDeeperAssociationAfterFind() { $this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article'); $Post = new Post(); $Post->bindModel(array( 'hasMany' => array( 'Comment' => array( 'className' => 'ModifiedComment', 'foreignKey' => 'article_id', ) ))); $Post->Comment->bindModel(array( 'hasOne' => array( 'Attachment' => array( 'className' => 'ModifiedAttachment', ) ))); $result = $Post->find('first', array( 'conditions' => array('Post.id' => 2), 'recursive' => 2 )); $this->assertTrue(isset($result['Comment'][0]['callback'])); $this->assertEquals('Fire', $result['Comment'][0]['callback']); $this->assertTrue(isset($result['Comment'][0]['Attachment']['callback'])); $this->assertEquals('Fired', $result['Comment'][0]['Attachment']['callback']); } /** * Tests that callbacks can be properly disabled * * @return void */ public function testCallbackDisabling() { $this->loadFixtures('Author'); $TestModel = new ModifiedAuthor(); $result = Hash::extract($TestModel->find('all'), '{n}.Author.user'); $expected = array('mariano (CakePHP)', 'nate (CakePHP)', 'larry (CakePHP)', 'garrett (CakePHP)'); $this->assertEquals($expected, $result); $result = Hash::extract($TestModel->find('all', array('callbacks' => 'after')), '{n}.Author.user'); $expected = array('mariano (CakePHP)', 'nate (CakePHP)', 'larry (CakePHP)', 'garrett (CakePHP)'); $this->assertEquals($expected, $result); $result = Hash::extract($TestModel->find('all', array('callbacks' => 'before')), '{n}.Author.user'); $expected = array('mariano', 'nate', 'larry', 'garrett'); $this->assertEquals($expected, $result); $result = Hash::extract($TestModel->find('all', array('callbacks' => false)), '{n}.Author.user'); $expected = array('mariano', 'nate', 'larry', 'garrett'); $this->assertEquals($expected, $result); } /** * testAssociationAfterFindCallbacksDisabled method * * @return void */ public function testAssociationAfterFindCalbacksDisabled() { $this->loadFixtures('Post', 'Author', 'Comment'); $TestModel = new Post(); $result = $TestModel->find('all', array( 'callbacks' => false, 'order' => array('Post.id' => 'ASC'), )); $expected = array( array( 'Post' => array( 'id' => '1', 'author_id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Author' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' )), array( 'Post' => array( 'id' => '2', 'author_id' => '3', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Author' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' )), array( 'Post' => array( 'id' => '3', 'author_id' => '1', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'Author' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ))); $this->assertEquals($expected, $result); unset($TestModel); $Author = new Author(); $Author->Post->bindModel(array( 'hasMany' => array( 'Comment' => array( 'className' => 'ModifiedComment', 'foreignKey' => 'article_id', ) ))); $result = $Author->find('all', array( 'conditions' => array('Author.id' => 1), 'recursive' => 2, 'order' => array('Author.id' => 'ASC'), 'callbacks' => false )); $expected = array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ); $this->assertEquals($expected, $result[0]['Post'][0]['Comment'][0]); } /** * Tests that the database configuration assigned to the model can be changed using * (before|after)Find callbacks * * @return void */ public function testCallbackSourceChange() { $this->loadFixtures('Post'); $TestModel = new Post(); $this->assertEquals(3, count($TestModel->find('all'))); } /** * testCallbackSourceChangeUnknownDatasource method * * @expectedException MissingDatasourceConfigException * @return void */ public function testCallbackSourceChangeUnknownDatasource() { $this->loadFixtures('Post', 'Author'); $TestModel = new Post(); $this->assertFalse($TestModel->find('all', array('connection' => 'foo'))); } /** * testMultipleBelongsToWithSameClass method * * @return void */ public function testMultipleBelongsToWithSameClass() { $this->loadFixtures( 'DeviceType', 'DeviceTypeCategory', 'FeatureSet', 'ExteriorTypeCategory', 'Document', 'Device', 'DocumentDirectory' ); $DeviceType = new DeviceType(); $DeviceType->recursive = 2; $result = $DeviceType->read(null, 1); $expected = array( 'DeviceType' => array( 'id' => 1, 'device_type_category_id' => 1, 'feature_set_id' => 1, 'exterior_type_category_id' => 1, 'image_id' => 1, 'extra1_id' => 1, 'extra2_id' => 1, 'name' => 'DeviceType 1', 'order' => 0 ), 'Image' => array( 'id' => 1, 'document_directory_id' => 1, 'name' => 'Document 1', 'DocumentDirectory' => array( 'id' => 1, 'name' => 'DocumentDirectory 1' )), 'Extra1' => array( 'id' => 1, 'document_directory_id' => 1, 'name' => 'Document 1', 'DocumentDirectory' => array( 'id' => 1, 'name' => 'DocumentDirectory 1' )), 'Extra2' => array( 'id' => 1, 'document_directory_id' => 1, 'name' => 'Document 1', 'DocumentDirectory' => array( 'id' => 1, 'name' => 'DocumentDirectory 1' )), 'DeviceTypeCategory' => array( 'id' => 1, 'name' => 'DeviceTypeCategory 1' ), 'FeatureSet' => array( 'id' => 1, 'name' => 'FeatureSet 1' ), 'ExteriorTypeCategory' => array( 'id' => 1, 'image_id' => 1, 'name' => 'ExteriorTypeCategory 1', 'Image' => array( 'id' => 1, 'device_type_id' => 1, 'name' => 'Device 1', 'typ' => 1 )), 'Device' => array( array( 'id' => 1, 'device_type_id' => 1, 'name' => 'Device 1', 'typ' => 1 ), array( 'id' => 2, 'device_type_id' => 1, 'name' => 'Device 2', 'typ' => 1 ), array( 'id' => 3, 'device_type_id' => 1, 'name' => 'Device 3', 'typ' => 2 ))); $this->assertEquals($expected, $result); } /** * testHabtmRecursiveBelongsTo method * * @return void */ public function testHabtmRecursiveBelongsTo() { $this->loadFixtures('Portfolio', 'Item', 'ItemsPortfolio', 'Syfile', 'Image'); $Portfolio = new Portfolio(); $result = $Portfolio->find('first', array('conditions' => array('id' => 2), 'recursive' => 3)); $expected = array( 'Portfolio' => array( 'id' => 2, 'seller_id' => 1, 'name' => 'Portfolio 2' ), 'Item' => array( array( 'id' => 2, 'syfile_id' => 2, 'published' => false, 'name' => 'Item 2', 'ItemsPortfolio' => array( 'id' => 2, 'item_id' => 2, 'portfolio_id' => 2 ), 'Syfile' => array( 'id' => 2, 'image_id' => 2, 'name' => 'Syfile 2', 'item_count' => null, 'Image' => array( 'id' => 2, 'name' => 'Image 2' ) )), array( 'id' => 6, 'syfile_id' => 6, 'published' => false, 'name' => 'Item 6', 'ItemsPortfolio' => array( 'id' => 6, 'item_id' => 6, 'portfolio_id' => 2 ), 'Syfile' => array( 'id' => 6, 'image_id' => null, 'name' => 'Syfile 6', 'item_count' => null, 'Image' => array() )))); $this->assertEquals($expected, $result); } /** * testNonNumericHabtmJoinKey method * * @return void */ public function testNonNumericHabtmJoinKey() { $this->loadFixtures('Post', 'Tag', 'PostsTag', 'Author'); $Post = new Post(); $Post->bindModel(array( 'hasAndBelongsToMany' => array('Tag') )); $Post->Tag->primaryKey = 'tag'; $result = $Post->find('all', array( 'order' => 'Post.id ASC', )); $expected = array( array( 'Post' => array( 'id' => '1', 'author_id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'Author' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'test' => 'working' ), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ))), array( 'Post' => array( 'id' => '2', 'author_id' => '3', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Author' => array( 'id' => 3, 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31', 'test' => 'working' ), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ))), array( 'Post' => array( 'id' => '3', 'author_id' => '1', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'Author' => array( 'id' => 1, 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'test' => 'working' ), 'Tag' => array() )); $this->assertEquals($expected, $result); } /** * testHabtmFinderQuery method * * @return void */ public function testHabtmFinderQuery() { $this->loadFixtures('Article', 'Tag', 'ArticlesTag'); $Article = new Article(); $sql = $this->db->buildStatement( array( 'fields' => $this->db->fields($Article->Tag, null, array( 'Tag.id', 'Tag.tag', 'ArticlesTag.article_id', 'ArticlesTag.tag_id' )), 'table' => $this->db->fullTableName('tags'), 'alias' => 'Tag', 'limit' => null, 'offset' => null, 'group' => null, 'joins' => array(array( 'alias' => 'ArticlesTag', 'table' => 'articles_tags', 'conditions' => array( array("ArticlesTag.article_id" => '{$__cakeID__$}'), array("ArticlesTag.tag_id" => $this->db->identifier('Tag.id')) ) )), 'conditions' => array(), 'order' => null ), $Article ); $Article->hasAndBelongsToMany['Tag']['finderQuery'] = $sql; $result = $Article->find('first'); $expected = array( array( 'id' => '1', 'tag' => 'tag1' ), array( 'id' => '2', 'tag' => 'tag2' )); $this->assertEquals($expected, $result['Tag']); } /** * testHabtmLimitOptimization method * * @return void */ public function testHabtmLimitOptimization() { $this->loadFixtures('Article', 'User', 'Comment', 'Tag', 'ArticlesTag'); $TestModel = new Article(); $TestModel->hasAndBelongsToMany['Tag']['limit'] = 2; $result = $TestModel->read(null, 2); $expected = array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'Comment' => array( array( 'id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ), array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' )), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ))); $this->assertEquals($expected, $result); $TestModel->hasAndBelongsToMany['Tag']['limit'] = 1; $result = $TestModel->read(null, 2); unset($expected['Tag'][1]); $this->assertEquals($expected, $result); } /** * testHasManyLimitOptimization method * * @return void */ public function testHasManyLimitOptimization() { $this->loadFixtures('Project', 'Thread', 'Message', 'Bid'); $Project = new Project(); $Project->recursive = 3; $result = $Project->find('all', array( 'order' => 'Project.id ASC', )); $expected = array( array( 'Project' => array( 'id' => 1, 'name' => 'Project 1' ), 'Thread' => array( array( 'id' => 1, 'project_id' => 1, 'name' => 'Project 1, Thread 1', 'Project' => array( 'id' => 1, 'name' => 'Project 1', 'Thread' => array( array( 'id' => 1, 'project_id' => 1, 'name' => 'Project 1, Thread 1' ), array( 'id' => 2, 'project_id' => 1, 'name' => 'Project 1, Thread 2' ))), 'Message' => array( array( 'id' => 1, 'thread_id' => 1, 'name' => 'Thread 1, Message 1', 'Bid' => array( 'id' => 1, 'message_id' => 1, 'name' => 'Bid 1.1' )))), array( 'id' => 2, 'project_id' => 1, 'name' => 'Project 1, Thread 2', 'Project' => array( 'id' => 1, 'name' => 'Project 1', 'Thread' => array( array( 'id' => 1, 'project_id' => 1, 'name' => 'Project 1, Thread 1' ), array( 'id' => 2, 'project_id' => 1, 'name' => 'Project 1, Thread 2' ))), 'Message' => array( array( 'id' => 2, 'thread_id' => 2, 'name' => 'Thread 2, Message 1', 'Bid' => array( 'id' => 4, 'message_id' => 2, 'name' => 'Bid 2.1' )))))), array( 'Project' => array( 'id' => 2, 'name' => 'Project 2' ), 'Thread' => array( array( 'id' => 3, 'project_id' => 2, 'name' => 'Project 2, Thread 1', 'Project' => array( 'id' => 2, 'name' => 'Project 2', 'Thread' => array( array( 'id' => 3, 'project_id' => 2, 'name' => 'Project 2, Thread 1' ))), 'Message' => array( array( 'id' => 3, 'thread_id' => 3, 'name' => 'Thread 3, Message 1', 'Bid' => array( 'id' => 3, 'message_id' => 3, 'name' => 'Bid 3.1' )))))), array( 'Project' => array( 'id' => 3, 'name' => 'Project 3' ), 'Thread' => array() )); $this->assertEquals($expected, $result); } /** * testFindAllRecursiveSelfJoin method * * @return void */ public function testFindAllRecursiveSelfJoin() { $this->loadFixtures('Home', 'AnotherArticle', 'Advertisement'); $TestModel = new Home(); $TestModel->recursive = 2; $result = $TestModel->find('all', array( 'order' => 'Home.id ASC', )); $expected = array( array( 'Home' => array( 'id' => '1', 'another_article_id' => '1', 'advertisement_id' => '1', 'title' => 'First Home', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'AnotherArticle' => array( 'id' => '1', 'title' => 'First Article', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Home' => array( array( 'id' => '1', 'another_article_id' => '1', 'advertisement_id' => '1', 'title' => 'First Home', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ))), 'Advertisement' => array( 'id' => '1', 'title' => 'First Ad', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Home' => array( array( 'id' => '1', 'another_article_id' => '1', 'advertisement_id' => '1', 'title' => 'First Home', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => '2', 'another_article_id' => '3', 'advertisement_id' => '1', 'title' => 'Second Home', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' )))), array( 'Home' => array( 'id' => '2', 'another_article_id' => '3', 'advertisement_id' => '1', 'title' => 'Second Home', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'AnotherArticle' => array( 'id' => '3', 'title' => 'Third Article', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'Home' => array( array( 'id' => '2', 'another_article_id' => '3', 'advertisement_id' => '1', 'title' => 'Second Home', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ))), 'Advertisement' => array( 'id' => '1', 'title' => 'First Ad', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'Home' => array( array( 'id' => '1', 'another_article_id' => '1', 'advertisement_id' => '1', 'title' => 'First Home', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => '2', 'another_article_id' => '3', 'advertisement_id' => '1', 'title' => 'Second Home', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ))))); $this->assertEquals($expected, $result); } /** * testFindAllRecursiveWithHabtm method * * @return void */ public function testFindAllRecursiveWithHabtm() { $this->loadFixtures( 'MyCategoriesMyUsers', 'MyCategoriesMyProducts', 'MyCategory', 'MyUser', 'MyProduct' ); $MyUser = new MyUser(); $MyUser->recursive = 2; $result = $MyUser->find('all', array( 'order' => 'MyUser.id ASC' )); $expected = array( array( 'MyUser' => array('id' => '1', 'firstname' => 'userA'), 'MyCategory' => array( array( 'id' => '1', 'name' => 'A', 'MyProduct' => array( array( 'id' => '1', 'name' => 'book' ))), array( 'id' => '3', 'name' => 'C', 'MyProduct' => array( array( 'id' => '2', 'name' => 'computer' ))))), array( 'MyUser' => array( 'id' => '2', 'firstname' => 'userB' ), 'MyCategory' => array( array( 'id' => '1', 'name' => 'A', 'MyProduct' => array( array( 'id' => '1', 'name' => 'book' ))), array( 'id' => '2', 'name' => 'B', 'MyProduct' => array( array( 'id' => '1', 'name' => 'book' ), array( 'id' => '2', 'name' => 'computer' )))))); $this->assertEquals($expected, $result); } /** * testReadFakeThread method * * @return void */ public function testReadFakeThread() { $this->loadFixtures('CategoryThread'); $TestModel = new CategoryThread(); $fullDebug = $this->db->fullDebug; $this->db->fullDebug = true; $TestModel->recursive = 6; $TestModel->id = 7; $result = $TestModel->read(); $expected = array( 'CategoryThread' => array( 'id' => 7, 'parent_id' => 6, 'name' => 'Category 2.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'ParentCategory' => array( 'id' => 6, 'parent_id' => 5, 'name' => 'Category 2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 5, 'parent_id' => 4, 'name' => 'Category 1.1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 4, 'parent_id' => 3, 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 3, 'parent_id' => 2, 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 2, 'parent_id' => 1, 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ))))))); $this->db->fullDebug = $fullDebug; $this->assertEquals($expected, $result); } /** * testFindFakeThread method * * @return void */ public function testFindFakeThread() { $this->loadFixtures('CategoryThread'); $TestModel = new CategoryThread(); $fullDebug = $this->db->fullDebug; $this->db->fullDebug = true; $TestModel->recursive = 6; $result = $TestModel->find('first', array('conditions' => array('CategoryThread.id' => 7))); $expected = array( 'CategoryThread' => array( 'id' => 7, 'parent_id' => 6, 'name' => 'Category 2.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'ParentCategory' => array( 'id' => 6, 'parent_id' => 5, 'name' => 'Category 2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 5, 'parent_id' => 4, 'name' => 'Category 1.1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 4, 'parent_id' => 3, 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 3, 'parent_id' => 2, 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 2, 'parent_id' => 1, 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ))))))); $this->db->fullDebug = $fullDebug; $this->assertEquals($expected, $result); } /** * testFindAllFakeThread method * * @return void */ public function testFindAllFakeThread() { $this->loadFixtures('CategoryThread'); $TestModel = new CategoryThread(); $fullDebug = $this->db->fullDebug; $this->db->fullDebug = true; $TestModel->recursive = 6; $result = $TestModel->find('all'); $expected = array( array( 'CategoryThread' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'ParentCategory' => array( 'id' => null, 'parent_id' => null, 'name' => null, 'created' => null, 'updated' => null, 'ParentCategory' => array() )), array( 'CategoryThread' => array( 'id' => 2, 'parent_id' => 1, 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'ParentCategory' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array() )), array( 'CategoryThread' => array( 'id' => 3, 'parent_id' => 2, 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'ParentCategory' => array( 'id' => 2, 'parent_id' => 1, 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array() ))), array( 'CategoryThread' => array( 'id' => 4, 'parent_id' => 3, 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'ParentCategory' => array( 'id' => 3, 'parent_id' => 2, 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 2, 'parent_id' => 1, 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array() )))), array( 'CategoryThread' => array( 'id' => 5, 'parent_id' => 4, 'name' => 'Category 1.1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'ParentCategory' => array( 'id' => 4, 'parent_id' => 3, 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 3, 'parent_id' => 2, 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 2, 'parent_id' => 1, 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array() ))))), array( 'CategoryThread' => array( 'id' => 6, 'parent_id' => 5, 'name' => 'Category 2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'ParentCategory' => array( 'id' => 5, 'parent_id' => 4, 'name' => 'Category 1.1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 4, 'parent_id' => 3, 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 3, 'parent_id' => 2, 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 2, 'parent_id' => 1, 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array() )))))), array( 'CategoryThread' => array( 'id' => 7, 'parent_id' => 6, 'name' => 'Category 2.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ), 'ParentCategory' => array( 'id' => 6, 'parent_id' => 5, 'name' => 'Category 2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 5, 'parent_id' => 4, 'name' => 'Category 1.1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 4, 'parent_id' => 3, 'name' => 'Category 1.1.2', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 3, 'parent_id' => 2, 'name' => 'Category 1.1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 2, 'parent_id' => 1, 'name' => 'Category 1.1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31', 'ParentCategory' => array( 'id' => 1, 'parent_id' => 0, 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' )))))))); $this->db->fullDebug = $fullDebug; $this->assertEquals($expected, $result); } /** * testConditionalNumerics method * * @return void */ public function testConditionalNumerics() { $this->loadFixtures('NumericArticle'); $NumericArticle = new NumericArticle(); $data = array('conditions' => array('title' => '12345abcde')); $result = $NumericArticle->find('first', $data); $this->assertTrue(!empty($result)); $data = array('conditions' => array('title' => '12345')); $result = $NumericArticle->find('first', $data); $this->assertTrue(empty($result)); } /** * test buildQuery() * * @return void */ public function testBuildQuery() { $this->loadFixtures('User'); $TestModel = new User(); $TestModel->cacheQueries = false; $TestModel->order = null; $expected = array( 'conditions' => array( 'user' => 'larry' ), 'fields' => null, 'joins' => array(), 'limit' => null, 'offset' => null, 'order' => array(), 'page' => 1, 'group' => null, 'callbacks' => true, 'returnQuery' => true ); $result = $TestModel->buildQuery('all', array('returnQuery' => true, 'conditions' => array('user' => 'larry'))); $this->assertEquals($expected, $result); } /** * test find('all') method * * @return void */ public function testFindAll() { $this->loadFixtures('User'); $TestModel = new User(); $TestModel->cacheQueries = false; $result = $TestModel->find('all'); $expected = array( array( 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' )), array( 'User' => array( 'id' => '2', 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' )), array( 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' )), array( 'User' => array( 'id' => '4', 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ))); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array('conditions' => 'User.id > 2')); $expected = array( array( 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' )), array( 'User' => array( 'id' => '4', 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ))); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array( 'conditions' => array('User.id !=' => '0', 'User.user LIKE' => '%arr%') )); $expected = array( array( 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' )), array( 'User' => array( 'id' => '4', 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ))); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array('conditions' => array('User.id' => '0'))); $expected = array(); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array( 'conditions' => array('or' => array('User.id' => '0', 'User.user LIKE' => '%a%') ))); $expected = array( array( 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' )), array( 'User' => array( 'id' => '2', 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' )), array( 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' )), array( 'User' => array( 'id' => '4', 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ))); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array('fields' => 'User.id, User.user')); $expected = array( array('User' => array('id' => '1', 'user' => 'mariano')), array('User' => array('id' => '2', 'user' => 'nate')), array('User' => array('id' => '3', 'user' => 'larry')), array('User' => array('id' => '4', 'user' => 'garrett'))); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array('fields' => 'User.user', 'order' => 'User.user ASC')); $expected = array( array('User' => array('user' => 'garrett')), array('User' => array('user' => 'larry')), array('User' => array('user' => 'mariano')), array('User' => array('user' => 'nate'))); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array('fields' => 'User.user', 'order' => 'User.user DESC')); $expected = array( array('User' => array('user' => 'nate')), array('User' => array('user' => 'mariano')), array('User' => array('user' => 'larry')), array('User' => array('user' => 'garrett'))); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array('limit' => 3, 'page' => 1)); $expected = array( array( 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' )), array( 'User' => array( 'id' => '2', 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' )), array( 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ))); $this->assertEquals($expected, $result); $ids = array(4 => 1, 5 => 3); $result = $TestModel->find('all', array( 'conditions' => array('User.id' => $ids), 'order' => 'User.id' )); $expected = array( array( 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' )), array( 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ))); $this->assertEquals($expected, $result); // These tests are expected to fail on SQL Server since the LIMIT/OFFSET // hack can't handle small record counts. if (!($this->db instanceof Sqlserver)) { $result = $TestModel->find('all', array('limit' => 3, 'page' => 2)); $expected = array( array( 'User' => array( 'id' => '4', 'user' => 'garrett', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:22:23', 'updated' => '2007-03-17 01:24:31' ))); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array('limit' => 3, 'page' => 3)); $expected = array(); $this->assertEquals($expected, $result); } } /** * Test that find() with array conditions works when there is only one element. * * @return void */ public function testFindAllArrayConditions() { $this->loadFixtures('User'); $TestModel = new User(); $TestModel->cacheQueries = false; $result = $TestModel->find('all', array( 'conditions' => array('User.id' => array(3)), )); $expected = array( array( 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' )) ); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array( 'conditions' => array('User.user' => array('larry')), )); $this->assertEquals($expected, $result); } /** * test find('list') method * * @return void */ public function testFindList() { $this->loadFixtures('Article', 'Apple', 'Post', 'Author', 'User', 'Comment'); $TestModel = new Article(); $TestModel->displayField = 'title'; $result = $TestModel->find('list', array( 'order' => 'Article.title ASC' )); $expected = array( 1 => 'First Article', 2 => 'Second Article', 3 => 'Third Article' ); $this->assertEquals($expected, $result); $db = ConnectionManager::getDataSource('test'); if ($db instanceof Mysql) { $result = $TestModel->find('list', array( 'order' => array('FIELD(Article.id, 3, 2) ASC', 'Article.title ASC') )); $expected = array( 1 => 'First Article', 3 => 'Third Article', 2 => 'Second Article' ); $this->assertEquals($expected, $result); } $result = Hash::combine( $TestModel->find('all', array( 'order' => 'Article.title ASC', 'fields' => array('id', 'title') )), '{n}.Article.id', '{n}.Article.title' ); $expected = array( 1 => 'First Article', 2 => 'Second Article', 3 => 'Third Article' ); $this->assertEquals($expected, $result); $result = Hash::combine( $TestModel->find('all', array( 'order' => 'Article.title ASC' )), '{n}.Article.id', '{n}.Article' ); $expected = array( 1 => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 2 => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 3 => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' )); $this->assertEquals($expected, $result); $result = Hash::combine( $TestModel->find('all', array( 'order' => 'Article.title ASC' )), '{n}.Article.id', '{n}.Article', '{n}.Article.user_id' ); $expected = array( 1 => array( 1 => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 3 => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' )), 3 => array( 2 => array( 'id' => 2, 'user_id' => 3, 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ))); $this->assertEquals($expected, $result); $result = Hash::combine( $TestModel->find('all', array( 'order' => 'Article.title ASC', 'fields' => array('id', 'title', 'user_id') )), '{n}.Article.id', '{n}.Article.title', '{n}.Article.user_id' ); $expected = array( 1 => array( 1 => 'First Article', 3 => 'Third Article' ), 3 => array( 2 => 'Second Article' )); $this->assertEquals($expected, $result); $TestModel = new Apple(); $expected = array( 1 => 'Red Apple 1', 2 => 'Bright Red Apple', 3 => 'green blue', 4 => 'Test Name', 5 => 'Blue Green', 6 => 'My new apple', 7 => 'Some odd color' ); $this->assertEquals($expected, $TestModel->find('list')); $this->assertEquals($expected, $TestModel->Parent->find('list')); $TestModel = new Post(); $result = $TestModel->find('list', array( 'fields' => 'Post.title' )); $expected = array( 1 => 'First Post', 2 => 'Second Post', 3 => 'Third Post' ); $this->assertEquals($expected, $result); $result = $TestModel->find('list', array( 'fields' => 'title' )); $expected = array( 1 => 'First Post', 2 => 'Second Post', 3 => 'Third Post' ); $this->assertEquals($expected, $result); $result = $TestModel->find('list', array( 'fields' => array('title', 'id') )); $expected = array( 'First Post' => '1', 'Second Post' => '2', 'Third Post' => '3' ); $this->assertEquals($expected, $result); $result = $TestModel->find('list', array( 'fields' => array('title', 'id', 'created') )); $expected = array( '2007-03-18 10:39:23' => array( 'First Post' => '1' ), '2007-03-18 10:41:23' => array( 'Second Post' => '2' ), '2007-03-18 10:43:23' => array( 'Third Post' => '3' ), ); $this->assertEquals($expected, $result); $result = $TestModel->find('list', array( 'fields' => array('Post.body') )); $expected = array( 1 => 'First Post Body', 2 => 'Second Post Body', 3 => 'Third Post Body' ); $this->assertEquals($expected, $result); $result = $TestModel->find('list', array( 'fields' => array('Post.title', 'Post.body') )); $expected = array( 'First Post' => 'First Post Body', 'Second Post' => 'Second Post Body', 'Third Post' => 'Third Post Body' ); $this->assertEquals($expected, $result); $result = $TestModel->find('list', array( 'fields' => array('Post.id', 'Post.title', 'Author.user'), 'recursive' => 1 )); $expected = array( 'mariano' => array( 1 => 'First Post', 3 => 'Third Post' ), 'larry' => array( 2 => 'Second Post' )); $this->assertEquals($expected, $result); $TestModel = new User(); $result = $TestModel->find('list', array( 'fields' => array('User.user', 'User.password') )); $expected = array( 'mariano' => '5f4dcc3b5aa765d61d8327deb882cf99', 'nate' => '5f4dcc3b5aa765d61d8327deb882cf99', 'larry' => '5f4dcc3b5aa765d61d8327deb882cf99', 'garrett' => '5f4dcc3b5aa765d61d8327deb882cf99' ); $this->assertEquals($expected, $result); $TestModel = new ModifiedAuthor(); $result = $TestModel->find('list', array( 'fields' => array('Author.id', 'Author.user') )); $expected = array( 1 => 'mariano (CakePHP)', 2 => 'nate (CakePHP)', 3 => 'larry (CakePHP)', 4 => 'garrett (CakePHP)' ); $this->assertEquals($expected, $result); $TestModel = new Article(); $TestModel->displayField = 'title'; $result = $TestModel->find('list', array( 'conditions' => array('User.user' => 'mariano'), 'recursive' => 0 )); $expected = array( 1 => 'First Article', 3 => 'Third Article' ); $this->assertEquals($expected, $result); } /** * Test that find(list) works with array conditions that have only one element. * * @return void */ public function testFindListArrayCondition() { $this->loadFixtures('User'); $TestModel = new User(); $TestModel->cacheQueries = false; $result = $TestModel->find('list', array( 'fields' => array('id', 'user'), 'conditions' => array('User.id' => array(3)), )); $expected = array( 3 => 'larry' ); $this->assertEquals($expected, $result); $result = $TestModel->find('list', array( 'fields' => array('id', 'user'), 'conditions' => array('User.user' => array('larry')), )); $this->assertEquals($expected, $result); } /** * testFindField method * * @return void */ public function testFindField() { $this->loadFixtures('User'); $TestModel = new User(); $TestModel->id = 1; $result = $TestModel->field('user'); $this->assertEquals('mariano', $result); $result = $TestModel->field('User.user'); $this->assertEquals('mariano', $result); $TestModel->id = false; $result = $TestModel->field('user', array( 'user' => 'mariano' )); $this->assertEquals('mariano', $result); $TestModel->order = null; $result = $TestModel->field('COUNT(*) AS count', true); $this->assertEquals(4, $result); $result = $TestModel->field('COUNT(*)', true); $this->assertEquals(4, $result); } /** * testFindUnique method * * @return void */ public function testFindUnique() { $this->loadFixtures('User'); $TestModel = new User(); $this->assertFalse($TestModel->isUnique(array( 'user' => 'nate' ))); $TestModel->id = 2; $this->assertTrue($TestModel->isUnique(array( 'user' => 'nate' ))); $this->assertFalse($TestModel->isUnique(array( 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99' ))); } /** * test find('count') method * * @return void */ public function testFindCount() { $this->loadFixtures('User', 'Article', 'Comment', 'Tag', 'ArticlesTag'); $TestModel = new User(); $this->db->getLog(false, true); $result = $TestModel->find('count'); $this->assertEquals(4, $result); $this->db->getLog(false, true); $fullDebug = $this->db->fullDebug; $this->db->fullDebug = true; $TestModel->order = 'User.id'; $result = $TestModel->find('count'); $this->db->fullDebug = $fullDebug; $this->assertEquals(4, $result); $log = $this->db->getLog(); $this->assertTrue(isset($log['log'][0]['query'])); $this->assertNotRegExp('/ORDER\s+BY/', $log['log'][0]['query']); $Article = new Article(); $Article->order = null; $Article->recursive = -1; $expected = count($Article->find('all', array( 'fields' => array('Article.user_id'), 'group' => 'Article.user_id') )); $result = $Article->find('count', array('group' => array('Article.user_id'))); $this->assertEquals($expected, $result); $expected = count($Article->find('all', array( 'fields' => array('Article.user_id'), 'conditions' => array('Article.user_id' => 1), 'group' => 'Article.user_id') )); $result = $Article->find('count', array( 'conditions' => array('Article.user_id' => 1), 'group' => array('Article.user_id'), )); $this->assertEquals($expected, $result); } /** * Test that find('first') does not use the id set to the object. * * @return void */ public function testFindFirstNoIdUsed() { $this->loadFixtures('Project'); $Project = new Project(); $Project->id = 3; $result = $Project->find('first'); $this->assertEquals('Project 1', $result['Project']['name'], 'Wrong record retrieved'); } /** * test find with COUNT(DISTINCT field) * * @return void */ public function testFindCountDistinct() { $this->skipIf($this->db instanceof Sqlite, 'SELECT COUNT(DISTINCT field) is not compatible with SQLite.'); $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.'); $this->loadFixtures('Project', 'Thread'); $TestModel = new Project(); $TestModel->create(array('name' => 'project')) && $TestModel->save(); $TestModel->create(array('name' => 'project')) && $TestModel->save(); $TestModel->create(array('name' => 'project')) && $TestModel->save(); $result = $TestModel->find('count', array('fields' => 'DISTINCT name')); $this->assertEquals(4, $result); } /** * Test find(count) with Db::expression * * @return void */ public function testFindCountWithDbExpressions() { $this->skipIf($this->db instanceof Postgres, 'testFindCountWithDbExpressions is not compatible with Postgres.'); $this->loadFixtures('Project', 'Thread'); $db = ConnectionManager::getDataSource('test'); $TestModel = new Project(); $result = $TestModel->find('count', array('conditions' => array( $db->expression('Project.name = \'Project 3\'') ))); $this->assertEquals(1, $result); $result = $TestModel->find('count', array('conditions' => array( 'Project.name' => $db->expression('\'Project 3\'') ))); $this->assertEquals(1, $result); } /** * testFindMagic method * * @return void */ public function testFindMagic() { $this->loadFixtures('User', 'Comment', 'Article'); $TestModel = new User(); $result = $TestModel->findByUser('mariano'); $expected = array( 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' )); $this->assertEquals($expected, $result); $result = $TestModel->findByPassword('5f4dcc3b5aa765d61d8327deb882cf99'); $expected = array('User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' )); $this->assertEquals($expected, $result); $Comment = new Comment(); $Comment->recursive = -1; $results = $Comment->findAllByUserId(1); $expected = array( array( 'Comment' => array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ) ), array( 'Comment' => array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), array( 'Comment' => array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ) ) ); $this->assertEquals($expected, $results); $results = $Comment->findAllByUserIdAndPublished(1, 'Y'); $expected = array( array( 'Comment' => array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ) ), array( 'Comment' => array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ) ) ); $this->assertEquals($expected, $results); $Article = new CustomArticle(); $Article->recursive = -1; $results = $Article->findListByUserId(1); $expected = array( 1 => 'First Article', 3 => 'Third Article' ); $this->assertEquals($expected, $results); $results = $Article->findPublishedByUserId(1); $expected = array( array( 'CustomArticle' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ) ), array( 'CustomArticle' => array( 'id' => 3, 'user_id' => 1, 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ); $this->assertEquals($expected, $results); $results = $Article->findUnPublishedByUserId(1); $expected = array(); $this->assertEquals($expected, $results); } /** * testRead method * * @return void */ public function testRead() { $this->loadFixtures('User', 'Article'); $TestModel = new User(); $result = $TestModel->read(); $this->assertFalse($result); $TestModel->id = 2; $result = $TestModel->read(); $expected = array( 'User' => array( 'id' => '2', 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' )); $this->assertEquals($expected, $result); $result = $TestModel->read(null, 2); $expected = array( 'User' => array( 'id' => '2', 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' )); $this->assertEquals($expected, $result); $TestModel->id = 2; $result = $TestModel->read(array('id', 'user')); $expected = array('User' => array('id' => '2', 'user' => 'nate')); $this->assertEquals($expected, $result); $result = $TestModel->read('id, user', 2); $expected = array( 'User' => array( 'id' => '2', 'user' => 'nate' )); $this->assertEquals($expected, $result); $result = $TestModel->bindModel(array('hasMany' => array('Article'))); $this->assertTrue($result); $TestModel->id = 1; $result = $TestModel->read('id, user'); $expected = array( 'User' => array( 'id' => '1', 'user' => 'mariano' ), 'Article' => array( array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => '3', 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ))); $this->assertEquals($expected, $result); } /** * testRecursiveRead method * * @return void */ public function testRecursiveRead() { $this->loadFixtures( 'User', 'Article', 'Comment', 'Tag', 'ArticlesTag', 'Featured', 'ArticleFeatured' ); $TestModel = new User(); $result = $TestModel->bindModel(array('hasMany' => array('Article')), false); $this->assertTrue($result); $TestModel->recursive = 0; $result = $TestModel->read('id, user', 1); $expected = array( 'User' => array('id' => '1', 'user' => 'mariano'), ); $this->assertEquals($expected, $result); $TestModel->recursive = 1; $result = $TestModel->read('id, user', 1); $expected = array( 'User' => array( 'id' => '1', 'user' => 'mariano' ), 'Article' => array( array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), array( 'id' => '3', 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ))); $this->assertEquals($expected, $result); $TestModel->recursive = 2; $result = $TestModel->read('id, user', 3); $expected = array( 'User' => array( 'id' => '3', 'user' => 'larry' ), 'Article' => array( array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'Comment' => array( array( 'id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ), array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' )), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ))))); $this->assertEquals($expected, $result); } public function testRecursiveFindAll() { $this->loadFixtures( 'User', 'Article', 'Comment', 'Tag', 'ArticlesTag', 'Attachment', 'ArticleFeatured', 'ArticleFeaturedsTags', 'Featured', 'Category' ); $TestModel = new Article(); $result = $TestModel->find('all', array('conditions' => array('Article.user_id' => 1))); $expected = array( array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Comment' => array( array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), array( 'id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31' ), array( 'id' => '3', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Third Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:49:23', 'updated' => '2007-03-18 10:51:31' ), array( 'id' => '4', 'article_id' => '1', 'user_id' => '1', 'comment' => 'Fourth Comment for First Article', 'published' => 'N', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ))), array( 'Article' => array( 'id' => '3', 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Comment' => array(), 'Tag' => array() ) ); $this->assertEquals($expected, $result); $result = $TestModel->find('all', array( 'conditions' => array('Article.user_id' => 3), 'limit' => 1, 'recursive' => 2 )); $expected = array( array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'Comment' => array( array( 'id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Attachment' => array( 'id' => '1', 'comment_id' => 5, 'attachment' => 'attachment.zip', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ), array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31', 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => '2', 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'Attachment' => array() ) ), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' )))); $this->assertEquals($expected, $result); $Featured = new Featured(); $Featured->recursive = 2; $Featured->bindModel(array( 'belongsTo' => array( 'ArticleFeatured' => array( 'conditions' => "ArticleFeatured.published = 'Y'", 'fields' => 'id, title, user_id, published' ) ) )); $Featured->ArticleFeatured->unbindModel(array( 'hasMany' => array('Attachment', 'Comment'), 'hasAndBelongsToMany' => array('Tag')) ); $orderBy = 'ArticleFeatured.id ASC'; $result = $Featured->find('all', array( 'order' => $orderBy, 'limit' => 3 )); $expected = array( array( 'Featured' => array( 'id' => '1', 'article_featured_id' => '1', 'category_id' => '1', 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'ArticleFeatured' => array( 'id' => '1', 'title' => 'First Article', 'user_id' => '1', 'published' => 'Y', 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Category' => array(), 'Featured' => array( 'id' => '1', 'article_featured_id' => '1', 'category_id' => '1', 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' )), 'Category' => array( 'id' => '1', 'parent_id' => '0', 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' )), array( 'Featured' => array( 'id' => '2', 'article_featured_id' => '2', 'category_id' => '1', 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'ArticleFeatured' => array( 'id' => '2', 'title' => 'Second Article', 'user_id' => '3', 'published' => 'Y', 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'Category' => array(), 'Featured' => array( 'id' => '2', 'article_featured_id' => '2', 'category_id' => '1', 'published_date' => '2007-03-31 10:39:23', 'end_date' => '2007-05-15 10:39:23', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' )), 'Category' => array( 'id' => '1', 'parent_id' => '0', 'name' => 'Category 1', 'created' => '2007-03-18 15:30:23', 'updated' => '2007-03-18 15:32:31' ))); $this->assertEquals($expected, $result); } /** * testRecursiveFindAllWithLimit method * * @return void */ public function testRecursiveFindAllWithLimit() { $this->loadFixtures('Article', 'User', 'Tag', 'ArticlesTag', 'Comment', 'Attachment'); $TestModel = new Article(); $TestModel->hasMany['Comment']['limit'] = 2; $result = $TestModel->find('all', array( 'conditions' => array('Article.user_id' => 1) )); $expected = array( array( 'Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Comment' => array( array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31' ), array( 'id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31' ), ), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ))), array( 'Article' => array( 'id' => '3', 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Comment' => array(), 'Tag' => array() ) ); $this->assertEquals($expected, $result); $TestModel->hasMany['Comment']['limit'] = 1; $result = $TestModel->find('all', array( 'conditions' => array('Article.user_id' => 3), 'limit' => 1, 'recursive' => 2 )); $expected = array( array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'Comment' => array( array( 'id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31', 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Attachment' => array( 'id' => '1', 'comment_id' => 5, 'attachment' => 'attachment.zip', 'created' => '2007-03-18 10:51:23', 'updated' => '2007-03-18 10:53:31' ) ) ), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ) ) ) ); $this->assertEquals($expected, $result); } /** * Testing availability of $this->findQueryType in Model callbacks * * @return void */ public function testFindQueryTypeInCallbacks() { $this->loadFixtures('Comment'); $Comment = new AgainModifiedComment(); $comments = $Comment->find('all'); $this->assertEquals('all', $comments[0]['Comment']['querytype']); $comments = $Comment->find('first'); $this->assertEquals('first', $comments['Comment']['querytype']); } /** * testVirtualFields() * * Test correct fetching of virtual fields * currently is not possible to do Relation.virtualField * * @return void */ public function testVirtualFields() { $this->loadFixtures('Post', 'Author'); $Post = ClassRegistry::init('Post'); $Post->virtualFields = array('two' => "1 + 1"); $result = $Post->find('first'); $this->assertEquals(2, $result['Post']['two']); // SQL Server does not support operators in expressions if (!($this->db instanceof Sqlserver)) { $Post->Author->virtualFields = array('false' => '1 = 2'); $result = $Post->find('first'); $this->assertEquals(2, $result['Post']['two']); $this->assertFalse((bool)$result['Author']['false']); } $result = $Post->find('first', array('fields' => array('author_id'))); $this->assertFalse(isset($result['Post']['two'])); $this->assertFalse(isset($result['Author']['false'])); $result = $Post->find('first', array('fields' => array('author_id', 'two'))); $this->assertEquals(2, $result['Post']['two']); $this->assertFalse(isset($result['Author']['false'])); $result = $Post->find('first', array('fields' => array('two'))); $this->assertEquals(2, $result['Post']['two']); $Post->id = 1; $result = $Post->field('two'); $this->assertEquals(2, $result); $result = $Post->find('first', array( 'conditions' => array('two' => 2), 'limit' => 1 )); $this->assertEquals(2, $result['Post']['two']); $result = $Post->find('first', array( 'conditions' => array('two <' => 3), 'limit' => 1 )); $this->assertEquals(2, $result['Post']['two']); $result = $Post->find('first', array( 'conditions' => array('NOT' => array('two >' => 3)), 'limit' => 1 )); $this->assertEquals(2, $result['Post']['two']); $dbo = $Post->getDataSource(); $Post->virtualFields = array('other_field' => 'Post.id + 1'); $result = $Post->find('first', array( 'conditions' => array('other_field' => 3), 'limit' => 1 )); $this->assertEquals(2, $result['Post']['id']); $Post->order = null; $Post->virtualFields = array('other_field' => 'Post.id + 1'); $result = $Post->find('all', array( 'fields' => array($dbo->calculate($Post, 'max', array('other_field'))) )); $this->assertEquals(4, $result[0][0]['other_field']); ClassRegistry::flush(); $Writing = ClassRegistry::init(array('class' => 'Post', 'alias' => 'Writing')); $Writing->virtualFields = array('two' => "1 + 1"); $result = $Writing->find('first'); $this->assertEquals(2, $result['Writing']['two']); $Post->create(); $Post->virtualFields = array('other_field' => 'COUNT(Post.id) + 1'); $result = $Post->field('other_field'); $this->assertEquals(4, $result); } /** * Test virtualfields that contain subqueries get correctly * quoted allowing reserved words to be used. * * @return void */ public function testVirtualFieldSubqueryReservedWords() { $this->loadFixtures('User'); $user = ClassRegistry::init('User'); $user->cacheMethods = false; $ds = $user->getDataSource(); $sub = $ds->buildStatement( array( 'fields' => array('Table.user'), 'table' => $ds->fullTableName($user), 'alias' => 'Table', 'limit' => 1, 'conditions' => array( "Table.id > 1" ) ), $user ); $user->virtualFields = array( 'sub_test' => $sub ); $result = $user->find('first'); $this->assertNotEmpty($result); } /** * testVirtualFieldsOrder() * * Test correct order on virtual fields * * @return void */ public function testVirtualFieldsOrder() { $this->loadFixtures('Post', 'Author'); $Post = ClassRegistry::init('Post'); $Post->virtualFields = array('other_field' => '10 - Post.id'); $result = $Post->find('list', array('order' => array('Post.other_field' => 'ASC'))); $expected = array( '3' => 'Third Post', '2' => 'Second Post', '1' => 'First Post' ); $this->assertEquals($expected, $result); $result = $Post->find('list', array('order' => array('Post.other_field' => 'DESC'))); $expected = array( '1' => 'First Post', '2' => 'Second Post', '3' => 'Third Post' ); $this->assertEquals($expected, $result); $Post->Author->virtualFields = array('joined' => 'Post.id * Author.id'); $result = $Post->find('all', array( 'order' => array('Post.id' => 'ASC') )); $result = Hash::extract($result, '{n}.Author.joined'); $expected = array(1, 6, 3); $this->assertEquals($expected, $result); $result = $Post->find('all', array('order' => array('Author.joined' => 'ASC'))); $result = Hash::extract($result, '{n}.Author.joined'); $expected = array(1, 3, 6); $this->assertEquals($expected, $result); $result = $Post->find('all', array('order' => array('Author.joined' => 'DESC'))); $result = Hash::extract($result, '{n}.Author.joined'); $expected = array(6, 3, 1); $this->assertEquals($expected, $result); } /** * testVirtualFieldsMysql() * * Test correct fetching of virtual fields * currently is not possible to do Relation.virtualField * * @return void */ public function testVirtualFieldsMysql() { $this->skipIf(!($this->db instanceof Mysql), 'The rest of virtualFields test only compatible with Mysql.'); $this->loadFixtures('Post', 'Author'); $Post = ClassRegistry::init('Post'); $Post->create(); $Post->virtualFields = array( 'low_title' => 'lower(Post.title)', 'unique_test_field' => 'COUNT(Post.id)' ); $expectation = array( 'Post' => array( 'low_title' => 'first post', 'unique_test_field' => 1 ) ); $result = $Post->find('first', array( 'fields' => array_keys($Post->virtualFields), 'group' => array('low_title') )); $this->assertEquals($expectation, $result); $Author = ClassRegistry::init('Author'); $Author->virtualFields = array( 'full_name' => 'CONCAT(Author.user, " ", Author.id)' ); $result = $Author->find('first', array( 'conditions' => array('Author.user' => 'mariano'), 'fields' => array('Author.password', 'Author.full_name'), 'recursive' => -1 )); $this->assertTrue(isset($result['Author']['full_name'])); $result = $Author->find('first', array( 'conditions' => array('Author.user' => 'mariano'), 'fields' => array('Author.full_name', 'Author.password'), 'recursive' => -1 )); $this->assertTrue(isset($result['Author']['full_name'])); } /** * test that virtual fields work when they don't contain functions. * * @return void */ public function testVirtualFieldAsAString() { $this->loadFixtures('Post', 'Author'); $Post = new Post(); $Post->virtualFields = array( 'writer' => 'Author.user' ); $result = $Post->find('first'); $this->assertTrue(isset($result['Post']['writer']), 'virtual field not fetched %s'); } /** * test that isVirtualField will accept both aliased and non aliased fieldnames * * @return void */ public function testIsVirtualField() { $this->loadFixtures('Post'); $Post = ClassRegistry::init('Post'); $Post->virtualFields = array('other_field' => 'COUNT(Post.id) + 1'); $this->assertTrue($Post->isVirtualField('other_field')); $this->assertTrue($Post->isVirtualField('Post.other_field')); $this->assertFalse($Post->isVirtualField('Comment.other_field'), 'Other models should not match.'); $this->assertFalse($Post->isVirtualField('id')); $this->assertFalse($Post->isVirtualField('Post.id')); $this->assertFalse($Post->isVirtualField(array())); } /** * test that getting virtual fields works with and without model alias attached * * @return void */ public function testGetVirtualField() { $this->loadFixtures('Post'); $Post = ClassRegistry::init('Post'); $Post->virtualFields = array('other_field' => 'COUNT(Post.id) + 1'); $this->assertEquals($Post->getVirtualField('other_field'), $Post->virtualFields['other_field']); $this->assertEquals($Post->getVirtualField('Post.other_field'), $Post->virtualFields['other_field']); } /** * test that checks for error when NOT condition passed in key and a 1 element array value * * @return void */ public function testNotInArrayWithOneValue() { $this->loadFixtures('Article'); $Article = new Article(); $Article->recursive = -1; $result = $Article->find( 'all', array( 'conditions' => array( 'Article.id NOT' => array(1) ) ) ); $this->assertTrue(is_array($result) && !empty($result)); } /** * test to assert that != in key together with a single element array will work * * @return void */ public function testNotEqualsInArrayWithOneValue() { $this->loadFixtures('Article'); $Article = new Article(); $Article->recursive = -1; $result = $Article->find( 'all', array( 'conditions' => array( 'Article.id !=' => array(1) ) ) ); $this->assertTrue(is_array($result) && !empty($result)); } /** * test custom find method * * @return void */ public function testfindCustom() { $this->loadFixtures('Article'); $Article = new CustomArticle(); $data = array('user_id' => 3, 'title' => 'Fourth Article', 'body' => 'Article Body, unpublished', 'published' => 'N'); $Article->create($data); $Article->save(null, false); $this->assertEquals(4, $Article->id); $result = $Article->find('published'); $this->assertEquals(3, count($result)); $result = $Article->find('unPublished'); $this->assertEquals(1, count($result)); } /** * test after find callback on related model * * @return void */ public function testRelatedAfterFindCallback() { $this->loadFixtures('Something', 'SomethingElse', 'JoinThing'); $Something = new Something(); $Something->bindModel(array( 'hasMany' => array( 'HasMany' => array( 'className' => 'JoinThing', 'foreignKey' => 'something_id' ) ), 'hasOne' => array( 'HasOne' => array( 'className' => 'JoinThing', 'foreignKey' => 'something_id' ) ) )); $results = $Something->find('all'); $expected = array( array( 'Something' => array( 'id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ), 'HasOne' => array( 'id' => '1', 'something_id' => '1', 'something_else_id' => '2', 'doomed' => true, 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'afterFind' => 'Successfully added by AfterFind' ), 'HasMany' => array( array( 'id' => '1', 'something_id' => '1', 'something_else_id' => '2', 'doomed' => true, 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'afterFind' => 'Successfully added by AfterFind' ) ), 'SomethingElse' => array( array( 'id' => '2', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'afterFind' => 'Successfully added by AfterFind', 'JoinThing' => array( 'doomed' => true, 'something_id' => '1', 'something_else_id' => '2', 'afterFind' => 'Successfully added by AfterFind' ) ) ) ), array( 'Something' => array( 'id' => '2', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'HasOne' => array( 'id' => '2', 'something_id' => '2', 'something_else_id' => '3', 'doomed' => false, 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'afterFind' => 'Successfully added by AfterFind' ), 'HasMany' => array( array( 'id' => '2', 'something_id' => '2', 'something_else_id' => '3', 'doomed' => false, 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'afterFind' => 'Successfully added by AfterFind' ) ), 'SomethingElse' => array( array( 'id' => '3', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'afterFind' => 'Successfully added by AfterFind', 'JoinThing' => array( 'doomed' => false, 'something_id' => '2', 'something_else_id' => '3', 'afterFind' => 'Successfully added by AfterFind' ) ) ) ), array( 'Something' => array( 'id' => '3', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ), 'HasOne' => array( 'id' => '3', 'something_id' => '3', 'something_else_id' => '1', 'doomed' => true, 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'afterFind' => 'Successfully added by AfterFind' ), 'HasMany' => array( array( 'id' => '3', 'something_id' => '3', 'something_else_id' => '1', 'doomed' => true, 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'afterFind' => 'Successfully added by AfterFind' ) ), 'SomethingElse' => array( array( 'id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'afterFind' => 'Successfully added by AfterFind', 'JoinThing' => array( 'doomed' => true, 'something_id' => '3', 'something_else_id' => '1', 'afterFind' => 'Successfully added by AfterFind' ) ) ) ) ); $this->assertEquals($expected, $results, 'Model related with has* afterFind callback fails'); $JoinThing = new JoinThing(); $JoinThing->unbindModel(array( 'belongsTo' => array( 'Something' ) )); $results = $JoinThing->find('all'); $expected = array( array( 'JoinThing' => array( 'id' => '1', 'something_id' => '1', 'something_else_id' => '2', 'doomed' => true, 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'afterFind' => 'Successfully added by AfterFind' ), 'SomethingElse' => array( 'id' => '2', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'afterFind' => 'Successfully added by AfterFind' ) ), array( 'JoinThing' => array( 'id' => '2', 'something_id' => '2', 'something_else_id' => '3', 'doomed' => false, 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'afterFind' => 'Successfully added by AfterFind' ), 'SomethingElse' => array( 'id' => '3', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'afterFind' => 'Successfully added by AfterFind' ) ), array( 'JoinThing' => array( 'id' => '3', 'something_id' => '3', 'something_else_id' => '1', 'doomed' => true, 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'afterFind' => 'Successfully added by AfterFind' ), 'SomethingElse' => array( 'id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'afterFind' => 'Successfully added by AfterFind' ) ) ); $this->assertEquals($expected, $results, 'Model related with belongsTo afterFind callback fails'); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/ModelTest.php000066400000000000000000000033541265552240500220230ustar00rootroot00000000000000addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'Validator' . DS . 'CakeValidationSetTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'Validator' . DS . 'CakeValidationRuleTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'ModelReadTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'ModelWriteTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'ModelDeleteTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'ModelValidationTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'ModelIntegrationTest.php'); $suite->addTestFile(CORE_TEST_CASES . DS . 'Model' . DS . 'ModelCrossSchemaHabtmTest.php'); return $suite; } } cakephp-2.8.0/lib/Cake/Test/Case/Model/ModelTestBase.php000066400000000000000000000066331265552240500226210ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Model', 'Model'); App::uses('AppModel', 'Model'); require_once dirname(__FILE__) . DS . 'models.php'; /** * ModelBaseTest * * @package Cake.Test.Case.Model */ abstract class BaseModelTest extends CakeTestCase { /** * autoFixtures property * * @var bool */ public $autoFixtures = false; /** * Whether backup global state for each test method or not * * @var bool */ public $backupGlobals = false; /** * fixtures property * * @var array */ public $fixtures = array( 'core.category', 'core.category_thread', 'core.user', 'core.my_category', 'core.my_product', 'core.my_user', 'core.my_categories_my_users', 'core.my_categories_my_products', 'core.article', 'core.featured', 'core.article_featureds_tags', 'core.article_featured', 'core.numeric_article', 'core.tag', 'core.articles_tag', 'core.comment', 'core.attachment', 'core.apple', 'core.sample', 'core.another_article', 'core.item', 'core.advertisement', 'core.home', 'core.post', 'core.author', 'core.bid', 'core.portfolio', 'core.product', 'core.project', 'core.thread', 'core.message', 'core.items_portfolio', 'core.syfile', 'core.image', 'core.device_type', 'core.device_type_category', 'core.feature_set', 'core.exterior_type_category', 'core.document', 'core.device', 'core.document_directory', 'core.primary_model', 'core.secondary_model', 'core.something', 'core.something_else', 'core.join_thing', 'core.join_a', 'core.join_b', 'core.join_c', 'core.join_a_b', 'core.join_a_c', 'core.uuid', 'core.data_test', 'core.posts_tag', 'core.the_paper_monkies', 'core.person', 'core.underscore_field', 'core.node', 'core.dependency', 'core.story', 'core.stories_tag', 'core.cd', 'core.book', 'core.basket', 'core.overall_favorite', 'core.account', 'core.content', 'core.content_account', 'core.film_file', 'core.test_plugin_article', 'core.test_plugin_comment', 'core.uuiditem', 'core.counter_cache_user', 'core.counter_cache_post', 'core.counter_cache_user_nonstandard_primary_key', 'core.counter_cache_post_nonstandard_primary_key', 'core.uuidportfolio', 'core.uuiditems_uuidportfolio', 'core.uuiditems_uuidportfolio_numericid', 'core.fruit', 'core.fruits_uuid_tag', 'core.uuid_tag', 'core.product_update_all', 'core.group_update_all', 'core.player', 'core.guild', 'core.guilds_player', 'core.armor', 'core.armors_player', 'core.bidding', 'core.bidding_message', 'core.site', 'core.domain', 'core.domains_site', ); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->debug = Configure::read('debug'); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); Configure::write('debug', $this->debug); ClassRegistry::flush(); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/ModelValidationTest.php000066400000000000000000002157471265552240500240510ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ require_once dirname(__FILE__) . DS . 'ModelTestBase.php'; /** * ModelValidationTest * * @package Cake.Test.Case.Model */ class ModelValidationTest extends BaseModelTest { /** * override locale to the default (eng). * * @return void */ public function setUp() { parent::setUp(); Configure::write('Config.language', 'eng'); } /** * Tests validation parameter order in custom validation methods * * @return void */ public function testValidationParams() { $TestModel = new ValidationTest1(); $TestModel->validate['title'] = array( 'rule' => 'customValidatorWithParams', 'required' => true ); $TestModel->create(array('title' => 'foo')); $TestModel->invalidFields(); $expected = array( 'data' => array( 'title' => 'foo' ), 'validator' => array( 'rule' => 'customValidatorWithParams', 'on' => null, 'last' => true, 'allowEmpty' => false, 'required' => true, 'message' => null ), 'or' => true, 'ignoreOnSame' => 'id' ); $this->assertEquals($expected, $TestModel->validatorParams); $TestModel->validate['title'] = array( 'rule' => 'customValidatorWithMessage', 'required' => true ); $expected = array( 'title' => array('This field will *never* validate! Muhahaha!') ); $this->assertEquals($expected, $TestModel->invalidFields()); $TestModel->validate['title'] = array( 'rule' => array('customValidatorWithSixParams', 'one', 'two', null, 'four'), 'required' => true ); $TestModel->create(array('title' => 'foo')); $TestModel->invalidFields(); $expected = array( 'data' => array( 'title' => 'foo' ), 'one' => 'one', 'two' => 'two', 'three' => null, 'four' => 'four', 'five' => array( 'rule' => array(1 => 'one', 2 => 'two', 3 => null, 4 => 'four'), 'on' => null, 'last' => true, 'allowEmpty' => false, 'required' => true, 'message' => null ), 'six' => 6 ); $this->assertEquals($expected, $TestModel->validatorParams); $TestModel->validate['title'] = array( 'rule' => array('customValidatorWithSixParams', 'one', array('two'), null, 'four', array('five' => 5)), 'required' => true ); $TestModel->create(array('title' => 'foo')); $TestModel->invalidFields(); $expected = array( 'data' => array( 'title' => 'foo' ), 'one' => 'one', 'two' => array('two'), 'three' => null, 'four' => 'four', 'five' => array('five' => 5), 'six' => array( 'rule' => array(1 => 'one', 2 => array('two'), 3 => null, 4 => 'four', 5 => array('five' => 5)), 'on' => null, 'last' => true, 'allowEmpty' => false, 'required' => true, 'message' => null ) ); $this->assertEquals($expected, $TestModel->validatorParams); } /** * Tests validation parameter fieldList in invalidFields * * @return void */ public function testInvalidFieldsWithFieldListParams() { $TestModel = new ValidationTest1(); $TestModel->validate = $validate = array( 'title' => array( 'rule' => 'alphaNumeric', 'required' => true ), 'name' => array( 'rule' => 'alphaNumeric', 'required' => true )); $TestModel->set(array('title' => '$$', 'name' => '##')); $TestModel->invalidFields(array('fieldList' => array('title'))); $expected = array( 'title' => array('This field cannot be left blank') ); $this->assertEquals($expected, $TestModel->validationErrors); $TestModel->validationErrors = array(); $TestModel->invalidFields(array('fieldList' => array('name'))); $expected = array( 'name' => array('This field cannot be left blank') ); $this->assertEquals($expected, $TestModel->validationErrors); $TestModel->validationErrors = array(); $TestModel->invalidFields(array('fieldList' => array('name', 'title'))); $expected = array( 'name' => array('This field cannot be left blank'), 'title' => array('This field cannot be left blank') ); $this->assertEquals($expected, $TestModel->validationErrors); $TestModel->validationErrors = array(); $TestModel->whitelist = array('name'); $TestModel->invalidFields(); $expected = array('name' => array('This field cannot be left blank')); $this->assertEquals($expected, $TestModel->validationErrors); $this->assertEquals($TestModel->validate, $validate); } /** * Test that invalidFields() integrates well with save(). And that fieldList can be an empty type. * * @return void */ public function testInvalidFieldsWhitelist() { $TestModel = new ValidationTest1(); $TestModel->validate = array( 'title' => array( 'rule' => 'alphaNumeric', 'required' => true ), 'name' => array( 'rule' => 'alphaNumeric', 'required' => true )); $TestModel->whitelist = array('name'); $TestModel->save(array('name' => '#$$#', 'title' => '$$$$')); $expected = array('name' => array('This field cannot be left blank')); $this->assertEquals($expected, $TestModel->validationErrors); } /** * testValidates method * * @return void */ public function testValidates() { $TestModel = new TestValidate(); $TestModel->validate = array( 'user_id' => 'numeric', 'title' => array('allowEmpty' => false, 'rule' => 'notBlank'), 'body' => 'notBlank' ); $data = array('TestValidate' => array( 'user_id' => '1', 'title' => '', 'body' => 'body' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $data = array('TestValidate' => array( 'user_id' => '1', 'title' => 'title', 'body' => 'body' )); $result = $TestModel->create($data) && $TestModel->validates(); $this->assertTrue($result); $data = array('TestValidate' => array( 'user_id' => '1', 'title' => '0', 'body' => 'body' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertTrue($result); $data = array('TestValidate' => array( 'user_id' => '1', 'title' => 0, 'body' => 'body' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertTrue($result); $TestModel->validate['modified'] = array('allowEmpty' => true, 'rule' => 'date'); $data = array('TestValidate' => array( 'user_id' => '1', 'title' => 0, 'body' => 'body', 'modified' => '' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertTrue($result); $data = array('TestValidate' => array( 'user_id' => '1', 'title' => 0, 'body' => 'body', 'modified' => '2007-05-01' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertTrue($result); $data = array('TestValidate' => array( 'user_id' => '1', 'title' => 0, 'body' => 'body', 'modified' => 'invalid-date-here' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $data = array('TestValidate' => array( 'user_id' => '1', 'title' => 0, 'body' => 'body', 'modified' => 0 )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $data = array('TestValidate' => array( 'user_id' => '1', 'title' => 0, 'body' => 'body', 'modified' => '0' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $TestModel->validate['modified'] = array('allowEmpty' => false, 'rule' => 'date'); $data = array('TestValidate' => array('modified' => null)); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $data = array('TestValidate' => array('modified' => false)); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $data = array('TestValidate' => array('modified' => '')); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $data = array('TestValidate' => array( 'modified' => '2007-05-01' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertTrue($result); $TestModel->validate['slug'] = array('allowEmpty' => false, 'rule' => array('maxLength', 45)); $data = array('TestValidate' => array( 'user_id' => '1', 'title' => 0, 'body' => 'body', 'slug' => '' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $data = array('TestValidate' => array( 'user_id' => '1', 'title' => 0, 'body' => 'body', 'slug' => 'slug-right-here' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertTrue($result); $data = array('TestValidate' => array( 'user_id' => '1', 'title' => 0, 'body' => 'body', 'slug' => 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $TestModel->validate = array( 'number' => array( 'rule' => 'validateNumber', 'min' => 3, 'max' => 5 ), 'title' => array( 'allowEmpty' => false, 'rule' => 'notBlank' )); $data = array('TestValidate' => array( 'title' => 'title', 'number' => '0' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $data = array('TestValidate' => array( 'title' => 'title', 'number' => 0 )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $data = array('TestValidate' => array( 'title' => 'title', 'number' => '3' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertTrue($result); $data = array('TestValidate' => array( 'title' => 'title', 'number' => 3 )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertTrue($result); $TestModel->validate = array( 'number' => array( 'rule' => 'validateNumber', 'min' => 5, 'max' => 10 ), 'title' => array( 'allowEmpty' => false, 'rule' => 'notBlank' )); $data = array('TestValidate' => array( 'title' => 'title', 'number' => '3' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $data = array('TestValidate' => array( 'title' => 'title', 'number' => 3 )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $TestModel->validate = array( 'title' => array( 'allowEmpty' => false, 'rule' => 'validateTitle' )); $data = array('TestValidate' => array('title' => '')); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $data = array('TestValidate' => array('title' => 'new title')); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $data = array('TestValidate' => array('title' => 'title-new')); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertTrue($result); $TestModel->validate = array('title' => array( 'allowEmpty' => true, 'rule' => 'validateTitle' )); $data = array('TestValidate' => array('title' => '')); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertTrue($result); $TestModel->validate = array( 'title' => array( 'length' => array( 'allowEmpty' => true, 'rule' => array('maxLength', 10) ))); $data = array('TestValidate' => array('title' => '')); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertTrue($result); $TestModel->validate = array( 'title' => array( 'rule' => array('userDefined', 'Article', 'titleDuplicate') )); $data = array('TestValidate' => array('title' => 'My Article Title')); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertFalse($result); $data = array('TestValidate' => array( 'title' => 'My Article With a Different Title' )); $result = $TestModel->create($data); $this->assertEquals($data, $result); $result = $TestModel->validates(); $this->assertTrue($result); $TestModel->validate = array( 'title' => array( 'tooShort' => array('rule' => array('minLength', 50)), 'onlyLetters' => array('rule' => '/^[a-z]+$/i') ), ); $data = array('TestValidate' => array( 'title' => 'I am a short string' )); $TestModel->create($data); $result = $TestModel->validates(); $this->assertFalse($result); $result = $TestModel->validationErrors; $expected = array( 'title' => array('tooShort') ); $this->assertEquals($expected, $result); $TestModel->validate = array( 'title' => array( 'tooShort' => array( 'rule' => array('minLength', 50), 'last' => false ), 'onlyLetters' => array('rule' => '/^[a-z]+$/i') ), ); $data = array('TestValidate' => array( 'title' => 'I am a short string' )); $TestModel->create($data); $result = $TestModel->validates(); $this->assertFalse($result); $result = $TestModel->validationErrors; $expected = array( 'title' => array('tooShort', 'onlyLetters') ); $this->assertEquals($expected, $result); $result = $TestModel->validationErrors; $this->assertEquals($expected, $result); } /** * test that validates() still performs correctly when useTable = false on the model. * * @return void */ public function testValidatesWithNoTable() { $TestModel = new TheVoid(); $TestModel->validate = array( 'title' => array( 'notEmpty' => array( 'rule' => array('notBlank'), 'required' => true, ), 'tooShort' => array( 'rule' => array('minLength', 10), ), ), ); $data = array( 'TheVoid' => array( 'title' => 'too short', ), ); $TestModel->create($data); $result = $TestModel->validates(); $this->assertFalse($result); $data = array( 'TheVoid' => array( 'id' => '1', 'title' => 'A good title', ), ); $TestModel->create($data); $result = $TestModel->validates(); $this->assertTrue($result); } /** * test that validates() checks all the 'with' associations as well for validation * as this can cause partial/wrong data insertion. * * @return void */ public function testValidatesWithAssociations() { $this->loadFixtures('Something', 'SomethingElse', 'JoinThing'); $data = array( 'Something' => array( 'id' => 5, 'title' => 'Extra Fields', 'body' => 'Extra Fields Body', 'published' => '1' ), 'SomethingElse' => array( array('something_else_id' => 1, 'doomed' => '') ) ); $Something = new Something(); $JoinThing = $Something->JoinThing; $JoinThing->validate = array('doomed' => array('rule' => 'notBlank')); $expectedError = array('doomed' => array('This field cannot be left blank')); $Something->create(); $result = $Something->save($data); $this->assertFalse($result, 'Save occurred even when with models failed. %s'); $this->assertEquals($expectedError, $JoinThing->validationErrors); $count = $Something->find('count', array('conditions' => array('Something.id' => $data['Something']['id']))); $this->assertSame(0, $count); $data = array( 'Something' => array( 'id' => 5, 'title' => 'Extra Fields', 'body' => 'Extra Fields Body', 'published' => '1' ), 'SomethingElse' => array( array('something_else_id' => 1, 'doomed' => 1), array('something_else_id' => 1, 'doomed' => '') ) ); $Something->create(); $result = $Something->save($data); $this->assertFalse($result, 'Save occurred even when with models failed. %s'); $joinRecords = $JoinThing->find('count', array( 'conditions' => array('JoinThing.something_id' => $data['Something']['id']) )); $this->assertEquals(0, $joinRecords, 'Records were saved on the join table. %s'); } /** * Test that if a behavior modifies the model's whitelist validation gets triggered * properly for those fields. * * @return void */ public function testValidateWithFieldListAndBehavior() { $TestModel = new ValidationTest1(); $TestModel->validate = array( 'title' => array( 'rule' => 'notBlank', ), 'name' => array( 'rule' => 'notBlank', )); $TestModel->Behaviors->attach('ValidationRule', array('fields' => array('name'))); $data = array( 'title' => '', 'name' => '', ); $result = $TestModel->save($data, array('fieldList' => array('title'))); $this->assertFalse($result); $expected = array('title' => array('This field cannot be left blank'), 'name' => array('This field cannot be left blank')); $this->assertEquals($expected, $TestModel->validationErrors); } /** * test that saveAll and with models with validation interact well * * @return void */ public function testValidatesWithModelsAndSaveAll() { $this->loadFixtures('Something', 'SomethingElse', 'JoinThing'); $data = array( 'Something' => array( 'id' => 5, 'title' => 'Extra Fields', 'body' => 'Extra Fields Body', 'published' => '1' ), 'SomethingElse' => array( array('something_else_id' => 1, 'doomed' => '') ) ); $Something = new Something(); $JoinThing = $Something->JoinThing; $JoinThing->validate = array('doomed' => array('rule' => 'notBlank')); $expectedError = array('doomed' => array('This field cannot be left blank')); $Something->create(); $result = $Something->saveAll($data, array('validate' => 'only')); $this->assertFalse($result); $result = $Something->validateAssociated($data); $this->assertFalse($result); $this->assertEquals($expectedError, $JoinThing->validationErrors); $result = $Something->validator()->validateAssociated($data); $this->assertFalse($result); $Something->create(); $result = $Something->saveAll($data, array('validate' => 'first')); $this->assertFalse($result); $this->assertEquals($expectedError, $JoinThing->validationErrors); $count = $Something->find('count', array('conditions' => array('Something.id' => $data['Something']['id']))); $this->assertSame(0, $count); $joinRecords = $JoinThing->find('count', array( 'conditions' => array('JoinThing.something_id' => $data['Something']['id']) )); $this->assertEquals(0, $joinRecords, 'Records were saved on the join table. %s'); } /** * test that saveAll and with models at initial insert (no id has set yet) * with validation interact well * * @return void */ public function testValidatesWithModelsAndSaveAllWithoutId() { $this->loadFixtures('Post', 'Author'); $data = array( 'Author' => array( 'name' => 'Foo Bar', ), 'Post' => array( array('title' => 'Hello'), array('title' => 'World'), ) ); $Author = new Author(); $Post = $Author->Post; $Post->validate = array('author_id' => array('rule' => 'numeric')); $Author->create(); $result = $Author->saveAll($data, array('validate' => 'only')); $this->assertTrue($result); $result = $Author->validateAssociated($data); $this->assertTrue($result); $this->assertTrue($result); $Author->create(); $result = $Author->saveAll($data, array('validate' => 'first')); $this->assertTrue($result); $this->assertNotNull($Author->id); $id = $Author->id; $count = $Author->find('count', array('conditions' => array('Author.id' => $id))); $this->assertSame(1, $count); $count = $Post->find('count', array( 'conditions' => array('Post.author_id' => $id) )); $this->assertEquals($count, count($data['Post'])); } /** * Test that missing validation methods trigger errors in development mode. * Helps to make development easier. * * @expectedException PHPUnit_Framework_Error * @return void */ public function testMissingValidationErrorTriggering() { Configure::write('debug', 2); $TestModel = new ValidationTest1(); $TestModel->create(array('title' => 'foo')); $TestModel->validate = array( 'title' => array( 'rule' => array('thisOneBringsThePain'), 'required' => true ) ); $TestModel->invalidFields(array('fieldList' => array('title'))); } /** * Test placeholder replacement when validation message is an array * * @return void */ public function testValidationMessageAsArray() { $TestModel = new ValidationTest1(); $TestModel->validate = array( 'title' => array( 'minLength' => array( 'rule' => array('minLength', 6), 'required' => true, 'message' => 'Minimum length allowed is %d chars', 'last' => false ), 'between' => array( 'rule' => array('lengthBetween', 5, 15), 'message' => array('You may enter up to %s chars (minimum is %s chars)', 14, 6) ) ) ); $TestModel->create(); $expected = array( 'title' => array( 'Minimum length allowed is 6 chars', ) ); $TestModel->invalidFields(); $this->assertEquals($expected, $TestModel->validationErrors); $TestModel->create(array('title' => 'foo')); $expected = array( 'title' => array( 'Minimum length allowed is 6 chars', 'You may enter up to 14 chars (minimum is 6 chars)' ) ); $TestModel->invalidFields(); $this->assertEquals($expected, $TestModel->validationErrors); } /** * Test validation message translation * * @return void */ public function testValidationMessageTranslation() { $lang = Configure::read('Config.language'); Configure::write('Config.language', 'en'); App::build(array( 'Locale' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Locale' . DS), ), App::RESET); $TestModel = new ValidationTest1(); $TestModel->validationDomain = 'validation_messages'; $TestModel->validate = array( 'title' => array( array( 'rule' => array('customValidationMethod', 'arg1'), 'required' => true, 'message' => 'Validation failed: %s' ) ) ); $TestModel->create(); $expected = array( 'title' => array( 'Translated validation failed: Translated arg1', ) ); $TestModel->invalidFields(); $this->assertEquals($expected, $TestModel->validationErrors); $TestModel->validationDomain = 'default'; Configure::write('Config.language', $lang); App::build(); } /** * Test for 'on' => [create|update] in validation rules. * * @return void */ public function testStateValidation() { $this->loadFixtures('Article'); $Article = new Article(); $data = array( 'Article' => array( 'title' => '', 'body' => 'Extra Fields Body', 'published' => '1' ) ); $Article->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'on' => 'create' ) ) ); $Article->create($data); $this->assertFalse($Article->validates()); $Article->save(null, array('validate' => false)); $data['Article']['id'] = $Article->id; $Article->set($data); $this->assertTrue($Article->validates()); unset($data['Article']['id']); $Article->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'on' => 'update' ) ) ); $Article->create($data); $this->assertTrue($Article->validates()); $Article->save(null, array('validate' => false)); $data['Article']['id'] = $Article->id; $Article->set($data); $this->assertFalse($Article->validates()); } /** * Test for 'required' => [create|update] in validation rules. * * @return void */ public function testStateRequiredValidation() { $this->loadFixtures('Article'); $Article = new Article(); // no title field present $data = array( 'Article' => array( 'body' => 'Extra Fields Body', 'published' => '1' ) ); $Article->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => 'create' ) ) ); $Article->create($data); $this->assertFalse($Article->validates()); $Article->save(null, array('validate' => false)); $data['Article']['id'] = $Article->id; $Article->set($data); $this->assertTrue($Article->validates()); unset($data['Article']['id']); $Article->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => 'update' ) ) ); $Article->create($data); $this->assertTrue($Article->validates()); $Article->save(null, array('validate' => false)); $data['Article']['id'] = $Article->id; $Article->set($data); $this->assertFalse($Article->validates()); } /** * Test that 'required' and 'on' are not conflicting * * @return void */ public function testOnRequiredConflictValidation() { $this->loadFixtures('Article'); $Article = new Article(); // no title field present $data = array( 'Article' => array( 'body' => 'Extra Fields Body', 'published' => '1' ) ); $Article->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => 'create', 'on' => 'create' ) ) ); $Article->create($data); $this->assertFalse($Article->validates()); $Article->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => 'update', 'on' => 'create' ) ) ); $Article->create($data); $this->assertTrue($Article->validates()); $Article->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => 'create', 'on' => 'update' ) ) ); $Article->create($data); $this->assertTrue($Article->validates()); $Article->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => 'update', 'on' => 'update' ) ) ); $Article->create($data); $this->assertTrue($Article->validates()); $Article->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => 'create', 'on' => 'create' ) ) ); $Article->save(null, array('validate' => false)); $data['Article']['id'] = $Article->id; $Article->set($data); $this->assertTrue($Article->validates()); $Article->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => 'update', 'on' => 'create' ) ) ); $Article->set($data); $this->assertTrue($Article->validates()); $Article->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => 'create', 'on' => 'update' ) ) ); $Article->set($data); $this->assertTrue($Article->validates()); $Article->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => 'update', 'on' => 'update' ) ) ); $Article->set($data); $this->assertFalse($Article->validates()); } /** * 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'] = 'notBlank'; $TestModel->Comment->validate['comment'] = 'notBlank'; $data = 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) ) ); $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true)); $this->assertTrue($result); $result = $TestModel->validateAssociated($data, array('deep' => true)); $this->assertTrue($result); $data = 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) ) ); $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true)); $this->assertFalse($result); $result = $TestModel->validateAssociated($data, array('deep' => true)); $this->assertFalse($result); $data = 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) ) ); $expected = array( 'Article' => true, 'Comment' => array( true, true ) ); $result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true)); $this->assertSame($expected, $result); $result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true)); $this->assertSame($expected, $result); $data = 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) ) ); $expected = array( 'Article' => true, 'Comment' => array( false, true ) ); $result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true)); $this->assertSame($expected, $result); $result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true)); $this->assertSame($expected, $result); $data = 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')) ) ); $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true)); $this->assertTrue($result); $result = $TestModel->validateAssociated($data, array('deep' => true)); $this->assertTrue($result); $data = 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' => '')) ) ); $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => true)); $this->assertFalse($result); $result = $TestModel->validateAssociated($data, array('deep' => true)); $this->assertFalse($result); $data = 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')) ) ); $expected = array( 'Article' => true, 'Comment' => array( true, true ) ); $result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true)); $this->assertSame($expected, $result); $result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true)); $this->assertSame($expected, $result); $data = 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' => '')) ) ); $expected = array( 'Article' => true, 'Comment' => array( true, false ) ); $result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true)); $this->assertSame($expected, $result); $result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => true)); $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->validateAssociated($data, array('deep' => true)); $this->assertTrue($result); $expected = array( 'Attachment' => true, 'Comment' => true ); $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true)); $this->assertSame($expected, $result); $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => 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->validateAssociated($data, array('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); $expected = array( 'Attachment' => true, 'Comment' => false ); $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true)); $this->assertEquals($expected, $result); $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true)); $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->validateAssociated($data, array('deep' => true)); $this->assertFalse($result); $result = $TestModel->Comment->Attachment->validationErrors; $expected = array( 'Comment' => array( 'Article' => array( 'body' => array('This field cannot be left blank'), 'User' => array( 'user' => array('This field cannot be left blank') ) ) ) ); $this->assertSame($expected, $result); $expected = array( 'Attachment' => true, 'Comment' => false ); $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true)); $this->assertEquals($expected, $result); $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true)); $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->validateAssociated($data, array('deep' => true)); $this->assertFalse($result); $result = $TestModel->Comment->Attachment->validationErrors; $expected = array( 'Comment' => array( 'comment' => array('This field cannot be left blank'), 'Article' => array( 'body' => array('This field cannot be left blank'), 'User' => array( 'user' => array('This field cannot be left blank') ) ) ) ); $this->assertSame($expected, $result); $expected = array( 'Attachment' => true, 'Comment' => false ); $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true)); $this->assertEquals($expected, $result); $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true)); $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->validateAssociated($data, array('deep' => true)); $this->assertFalse($result); $result = $TestModel->Comment->Attachment->validationErrors; $expected = array( 'attachment' => array('This field cannot be left blank'), 'Comment' => array( 'comment' => array('This field cannot be left blank'), 'Article' => array( 'body' => array('This field cannot be left blank'), 'User' => array( 'user' => 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'), 'Article' => array( 'body' => array('This field cannot be left blank'), 'User' => array( 'user' => array('This field cannot be left blank') ) ) ); $this->assertSame($expected, $result); $expected = array( 'Attachment' => false, 'Comment' => false ); $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => true)); $this->assertEquals($expected, $result); $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true)); $this->assertEquals($expected, $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'] = 'notBlank'; $TestModel->Comment->validate['comment'] = 'notBlank'; $data = 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) ) ); $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => false)); $this->assertFalse($result); $result = $TestModel->validateAssociated($data, array('deep' => false)); $this->assertFalse($result); $expected = array('body' => array('This field cannot be left blank')); $result = $TestModel->validationErrors; $this->assertSame($expected, $result); $data = 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) ) ); $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => false)); $this->assertTrue($result); $result = $TestModel->validateAssociated($data, array('deep' => false)); $this->assertTrue($result); $data = 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) ) ); $expected = array( 'Article' => true, 'Comment' => array( true, true ) ); $result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false)); $this->assertSame($expected, $result); $result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => false)); $this->assertSame($expected, $result); $data = 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' => '')) ) ); $result = $TestModel->saveAll($data, array('validate' => 'only', 'deep' => false)); $this->assertTrue($result); $result = $TestModel->validateAssociated($data, array('deep' => false)); $this->assertTrue($result); $data = 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' => '')) ) ); $expected = array( 'Article' => true, 'Comment' => array( true, true ) ); $result = $TestModel->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false)); $this->assertSame($expected, $result); $result = $TestModel->validateAssociated($data, array('atomic' => false, 'deep' => false)); $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->validateAssociated($data, array('deep' => false)); $this->assertTrue($result); $result = $TestModel->Comment->Attachment->validationErrors; $expected = array(); $this->assertSame($expected, $result); $expected = array( 'Attachment' => true, 'Comment' => true ); $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false)); $this->assertEquals($expected, $result); $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => false)); $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->validateAssociated($data, array('deep' => false)); $this->assertTrue($result); $result = $TestModel->Comment->Attachment->validationErrors; $expected = array(); $this->assertSame($expected, $result); $expected = array( 'Attachment' => true, 'Comment' => true ); $result = $TestModel->Comment->Attachment->saveAll($data, array('validate' => 'only', 'atomic' => false, 'deep' => false)); $this->assertEquals($expected, $result); $result = $TestModel->Comment->Attachment->validateAssociated($data, array('atomic' => false, 'deep' => false)); $this->assertEquals($expected, $result); } /** * testValidateAssociated method * * @return void */ public function testValidateAssociated() { $this->loadFixtures('Comment', 'Attachment', 'Article', 'User'); $TestModel = new Comment(); $TestModel->Attachment->validate = array('attachment' => 'notBlank'); $data = array( 'Comment' => array( 'comment' => 'This is the comment' ), 'Attachment' => array( 'attachment' => '' ) ); $result = $TestModel->saveAll($data, array('validate' => 'only')); $this->assertFalse($result); $result = $TestModel->validateAssociated($data); $this->assertFalse($result); $fieldList = array( 'Attachment' => array('comment_id') ); $result = $TestModel->saveAll($data, array( 'fieldList' => $fieldList, 'validate' => 'only' )); $this->assertTrue($result); $this->assertEmpty($TestModel->validationErrors); $result = $TestModel->validateAssociated($data, array('fieldList' => $fieldList)); $this->assertTrue($result); $this->assertEmpty($TestModel->validationErrors); $TestModel->validate = array('comment' => 'notBlank'); $record = array( 'Comment' => array( 'user_id' => 1, 'article_id' => 1, 'comment' => '', ), 'Attachment' => array( 'attachment' => '' ) ); $result = $TestModel->saveAll($record, array('validate' => 'only')); $this->assertFalse($result); $result = $TestModel->validateAssociated($record); $this->assertFalse($result); $fieldList = array( 'Comment' => array('id', 'article_id', 'user_id'), 'Attachment' => array('comment_id') ); $result = $TestModel->saveAll($record, array( 'fieldList' => $fieldList, 'validate' => 'only' )); $this->assertTrue($result); $this->assertEmpty($TestModel->validationErrors); $result = $TestModel->validateAssociated($record, array('fieldList' => $fieldList)); $this->assertTrue($result); $this->assertEmpty($TestModel->validationErrors); $TestModel = new Article(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array(); $TestModel->Comment->validate = array('comment' => 'notBlank'); $data = array( 'Article' => array('id' => 2), 'Comment' => array( array( 'id' => 1, 'comment' => '', 'published' => 'Y', 'user_id' => 1, ), array( 'id' => 2, 'comment' => 'comment', 'published' => 'Y', 'user_id' => 1 ), array( 'id' => 3, 'comment' => '', 'published' => 'Y', 'user_id' => 1 ))); $result = $TestModel->saveAll($data, array('validate' => 'only')); $this->assertFalse($result); $result = $TestModel->validateAssociated($data); $this->assertFalse($result); $expected = array( 'Article' => true, 'Comment' => array(false, true, false) ); $result = $TestModel->saveAll($data, array('atomic' => false, 'validate' => 'only')); $this->assertSame($expected, $result); $result = $TestModel->validateAssociated($data, array('atomic' => false)); $this->assertSame($expected, $result); $expected = array('Comment' => array( 0 => array('comment' => array('This field cannot be left blank')), 2 => array('comment' => array('This field cannot be left blank')) )); $this->assertEquals($expected['Comment'], $TestModel->Comment->validationErrors); $model = new Comment(); $model->deleteAll(true); $model->validate = array('comment' => 'notBlank'); $model->Attachment->validate = array('attachment' => 'notBlank'); $model->Attachment->bindModel(array('belongsTo' => array('Comment'))); $expected = array( 'comment' => array('This field cannot be left blank'), 'Attachment' => array( 'attachment' => array('This field cannot be left blank') ) ); $data = array( 'Comment' => array('comment' => '', 'article_id' => 1, 'user_id' => 1), 'Attachment' => array('attachment' => '') ); $result = $model->saveAll($data, array('validate' => 'only')); $this->assertFalse($result); $result = $model->validateAssociated($data); $this->assertFalse($result); $this->assertEquals($expected, $model->validationErrors); $this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors); } /** * testValidateMany method * * @return void */ public function testValidateMany() { $TestModel = new Article(); $TestModel->validate = array('title' => 'notBlank'); $data = array( 0 => array('title' => ''), 1 => array('title' => 'title 1'), 2 => array('title' => 'title 2'), ); $expected = array( 0 => array('title' => array('This field cannot be left blank')), ); $result = $TestModel->saveAll($data, array('validate' => 'only')); $this->assertFalse($result); $this->assertEquals($expected, $TestModel->validationErrors); $result = $TestModel->validateMany($data); $this->assertFalse($result); $this->assertEquals($expected, $TestModel->validationErrors); $data = array( 0 => array('title' => 'title 0'), 1 => array('title' => ''), 2 => array('title' => 'title 2'), ); $expected = array( 1 => array('title' => array('This field cannot be left blank')), ); $result = $TestModel->saveAll($data, array('validate' => 'only')); $this->assertFalse($result); $this->assertEquals($expected, $TestModel->validationErrors); $result = $TestModel->validateMany($data); $this->assertFalse($result); $this->assertEquals($expected, $TestModel->validationErrors); } /** * testGetMethods method * * @return void */ public function testGetMethods() { $this->loadFixtures('Article', 'Comment'); $TestModel = new Article(); $Validator = $TestModel->validator(); $result = $Validator->getMethods(); $expected = array_map('strtolower', get_class_methods('Article')); $this->assertEquals($expected, array_keys($result)); } /** * Tests that methods are refreshed when the list of behaviors change * * @return void */ public function testGetMethodsRefresh() { $this->loadFixtures('Article', 'Comment'); $TestModel = new Article(); $Validator = $TestModel->validator(); $result = $Validator->getMethods(); $expected = array_map('strtolower', get_class_methods('Article')); $this->assertEquals($expected, array_keys($result)); $TestModel->Behaviors->load('Containable'); $newList = array( 'contain', 'resetbindings', 'containments', 'fielddependencies', 'containmentsmap' ); $this->assertEquals(array_merge($expected, $newList), array_keys($Validator->getMethods())); $TestModel->Behaviors->unload('Containable'); $this->assertEquals($expected, array_keys($Validator->getMethods())); } /** * testSetValidationDomain method * * @return void */ public function testSetValidationDomain() { $this->loadFixtures('Article', 'Comment'); $TestModel = new Article(); $Validator = $TestModel->validator(); $result = $Validator->setValidationDomain('default'); $this->assertEquals('default', $TestModel->validationDomain); $result = $Validator->setValidationDomain('other'); $this->assertEquals('other', $TestModel->validationDomain); } /** * testGetModel method * * @return void */ public function testGetModel() { $TestModel = new Article(); $Validator = $TestModel->validator(); $result = $Validator->getModel(); $this->assertInstanceOf('Article', $result); } /** * Tests it is possible to get validation sets for a field using an array inteface * * @return void */ public function testArrayAccessGet() { $TestModel = new Article(); $Validator = $TestModel->validator(); $titleValidator = $Validator['title']; $this->assertEquals('title', $titleValidator->field); $this->assertCount(1, $titleValidator->getRules()); $rule = current($titleValidator->getRules()); $this->assertEquals('notBlank', $rule->rule); $titleValidator = $Validator['body']; $this->assertEquals('body', $titleValidator->field); $this->assertCount(1, $titleValidator->getRules()); $rule = current($titleValidator->getRules()); $this->assertEquals('notBlank', $rule->rule); $titleValidator = $Validator['user_id']; $this->assertEquals('user_id', $titleValidator->field); $this->assertCount(1, $titleValidator->getRules()); $rule = current($titleValidator->getRules()); $this->assertEquals('numeric', $rule->rule); } /** * Tests it is possible to check for validation sets for a field using an array inteface * * @return void */ public function testArrayAccessExists() { $TestModel = new Article(); $Validator = $TestModel->validator(); $this->assertTrue(isset($Validator['title'])); $this->assertTrue(isset($Validator['body'])); $this->assertTrue(isset($Validator['user_id'])); $this->assertFalse(isset($Validator['other'])); } /** * Tests it is possible to set validation rules for a field using an array inteface * * @return void */ public function testArrayAccessSet() { $TestModel = new Article(); $Validator = $TestModel->validator(); $set = array( 'numeric' => array('rule' => 'numeric', 'allowEmpty' => false), 'between' => array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false), ); $Validator['other'] = $set; $rules = $Validator['other']; $this->assertEquals('other', $rules->field); $validators = $rules->getRules(); $this->assertCount(2, $validators); $this->assertEquals('numeric', $validators['numeric']->rule); $this->assertEquals(array('lengthBetween', 1, 5), $validators['between']->rule); $Validator['new'] = new CakeValidationSet('new', $set, array()); $rules = $Validator['new']; $this->assertEquals('new', $rules->field); $validators = $rules->getRules(); $this->assertCount(2, $validators); $this->assertEquals('numeric', $validators['numeric']->rule); $this->assertEquals(array('lengthBetween', 1, 5), $validators['between']->rule); } /** * Tests it is possible to unset validation rules * * @return void */ public function testArrayAccessUset() { $TestModel = new Article(); $Validator = $TestModel->validator(); $this->assertTrue(isset($Validator['title'])); unset($Validator['title']); $this->assertFalse(isset($Validator['title'])); } /** * Tests it is possible to iterate a validation object * * @return void */ public function testIterator() { $TestModel = new Article(); $Validator = $TestModel->validator(); $i = 0; foreach ($Validator as $field => $rules) { if ($i === 0) { $this->assertEquals('user_id', $field); } if ($i === 1) { $this->assertEquals('title', $field); } if ($i === 2) { $this->assertEquals('body', $field); } $this->assertInstanceOf('CakeValidationSet', $rules); $i++; } $this->assertEquals(3, $i); } /** * Tests countable interface in ModelValidator * * @return void */ public function testCount() { $TestModel = new Article(); $Validator = $TestModel->validator(); $this->assertCount(3, $Validator); $set = array( 'numeric' => array('rule' => 'numeric', 'allowEmpty' => false), 'range' => array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false), ); $Validator['other'] = $set; $this->assertCount(4, $Validator); unset($Validator['title']); $this->assertCount(3, $Validator); unset($Validator['body']); $this->assertCount(2, $Validator); } /** * Tests it is possible to add validation rules * * @return void */ public function testAddRule() { $TestModel = new Article(); $Validator = $TestModel->validator(); $Validator->add('other', 'numeric', array('rule' => 'numeric', 'allowEmpty' => false)); $Validator->add('other', 'between', array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false)); $rules = $Validator['other']; $this->assertEquals('other', $rules->field); $validators = $rules->getRules(); $this->assertCount(2, $validators); $this->assertEquals('numeric', $validators['numeric']->rule); $this->assertEquals(array('lengthBetween', 1, 5), $validators['between']->rule); } /** * Tests it is possible to remove validation rules * * @return void */ public function testRemoveRule() { $TestModel = new Article(); $Validator = $TestModel->validator(); $this->assertTrue(isset($Validator['title'])); $Validator->remove('title'); $this->assertFalse(isset($Validator['title'])); $Validator->add('other', 'numeric', array('rule' => 'numeric', 'allowEmpty' => false)); $Validator->add('other', 'between', array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false)); $this->assertTrue(isset($Validator['other'])); $Validator->remove('other', 'numeric'); $this->assertTrue(isset($Validator['other'])); $this->assertFalse(isset($Validator['other']['numeric'])); $this->assertTrue(isset($Validator['other']['between'])); } /** * Tests validation callbacks are triggered * * @return void */ public function testValidateCallbacks() { $TestModel = $this->getMock('Article', array('beforeValidate', 'afterValidate')); $TestModel->expects($this->once())->method('beforeValidate'); $TestModel->expects($this->once())->method('afterValidate'); $TestModel->set(array('title' => '', 'body' => 'body')); $TestModel->validates(); } /** * Tests that altering data in a beforeValidate callback will lead to saving those * values in database * * @return void */ public function testValidateFirstWithBeforeValidate() { $this->loadFixtures('Article', 'User'); $model = new CustomArticle(); $model->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => true, 'allowEmpty' => false ) ) ); $data = array( 'CustomArticle' => array( 'body' => 'foo0' ) ); $result = $model->saveAll($data, array('validate' => 'first')); $this->assertTrue($result); $this->assertFalse($model->findMethods['unPublished'], 'beforeValidate was run twice'); $model->findMethods['unPublished'] = true; $data = array( 'CustomArticle' => array( 'body' => 'foo1' ) ); $result = $model->saveAll($data, array('validate' => 'first', 'deep' => true)); $this->assertTrue($result); $title = $model->field('title', array('body' => 'foo1')); $this->assertEquals('foo', $title); $this->assertFalse($model->findMethods['unPublished'], 'beforeValidate was run twice'); $data = array( array('body' => 'foo2'), array('body' => 'foo3'), array('body' => 'foo4') ); $result = $model->saveAll($data, array('validate' => 'first', 'deep' => true)); $this->assertTrue($result); $this->assertEquals('foo', $model->field('title', array('body' => 'foo2'))); $this->assertEquals('foo', $model->field('title', array('body' => 'foo3'))); $this->assertEquals('foo', $model->field('title', array('body' => 'foo4'))); } /** * Tests that altering data in a beforeValidate callback will lead to saving those * values in database * * @return void */ public function testValidateFirstAssociatedWithBeforeValidate() { $this->loadFixtures('Article', 'User'); $model = new CustomArticle(); $model->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => true ) ) ); $articles = array( array('body' => 'foo1'), array('body' => 'foo2'), array('body' => 'foo3') ); $user = new User(); $user->bindModel(array('hasMany' => array('CustomArticle'))); $data = array( 'User' => array('user' => 'foo', 'password' => 'bar'), 'CustomArticle' => $articles ); $result = $user->saveAll($data, array('validate' => 'first')); $this->assertTrue($result); $this->assertEquals('foo', $model->field('title', array('body' => 'foo1'))); $this->assertEquals('foo', $model->field('title', array('body' => 'foo2'))); $this->assertEquals('foo', $model->field('title', array('body' => 'foo3'))); } /** * testValidateFirstWithDefaults method * * @return void */ public function testFirstWithDefaults() { $this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag'); $TestModel = new Article(); $result = $TestModel->find('first', array( 'conditions' => array('Article.id' => 1) )); $expected = array( 'Article' => array( 'id' => 1, 'user_id' => 1, 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23' ), ); unset($result['Article']['updated']); $this->assertEquals($expected['Article'], $result['Article']); $data = array( 'Article' => array( 'id' => 1, 'title' => 'First Article (modified)' ), 'Comment' => array( array('comment' => 'Article comment', 'user_id' => 1) ) ); $result = $TestModel->saveAll($data, array('validate' => 'first')); $this->assertTrue($result); $result = $TestModel->find('first', array( 'conditions' => array('Article.id' => 1) )); $expected['Article']['title'] = 'First Article (modified)'; unset($result['Article']['updated']); $this->assertEquals($expected['Article'], $result['Article']); } public function testAddMultipleRules() { $TestModel = new Article(); $Validator = $TestModel->validator(); $set = array( 'numeric' => array('rule' => 'numeric', 'allowEmpty' => false), 'between' => array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false), ); $Validator->add('other', $set); $rules = $Validator['other']; $this->assertEquals('other', $rules->field); $validators = $rules->getRules(); $this->assertCount(2, $validators); $this->assertEquals('numeric', $validators['numeric']->rule); $this->assertEquals(array('lengthBetween', 1, 5), $validators['between']->rule); $set = new CakeValidationSet('other', array( 'a' => array('rule' => 'numeric', 'allowEmpty' => false), 'b' => array('rule' => array('lengthBetween', 1, 5), 'allowEmpty' => false), )); $Validator->add('other', $set); $this->assertSame($set, $Validator->getField('other')); } /** * Test that rules are parsed correctly when calling getField() * * @return void */ public function testValidator() { $TestModel = new Article(); $Validator = $TestModel->validator(); $result = $Validator->getField(); $expected = array('user_id', 'title', 'body'); $this->assertEquals($expected, array_keys($result)); $this->assertTrue($result['user_id'] instanceof CakeValidationSet); $result = $TestModel->validator()->getField('title'); $this->assertTrue($result instanceof CakeValidationSet); } /** * Test that validator override works as expected * * @return void */ public function testValidatorOverride() { $TestModel = new Article(); $ValidatorA = new ModelValidator($TestModel); $ValidatorB = new ModelValidator($TestModel); $TestModel->validator($ValidatorA); $TestModel->validator($ValidatorB); $this->assertSame($ValidatorB, $TestModel->validator()); $this->assertNotSame($ValidatorA, $TestModel->validator()); } /** * Test that type hint exception is thrown * * @expectedException PHPUnit_Framework_Error * @throws PHPUnit_Framework_Error * @return void */ public function testValidatorTypehintException() { try { new ModelValidator('asdasds'); } catch (Throwable $t) { throw new PHPUnit_Framework_Error($t); } } /** * Tests that altering data in a beforeValidate callback will lead to saving those * values in database, this time with belongsTo associations * * @return void */ public function testValidateFirstAssociatedWithBeforeValidate2() { $this->loadFixtures('Article', 'User'); $model = new CustomArticle(); $model->validate = array( 'title' => array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => true ) ) ); $data = array( 'User' => array('user' => 'foo', 'password' => 'bar'), 'CustomArticle' => array( 'body' => 'a test' ) ); $result = $model->saveAll($data, array('validate' => 'first')); $this->assertTrue($result); $this->assertEquals('foo', $model->field('title', array('body' => 'a test'))); } /** * Testing you can dynamically add rules to a field, added this to dispel doubts * after a presentation made to show off this new feature * * @return void */ public function testDynamicValidationRuleBuilding() { $model = new Article; $validator = $model->validator(); $validator->add('body', 'isSpecial', array('rule' => 'special')); $rules = $validator['body']->getRules(); $this->assertCount(2, $rules); $this->assertEquals('special', $rules['isSpecial']->rule); $validator['body']->setRule('isAwesome', array('rule' => 'awesome')); $rules = $validator['body']->getRules(); $this->assertCount(3, $rules); $this->assertEquals('awesome', $rules['isAwesome']->rule); } /** * Test to ensure custom validation methods work with CakeValidationSet * * @return void */ public function testCustomMethodsWithCakeValidationSet() { $TestModel = new TestValidate(); $Validator = $TestModel->validator(); $Validator->add('title', 'validateTitle', array( 'rule' => 'validateTitle', 'message' => 'That aint right', )); $data = array('title' => 'notatitle'); $result = $Validator->getField('title')->validate($data); $expected = array(0 => 'That aint right'); $this->assertEquals($expected, $result); $data = array('title' => 'title-is-good'); $result = $Validator->getField('title')->validate($data); $expected = array(); $this->assertEquals($expected, $result); } public function testCustomMethodWithEmptyValue() { $this->loadFixtures('Article'); $model = $this->getMock('Article', array('isLegit')); $model->validate = array( 'title' => array( 'custom' => array( 'rule' => array('isLegit'), 'message' => 'is no good' ) ) ); $model->expects($this->once()) ->method('isLegit') ->will($this->returnValue(false)); $model->set(array('title' => '')); $this->assertFalse($model->validates()); } /** * Test validateAssociated with atomic=false & deep=true * * @return void */ public function testValidateAssociatedAtomicFalseDeepTrueWithErrors() { $this->loadFixtures('Comment', 'Article', 'User', 'Attachment'); $Attachment = ClassRegistry::init('Attachment'); $Attachment->Comment->validator()->add('comment', array( array('rule' => 'notBlank') )); $Attachment->Comment->User->bindModel(array( 'hasMany' => array( 'Article', 'Comment' )), false ); $data = array( 'Attachment' => array( 'attachment' => 'text', 'Comment' => array( 'comment' => '', 'published' => 'N', 'User' => array( 'user' => 'Foo', 'password' => 'mypassword', 'Comment' => array( array( 'comment' => '' ) ) ) ) ) ); $result = $Attachment->validateAssociated($data, array('atomic' => false, 'deep' => true)); $result = $Attachment->validationErrors; $expected = array( 'Comment' => array( 'comment' => array( 0 => 'This field cannot be left blank', ), 'User' => array( 'Comment' => array( 0 => array( 'comment' => array( 0 => 'This field cannot be left blank', ), ), ), ), ), ); $this->assertEquals($expected, $result); } /** * Test validateMany with atomic=false & deep=true * * @return void */ public function testValidateManyAtomicFalseDeepTrueWithErrors() { $this->loadFixtures('Comment', 'Article', 'User'); $Article = ClassRegistry::init('Article'); $Article->Comment->validator()->add('comment', array( array('rule' => 'notBlank') )); $data = array( array( 'Article' => array( 'user_id' => 1, 'title' => 'Foo', 'body' => 'text', 'published' => 'N' ), 'Comment' => array( array( 'user_id' => 1, 'comment' => 'Baz', 'published' => 'N', ) ), ), array( 'Article' => array( 'user_id' => 1, 'title' => 'Bar', 'body' => 'text', 'published' => 'N' ), 'Comment' => array( array( 'user_id' => 1, 'comment' => '', 'published' => 'N', ) ), ), ); $Article->validateMany($data, array('atomic' => false, 'deep' => true)); $result = $Article->validationErrors; $expected = array( 1 => array( 'Comment' => array( 0 => array( 'comment' => array( 0 => 'This field cannot be left blank', ), ), ), ), ); $this->assertEquals($expected, $result); } /** * Test the isUnique method when used as a validator for multiple fields. * * @return void */ public function testIsUniqueValidator() { $this->loadFixtures('Article'); $Article = ClassRegistry::init('Article'); $Article->validate = array( 'user_id' => array( 'duplicate' => array( 'rule' => array('isUnique', array('user_id', 'title'), false) ) ) ); $data = array( 'user_id' => 1, 'title' => 'First Article', ); $Article->create($data); $this->assertFalse($Article->validates(), 'Contains a dupe'); $data = array( 'user_id' => 1, 'title' => 'Unique Article', ); $Article->create($data); $this->assertTrue($Article->validates(), 'Should pass'); $Article->validate = array( 'user_id' => array( 'duplicate' => array( 'rule' => array('isUnique', array('user_id', 'title')) ) ) ); $data = array( 'user_id' => 1, 'title' => 'Unique Article', ); $Article->create($data); $this->assertFalse($Article->validates(), 'Should fail, conditions are combined with or'); } /** * Test backward compatibility of the isUnique method when used as a validator for a single field. * * @return void */ public function testBackwardCompatIsUniqueValidator() { $this->loadFixtures('Article'); $Article = ClassRegistry::init('Article'); $Article->validate = array( 'title' => array( 'duplicate' => array( 'rule' => 'isUnique', 'message' => 'Title must be unique', ), 'minLength' => array( 'rule' => array('minLength', 1), 'message' => 'Title cannot be empty', ), ) ); $data = array( 'title' => 'First Article', ); $data = $Article->create($data); $this->assertFalse($Article->validates(), 'Contains a dupe'); } } /** * Behavior for testing validation rules. */ class ValidationRuleBehavior extends ModelBehavior { public function setup(Model $Model, $config = array()) { $this->settings[$Model->alias] = $config; } public function beforeValidate(Model $Model, $options = array()) { $fields = $this->settings[$Model->alias]['fields']; foreach ($fields as $field) { $Model->whitelist[] = $field; } } } cakephp-2.8.0/lib/Cake/Test/Case/Model/ModelWriteTest.php000066400000000000000000006754701265552240500230540ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('MockTransactionDboSource', 'Model/Datasource'); App::uses('MockTransactionAssociatedDboSource', 'Model/Datasource'); App::uses('MockManyTransactionDboSource', 'Model/Datasource'); App::uses('MockAssociatedTransactionDboSource', 'Model/Datasource'); require_once dirname(__FILE__) . DS . 'ModelTestBase.php'; /** * Helper class for testing with mocked datasources */ class TestAuthor extends Author { public $hasMany = array( 'Post' => array( 'className' => 'TestPost' ) ); protected $_dataSourceObject; public $dataForAfterSave; /** * Helper method to set a datasource object * * @param Object $object The datasource object * @return void */ public function setDataSourceObject($object) { $this->_dataSourceObject = $object; } /** * Overwritten in order to return the directly set datasource object if * available * * @return DataSource */ public function getDataSource() { if ($this->_dataSourceObject !== null) { return $this->_dataSourceObject; } return parent::getDataSource(); } } /** * Helper class for testing with mocked datasources */ class TestPost extends Post { public $belongsTo = array( 'Author' => array( 'className' => 'TestAuthor' ) ); protected $_dataSourceObject; public $dataForAfterSave; /** * Helper method to set a datasource object * * @param Object $object The datasource object * @return void */ public function setDataSourceObject($object) { $this->_dataSourceObject = $object; } /** * Overwritten in order to return the directly set datasource object if * available * * @return DataSource */ public function getDataSource() { if ($this->_dataSourceObject !== null) { return $this->_dataSourceObject; } return parent::getDataSource(); } } /** * ModelWriteTest * * @package Cake.Test.Case.Model */ class ModelWriteTest extends BaseModelTest { /** * override locale to the default (eng). * * @return void */ public function setUp() { parent::setUp(); Configure::write('Config.language', 'eng'); } /** * Test save() failing when there is no data. * * @return void */ public function testInsertNoData() { $this->loadFixtures('Bid'); $Bid = ClassRegistry::init('Bid'); $this->assertFalse($Bid->save()); $result = $Bid->save(array('Bid' => array())); $this->assertFalse($result); $result = $Bid->save(array('Bid' => array('not in schema' => 1))); $this->assertFalse($result); } /** * testInsertAnotherHabtmRecordWithSameForeignKey method * * @return void */ public function testInsertAnotherHabtmRecordWithSameForeignKey() { $this->loadFixtures('JoinA', 'JoinB', 'JoinAB', 'JoinC', 'JoinAC'); $TestModel = new JoinA(); $result = $TestModel->JoinAsJoinB->findById(1); $expected = array( 'JoinAsJoinB' => array( 'id' => 1, 'join_a_id' => 1, 'join_b_id' => 2, 'other' => 'Data for Join A 1 Join B 2', 'created' => '2008-01-03 10:56:33', 'updated' => '2008-01-03 10:56:33' )); $this->assertEquals($expected, $result); $TestModel->JoinAsJoinB->create(); $data = array( 'join_a_id' => 1, 'join_b_id' => 1, 'other' => 'Data for Join A 1 Join B 1', 'created' => '2008-01-03 10:56:44', 'updated' => '2008-01-03 10:56:44' ); $result = $TestModel->JoinAsJoinB->save($data); $lastInsertId = $TestModel->JoinAsJoinB->getLastInsertID(); $data['id'] = $lastInsertId; $this->assertEquals(array('JoinAsJoinB' => $data), $result); $this->assertTrue($lastInsertId > 0); $result = $TestModel->JoinAsJoinB->findById(1); $expected = array( 'JoinAsJoinB' => array( 'id' => 1, 'join_a_id' => 1, 'join_b_id' => 2, 'other' => 'Data for Join A 1 Join B 2', 'created' => '2008-01-03 10:56:33', 'updated' => '2008-01-03 10:56:33' )); $this->assertEquals($expected, $result); $updatedValue = 'UPDATED Data for Join A 1 Join B 2'; $TestModel->JoinAsJoinB->id = 1; $result = $TestModel->JoinAsJoinB->saveField('other', $updatedValue, false); $this->assertFalse(empty($result)); $result = $TestModel->JoinAsJoinB->findById(1); $this->assertEquals($updatedValue, $result['JoinAsJoinB']['other']); } /** * testSaveDateAsFirstEntry method * * @return void */ public function testSaveDateAsFirstEntry() { $this->loadFixtures('Article', 'User', 'Comment', 'Attachment', 'Tag', 'ArticlesTag'); $Article = new Article(); $data = array( 'Article' => array( 'created' => array( 'day' => '1', 'month' => '1', 'year' => '2008' ), 'title' => 'Test Title', 'user_id' => 1 )); $Article->create(); $result = $Article->save($data); $this->assertFalse(empty($result)); $testResult = $Article->find('first', array('conditions' => array('Article.title' => 'Test Title'))); $this->assertEquals($data['Article']['title'], $testResult['Article']['title']); $this->assertEquals('2008-01-01 00:00:00', $testResult['Article']['created']); } /** * testUnderscoreFieldSave method * * @return void */ public function testUnderscoreFieldSave() { $this->loadFixtures('UnderscoreField'); $UnderscoreField = new UnderscoreField(); $currentCount = $UnderscoreField->find('count'); $this->assertEquals(3, $currentCount); $data = array('UnderscoreField' => array( 'user_id' => '1', 'my_model_has_a_field' => 'Content here', 'body' => 'Body', 'published' => 'Y', 'another_field' => 4 )); $ret = $UnderscoreField->save($data); $this->assertFalse(empty($ret)); $currentCount = $UnderscoreField->find('count'); $this->assertEquals(4, $currentCount); } /** * testAutoSaveUuid method * * @return void */ public function testAutoSaveUuid() { // SQLite does not support non-integer primary keys $this->skipIf($this->db instanceof Sqlite, 'This test is not compatible with SQLite.'); $this->loadFixtures('Uuid'); $TestModel = new Uuid(); $TestModel->save(array('title' => 'Test record')); $result = $TestModel->findByTitle('Test record'); $this->assertEquals( array('id', 'title', 'count', 'created', 'updated'), array_keys($result['Uuid']) ); $this->assertEquals(36, strlen($result['Uuid']['id'])); } /** * Ensure that if the id key is null but present the save doesn't fail (with an * x sql error: "Column id specified twice") * * @return void */ public function testSaveUuidNull() { // SQLite does not support non-integer primary keys $this->skipIf($this->db instanceof Sqlite, 'This test is not compatible with SQLite.'); $this->loadFixtures('Uuid'); $TestModel = new Uuid(); $TestModel->save(array('title' => 'Test record', 'id' => null)); $result = $TestModel->findByTitle('Test record'); $this->assertEquals( array('id', 'title', 'count', 'created', 'updated'), array_keys($result['Uuid']) ); $this->assertEquals(36, strlen($result['Uuid']['id'])); } /** * testZeroDefaultFieldValue method * * @return void */ public function testZeroDefaultFieldValue() { $this->skipIf($this->db instanceof Sqlite, 'SQLite uses loose typing, this operation is unsupported.'); $this->loadFixtures('DataTest'); $TestModel = new DataTest(); $TestModel->create(array()); $TestModel->save(); $result = $TestModel->findById($TestModel->id); $this->assertEquals(0, $result['DataTest']['count']); $this->assertEquals(0, $result['DataTest']['float']); } /** * Tests validation parameter order in custom validation methods * * @return void */ public function testAllowSimulatedFields() { $TestModel = new ValidationTest1(); $TestModel->create(array( 'title' => 'foo', 'bar' => 'baz' )); $expected = array( 'ValidationTest1' => array( 'title' => 'foo', 'bar' => 'baz' )); $this->assertEquals($expected, $TestModel->data); } /** * test that Caches are getting cleared on save(). * ensure that both inflections of controller names are getting cleared * as URL for controller could be either overallFavorites/index or overall_favorites/index * * @return void */ public function testCacheClearOnSave() { $_back = array( 'check' => Configure::read('Cache.check'), 'disable' => Configure::read('Cache.disable'), ); Configure::write('Cache.check', true); Configure::write('Cache.disable', false); $this->loadFixtures('OverallFavorite'); $OverallFavorite = new OverallFavorite(); touch(CACHE . 'views' . DS . 'some_dir_overallfavorites_index.php'); touch(CACHE . 'views' . DS . 'some_dir_overall_favorites_index.php'); $data = array( 'OverallFavorite' => array( 'id' => 22, 'model_type' => '8-track', 'model_id' => '3', 'priority' => '1' ) ); $OverallFavorite->create($data); $OverallFavorite->save(); $this->assertFalse(file_exists(CACHE . 'views' . DS . 'some_dir_overallfavorites_index.php')); $this->assertFalse(file_exists(CACHE . 'views' . DS . 'some_dir_overall_favorites_index.php')); Configure::write('Cache.check', $_back['check']); Configure::write('Cache.disable', $_back['disable']); } /** * test that save() resets whitelist on failed save * * @return void */ public function testSaveFieldListResetsWhitelistOnFailedSave() { $this->loadFixtures('Bidding'); $model = new Bidding(); $whitelist = array('title'); $model->whitelist = $whitelist; $result = $model->save( array(), array('fieldList' => array('body')) ); $this->assertFalse($result); $this->assertEquals($whitelist, $model->whitelist); } /** * Test that save() with a fieldList continues to write * updated in all cases. * * @return void */ public function testSaveUpdatedWithFieldList() { $this->loadFixtures('Post', 'Author'); $model = ClassRegistry::init('Post'); $original = $model->find('first', array( 'conditions' => array('Post.id' => 1) )); $data = array( 'Post' => array( 'id' => 1, 'title' => 'New title', 'updated' => '1999-01-01 00:00:00', ) ); $model->save($data, array( 'fieldList' => array('title') )); $new = $model->find('first', array( 'conditions' => array('Post.id' => 1) )); $this->assertGreaterThan($original['Post']['updated'], $new['Post']['updated']); } /** * Test save() resets the whitelist after afterSave * * @return void */ public function testSaveResetWhitelistOnSuccess() { $this->loadFixtures('Post'); $callback = array($this, 'callbackForWhitelistReset'); $model = ClassRegistry::init('Post'); $model->whitelist = array('author_id', 'title', 'body'); $model->getEventManager()->attach($callback, 'Model.afterSave'); $data = array( 'title' => 'New post', 'body' => 'Post body', 'author_id' => 1 ); $result = $model->save($data); $this->assertNotEmpty($result); } /** * Callback for testing whitelist in afterSave * * @param Model $model The model having save called. * @return void */ public function callbackForWhitelistReset($event) { $expected = array('author_id', 'title', 'body', 'updated', 'created'); $this->assertEquals($expected, $event->subject()->whitelist); } /** * testSaveWithCounterCache method * * @return void */ public function testSaveWithCounterCache() { $this->loadFixtures('Syfile', 'Item', 'Image', 'Portfolio', 'ItemsPortfolio'); $TestModel = new Syfile(); $TestModel2 = new Item(); $result = $TestModel->findById(1); $this->assertNull($result['Syfile']['item_count']); $TestModel2->save(array( 'name' => 'Item 7', 'syfile_id' => 1, 'published' => false )); $result = $TestModel->findById(1); $this->assertEquals(2, $result['Syfile']['item_count']); $TestModel2->delete(1); $result = $TestModel->findById(1); $this->assertEquals(1, $result['Syfile']['item_count']); $TestModel2->id = 2; $TestModel2->saveField('syfile_id', 1); $result = $TestModel->findById(1); $this->assertEquals(2, $result['Syfile']['item_count']); $result = $TestModel->findById(2); $this->assertEquals(0, $result['Syfile']['item_count']); } /** * Tests that counter caches are updated when records are added * * @return void */ public function testCounterCacheIncrease() { $this->loadFixtures('CounterCacheUser', 'CounterCachePost'); $User = new CounterCacheUser(); $Post = new CounterCachePost(); $data = array('Post' => array( 'id' => 22, 'title' => 'New Post', 'user_id' => 66 )); $Post->save($data); $user = $User->find('first', array( 'conditions' => array('id' => 66), 'recursive' => -1 )); $result = $user[$User->alias]['post_count']; $expected = 3; $this->assertEquals($expected, $result); } /** * Tests that counter caches are updated when records are deleted * * @return void */ public function testCounterCacheDecrease() { $this->loadFixtures('CounterCacheUser', 'CounterCachePost'); $User = new CounterCacheUser(); $Post = new CounterCachePost(); $Post->delete(2); $user = $User->find('first', array( 'conditions' => array('id' => 66), 'recursive' => -1 )); $result = $user[$User->alias]['post_count']; $expected = 1; $this->assertEquals($expected, $result); } /** * Tests that counter caches are updated when foreign keys of counted records change * * @return void */ public function testCounterCacheUpdated() { $this->loadFixtures('CounterCacheUser', 'CounterCachePost'); $User = new CounterCacheUser(); $Post = new CounterCachePost(); $data = $Post->find('first', array( 'conditions' => array('id' => 1), 'recursive' => -1 )); $data[$Post->alias]['user_id'] = 301; $Post->save($data); $users = $User->find('all', array('order' => 'User.id')); $this->assertEquals(1, $users[0]['User']['post_count']); $this->assertEquals(2, $users[1]['User']['post_count']); } /** * Test counter cache with models that use a non-standard (i.e. not using 'id') * as their primary key. * * @return void */ public function testCounterCacheWithNonstandardPrimaryKey() { $this->loadFixtures( 'CounterCacheUserNonstandardPrimaryKey', 'CounterCachePostNonstandardPrimaryKey' ); $User = new CounterCacheUserNonstandardPrimaryKey(); $Post = new CounterCachePostNonstandardPrimaryKey(); $data = $Post->find('first', array( 'conditions' => array('pid' => 1), 'recursive' => -1 )); $data[$Post->alias]['uid'] = 301; $Post->save($data); $users = $User->find('all', array('order' => 'User.uid')); $this->assertEquals(1, $users[0]['User']['post_count']); $this->assertEquals(2, $users[1]['User']['post_count']); } /** * test Counter Cache With Self Joining table * * @return void */ public function testCounterCacheWithSelfJoin() { $this->skipIf($this->db instanceof Sqlite, 'SQLite 2.x does not support ALTER TABLE ADD COLUMN'); $this->loadFixtures('CategoryThread'); $column = 'COLUMN '; if ($this->db instanceof Sqlserver) { $column = ''; } $column .= $this->db->buildColumn(array('name' => 'child_count', 'type' => 'integer')); $this->db->query('ALTER TABLE ' . $this->db->fullTableName('category_threads') . ' ADD ' . $column); $this->db->flushMethodCache(); $Category = new CategoryThread(); $result = $Category->updateAll(array('CategoryThread.name' => "'updated'"), array('CategoryThread.parent_id' => 5)); $this->assertFalse(empty($result)); $Category = new CategoryThread(); $Category->belongsTo['ParentCategory']['counterCache'] = 'child_count'; $Category->updateCounterCache(array('parent_id' => 5)); $result = Hash::extract($Category->find('all', array('conditions' => array('CategoryThread.id' => 5))), '{n}.CategoryThread.child_count'); $expected = array(1); $this->assertEquals($expected, $result); } /** * testSaveWithCounterCacheScope method * * @return void */ public function testSaveWithCounterCacheScope() { $this->loadFixtures('Syfile', 'Item', 'Image', 'ItemsPortfolio', 'Portfolio'); $TestModel = new Syfile(); $TestModel2 = new Item(); $TestModel2->belongsTo['Syfile']['counterCache'] = true; $TestModel2->belongsTo['Syfile']['counterScope'] = array('published' => true); $result = $TestModel->findById(1); $this->assertNull($result['Syfile']['item_count']); $TestModel2->save(array( 'name' => 'Item 7', 'syfile_id' => 1, 'published' => true )); $result = $TestModel->findById(1); $this->assertEquals(1, $result['Syfile']['item_count']); $TestModel2->id = 1; $TestModel2->saveField('published', true); $result = $TestModel->findById(1); $this->assertEquals(2, $result['Syfile']['item_count']); $TestModel2->save(array( 'id' => 1, 'syfile_id' => 1, 'published' => false )); $result = $TestModel->findById(1); $this->assertEquals(1, $result['Syfile']['item_count']); } /** * Tests having multiple counter caches for an associated model * * @return void */ public function testCounterCacheMultipleCaches() { $this->loadFixtures('CounterCacheUser', 'CounterCachePost'); $User = new CounterCacheUser(); $Post = new CounterCachePost(); $Post->unbindModel(array('belongsTo' => array('User')), false); $Post->bindModel(array( 'belongsTo' => array( 'User' => array( 'className' => 'CounterCacheUser', 'foreignKey' => 'user_id', 'counterCache' => array( true, 'posts_published' => array('Post.published' => true) ) ) ) ), false); // Count Increase $data = array('Post' => array( 'id' => 22, 'title' => 'New Post', 'user_id' => 66, 'published' => true )); $Post->save($data); $result = $User->find('first', array( 'conditions' => array('id' => 66), 'recursive' => -1 )); $this->assertEquals(3, $result[$User->alias]['post_count']); $this->assertEquals(2, $result[$User->alias]['posts_published']); // Count decrease $Post->delete(1); $result = $User->find('first', array( 'conditions' => array('id' => 66), 'recursive' => -1 )); $this->assertEquals(2, $result[$User->alias]['post_count']); $this->assertEquals(2, $result[$User->alias]['posts_published']); // Count update $data = $Post->find('first', array( 'conditions' => array('id' => 1), 'recursive' => -1 )); $data[$Post->alias]['user_id'] = 301; $Post->save($data); $result = $User->find('all', array('order' => 'User.id')); $this->assertEquals(2, $result[0]['User']['post_count']); $this->assertEquals(1, $result[1]['User']['posts_published']); } /** * Tests that counter caches are unchanged when using 'counterCache' => false * * @return void */ public function testCounterCacheSkip() { $this->loadFixtures('CounterCacheUser', 'CounterCachePost'); $User = new CounterCacheUser(); $Post = new CounterCachePost(); $data = $Post->find('first', array( 'conditions' => array('id' => 1), 'recursive' => -1 )); $data[$Post->alias]['user_id'] = 301; $Post->save($data, array('counterCache' => false)); $users = $User->find('all', array('order' => 'User.id')); $this->assertEquals(2, $users[0]['User']['post_count']); $this->assertEquals(1, $users[1]['User']['post_count']); } /** * test that beforeValidate returning false can abort saves. * * @return void */ public function testBeforeValidateSaveAbortion() { $this->loadFixtures('Post'); $Model = new CallbackPostTestModel(); $Model->beforeValidateReturn = false; $data = array( 'title' => 'new article', 'body' => 'this is some text.' ); $Model->create(); $result = $Model->save($data); $this->assertFalse($result); } /** * test that beforeSave returning false can abort saves. * * @return void */ public function testBeforeSaveSaveAbortion() { $this->loadFixtures('Post'); $Model = new CallbackPostTestModel(); $Model->beforeSaveReturn = false; $data = array( 'title' => 'new article', 'body' => 'this is some text.' ); $Model->create(); $result = $Model->save($data); $this->assertFalse($result); } /** * testSaveAtomic method * * @return void */ public function testSaveAtomic() { $this->loadFixtures('Article'); $TestModel = new Article(); // Create record with 'atomic' = false $data = array( 'Article' => array( 'user_id' => '1', 'title' => 'Fourth Article', 'body' => 'Fourth Article Body', 'published' => 'Y' ) ); $TestModel->create(); $result = $TestModel->save($data, array('atomic' => false)); $this->assertTrue((bool)$result); // Check record we created $TestModel->recursive = -1; $result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4); $expected = array( 'Article' => array( 'id' => '4', 'user_id' => '1', 'title' => 'Fourth Article', 'body' => 'Fourth Article Body', 'published' => 'Y' ) ); $this->assertEquals($expected, $result); // Create record with 'atomic' = true $data = array( 'Article' => array( 'user_id' => '4', 'title' => 'Fifth Article', 'body' => 'Fifth Article Body', 'published' => 'Y' ) ); $TestModel->create(); $result = $TestModel->save($data, array('atomic' => true)); $this->assertTrue((bool)$result); // Check record we created $TestModel->recursive = -1; $result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5); $expected = array( 'Article' => array( 'id' => '5', 'user_id' => '4', 'title' => 'Fifth Article', 'body' => 'Fifth Article Body', 'published' => 'Y' ) ); $this->assertEquals($expected, $result); } /** * test save with transaction and ensure there is no missing rollback. * * @return void */ public function testSaveTransactionNoRollback() { $this->loadFixtures('Post', 'Article'); $db = $this->getMock('DboSource', array('begin', 'connect', 'rollback', 'describe')); $db->expects($this->once()) ->method('describe') ->will($this->returnValue(array())); $db->expects($this->once()) ->method('begin') ->will($this->returnValue(true)); $db->expects($this->once()) ->method('rollback'); $Post = new TestPost(); $Post->setDataSourceObject($db); $callback = array($this, 'callbackForTestSaveTransaction'); $Post->getEventManager()->attach($callback, 'Model.beforeSave'); $data = array( 'Post' => array( 'author_id' => 1, 'title' => 'New Fourth Post' ) ); $Post->save($data, array('atomic' => true)); } /** * test callback used in testSaveTransaction method * * @return bool false to stop event propagation */ public function callbackForTestSaveTransaction($event) { $TestModel = new Article(); // Create record. Do not use same model as in testSaveTransaction // to avoid infinite loop. $data = array( 'Article' => array( 'user_id' => '1', 'title' => 'Fourth Article', 'body' => 'Fourth Article Body', 'published' => 'Y' ) ); $TestModel->create(); $result = $TestModel->save($data); $this->assertTrue((bool)$result); // force transaction to be rolled back in Post model $event->stopPropagation(); return false; } /** * testSaveTransaction method * * @return void */ public function testSaveTransaction() { $this->loadFixtures('Post', 'Article'); $PostModel = new Post(); // Check if Database supports transactions $PostModel->validate = array('title' => 'notBlank'); $data = array( array('author_id' => 1, 'title' => 'New Fourth Post'), array('author_id' => 1, 'title' => 'New Fifth Post'), array('author_id' => 1, 'title' => '') ); $this->assertFalse($PostModel->saveAll($data)); $result = $PostModel->find('all', array('recursive' => -1)); $expectedPosts = array( array( 'Post' => array( 'id' => '1', 'author_id' => 1, 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' ) ), array( 'Post' => array( 'id' => '2', 'author_id' => 3, 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ) ), array( 'Post' => array( 'id' => '3', 'author_id' => 1, 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ) ); $this->skipIf(count($result) !== 3, 'Database does not support transactions.'); $this->assertEquals($expectedPosts, $result); // Database supports transactions --> continue tests $data = array( 'Post' => array( 'author_id' => 1, 'title' => 'New Fourth Post' ) ); $callback = array($this, 'callbackForTestSaveTransaction'); $PostModel->getEventManager()->attach($callback, 'Model.beforeSave'); $PostModel->create(); $result = $PostModel->save($data, array('atomic' => true)); $this->assertFalse($result); $result = $PostModel->find('all', array('recursive' => -1)); $this->assertEquals($expectedPosts, $result); // Check record we created in callbackForTestSaveTransaction method. // record should not exist due to rollback $ArticleModel = new Article(); $result = $ArticleModel->find('all', array('recursive' => -1)); $expectedArticles = array( array( 'Article' => array( 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31', 'id' => '1' ) ), array( 'Article' => array( 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31', 'id' => '2' ) ), array( 'Article' => array( 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31', 'id' => '3' ) ) ); $this->assertEquals($expectedArticles, $result); } /** * testSaveField method * * @return void */ public function testSaveField() { $this->loadFixtures('Article'); $TestModel = new Article(); $TestModel->id = 1; $result = $TestModel->saveField('title', 'New First Article'); $this->assertFalse(empty($result)); $TestModel->recursive = -1; $result = $TestModel->read(array('id', 'user_id', 'title', 'body'), 1); $expected = array('Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'New First Article', 'body' => 'First Article Body' )); $this->assertEquals($expected, $result); $TestModel->id = 1; $result = $TestModel->saveField('title', ''); $this->assertFalse(empty($result)); $TestModel->recursive = -1; $result = $TestModel->read(array('id', 'user_id', 'title', 'body'), 1); $expected = array('Article' => array( 'id' => '1', 'user_id' => '1', 'title' => '', 'body' => 'First Article Body' )); $result['Article']['title'] = trim($result['Article']['title']); $this->assertEquals($expected, $result); $TestModel->id = 1; $TestModel->set('body', 'Messed up data'); $result = $TestModel->saveField('title', 'First Article'); $this->assertFalse(empty($result)); $result = $TestModel->read(array('id', 'user_id', 'title', 'body'), 1); $expected = array('Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body' )); $this->assertEquals($expected, $result); $TestModel->recursive = -1; $TestModel->read(array('id', 'user_id', 'title', 'body'), 1); $TestModel->id = 1; $result = $TestModel->saveField('title', '', true); $this->assertFalse($result); $TestModel->recursive = -1; $TestModel->id = 1; $result = $TestModel->saveField('user_id', 9999); $this->assertTrue((bool)$result); $result = $TestModel->read(array('id', 'user_id'), 1); $expected = array('Article' => array( 'id' => '1', 'user_id' => '9999', )); $this->assertEquals($expected, $result); $this->loadFixtures('Node', 'Dependency'); $Node = new Node(); $Node->set('id', 1); $result = $Node->read(); $this->assertEquals(array('Second'), Hash::extract($result, 'ParentNode.{n}.name')); $Node->saveField('state', 10); $result = $Node->read(); $this->assertEquals(array('Second'), Hash::extract($result, 'ParentNode.{n}.name')); } /** * testSaveWithCreate method * * @return void */ public function testSaveWithCreate() { $this->loadFixtures( 'User', 'Article', 'User', 'Comment', 'Tag', 'ArticlesTag', 'Attachment' ); $TestModel = new User(); $data = array('User' => array( 'user' => 'user', 'password' => '' )); $result = $TestModel->save($data); $this->assertFalse($result); $this->assertTrue(!empty($TestModel->validationErrors)); $TestModel = new Article(); $data = array('Article' => array( 'user_id' => '', 'title' => '', 'body' => '' )); $result = $TestModel->create($data) && $TestModel->save(); $this->assertFalse($result); $this->assertTrue(!empty($TestModel->validationErrors)); $data = array('Article' => array( 'id' => 1, 'user_id' => '1', 'title' => 'New First Article', 'body' => '' )); $result = $TestModel->create($data) && $TestModel->save(); $this->assertFalse($result); $data = array('Article' => array( 'id' => 1, 'title' => 'New First Article' )); $result = $TestModel->create() && $TestModel->save($data, false); $this->assertFalse(empty($result)); $TestModel->recursive = -1; $result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 1); $expected = array('Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'New First Article', 'body' => 'First Article Body', 'published' => 'N' )); $this->assertEquals($expected, $result); $data = array('Article' => array( 'id' => 1, 'user_id' => '2', 'title' => 'First Article', 'body' => 'New First Article Body', 'published' => 'Y' )); $result = $TestModel->create() && $TestModel->save($data, true, array('id', 'title', 'published')); $this->assertFalse(empty($result)); $TestModel->recursive = -1; $result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 1); $expected = array('Article' => array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y' )); $this->assertEquals($expected, $result); $data = array( 'Article' => array( 'user_id' => '2', 'title' => 'New Article', 'body' => 'New Article Body', 'created' => '2007-03-18 14:55:23', 'updated' => '2007-03-18 14:57:31' ), 'Tag' => array('Tag' => array(1, 3)) ); $TestModel->create(); $result = $TestModel->create() && $TestModel->save($data); $this->assertFalse(empty($result)); $TestModel->recursive = 2; $result = $TestModel->read(null, 4); $expected = array( 'Article' => array( 'id' => '4', 'user_id' => '2', 'title' => 'New Article', 'body' => 'New Article Body', 'published' => 'N', 'created' => '2007-03-18 14:55:23', 'updated' => '2007-03-18 14:57:31' ), 'User' => array( 'id' => '2', 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'Comment' => array(), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ))); $this->assertEquals($expected, $result); $data = array('Comment' => array( 'article_id' => '4', 'user_id' => '1', 'comment' => 'Comment New Article', 'published' => 'Y', 'created' => '2007-03-18 14:57:23', 'updated' => '2007-03-18 14:59:31' )); $result = $TestModel->Comment->create() && $TestModel->Comment->save($data); $this->assertFalse(empty($result)); $data = array('Attachment' => array( 'comment_id' => '7', 'attachment' => 'newattachment.zip', 'created' => '2007-03-18 15:02:23', 'updated' => '2007-03-18 15:04:31' )); $result = $TestModel->Comment->Attachment->save($data); $this->assertFalse(empty($result)); $TestModel->recursive = 2; $result = $TestModel->read(null, 4); $expected = array( 'Article' => array( 'id' => '4', 'user_id' => '2', 'title' => 'New Article', 'body' => 'New Article Body', 'published' => 'N', 'created' => '2007-03-18 14:55:23', 'updated' => '2007-03-18 14:57:31' ), 'User' => array( 'id' => '2', 'user' => 'nate', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:18:23', 'updated' => '2007-03-17 01:20:31' ), 'Comment' => array( array( 'id' => '7', 'article_id' => '4', 'user_id' => '1', 'comment' => 'Comment New Article', 'published' => 'Y', 'created' => '2007-03-18 14:57:23', 'updated' => '2007-03-18 14:59:31', 'Article' => array( 'id' => '4', 'user_id' => '2', 'title' => 'New Article', 'body' => 'New Article Body', 'published' => 'N', 'created' => '2007-03-18 14:55:23', 'updated' => '2007-03-18 14:57:31' ), 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31' ), 'Attachment' => array( 'id' => '2', 'comment_id' => '7', 'attachment' => 'newattachment.zip', 'created' => '2007-03-18 15:02:23', 'updated' => '2007-03-18 15:04:31' ))), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ))); $this->assertEquals($expected, $result); } /** * test that a null Id doesn't cause errors * * @return void */ public function testSaveWithNullId() { $this->loadFixtures('User'); $User = new User(); $User->read(null, 1); $User->data['User']['id'] = null; $result = $User->save(array('password' => 'test')); $this->assertFalse(empty($result)); $this->assertTrue($User->id > 0); $User->read(null, 2); $User->data['User']['id'] = null; $result = $User->save(array('password' => 'test')); $this->assertFalse(empty($result)); $this->assertTrue($User->id > 0); $User->data['User'] = array('password' => 'something'); $result = $User->save(); $this->assertFalse(empty($result)); $result = $User->read(); $this->assertEquals('something', $User->data['User']['password']); } /** * testSaveWithSet method * * @return void */ public function testSaveWithSet() { $this->loadFixtures('Article'); $TestModel = new Article(); // Create record we will be updating later $data = array('Article' => array( 'user_id' => '1', 'title' => 'Fourth Article', 'body' => 'Fourth Article Body', 'published' => 'Y' )); $result = $TestModel->create() && $TestModel->save($data); $this->assertFalse(empty($result)); // Check record we created $TestModel->recursive = -1; $result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4); $expected = array('Article' => array( 'id' => '4', 'user_id' => '1', 'title' => 'Fourth Article', 'body' => 'Fourth Article Body', 'published' => 'Y' )); $this->assertEquals($expected, $result); // Create new record just to overlap Model->id on previously created record $data = array('Article' => array( 'user_id' => '4', 'title' => 'Fifth Article', 'body' => 'Fifth Article Body', 'published' => 'Y' )); $result = $TestModel->create() && $TestModel->save($data); $this->assertFalse(empty($result)); $TestModel->recursive = -1; $result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5); $expected = array('Article' => array( 'id' => '5', 'user_id' => '4', 'title' => 'Fifth Article', 'body' => 'Fifth Article Body', 'published' => 'Y' )); $this->assertEquals($expected, $result); // Go back and edit the first article we created, starting by checking it's still there $TestModel->recursive = -1; $result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4); $expected = array('Article' => array( 'id' => '4', 'user_id' => '1', 'title' => 'Fourth Article', 'body' => 'Fourth Article Body', 'published' => 'Y' )); $this->assertEquals($expected, $result); // And now do the update with set() $data = array('Article' => array( 'id' => '4', 'title' => 'Fourth Article - New Title', 'published' => 'N' )); $result = $TestModel->set($data) && $TestModel->save(); $this->assertFalse(empty($result)); $TestModel->recursive = -1; $result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4); $expected = array('Article' => array( 'id' => '4', 'user_id' => '1', 'title' => 'Fourth Article - New Title', 'body' => 'Fourth Article Body', 'published' => 'N' )); $this->assertEquals($expected, $result); $TestModel->recursive = -1; $result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5); $expected = array('Article' => array( 'id' => '5', 'user_id' => '4', 'title' => 'Fifth Article', 'body' => 'Fifth Article Body', 'published' => 'Y' )); $this->assertEquals($expected, $result); $data = array('Article' => array('id' => '5', 'title' => 'Fifth Article - New Title 5')); $result = ($TestModel->set($data) && $TestModel->save()); $this->assertFalse(empty($result)); $TestModel->recursive = -1; $result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5); $expected = array('Article' => array( 'id' => '5', 'user_id' => '4', 'title' => 'Fifth Article - New Title 5', 'body' => 'Fifth Article Body', 'published' => 'Y' )); $this->assertEquals($expected, $result); $TestModel->recursive = -1; $result = $TestModel->find('all', array( 'fields' => array('id', 'title'), 'order' => array('Article.id' => 'ASC') )); $expected = array( array('Article' => array('id' => 1, 'title' => 'First Article')), array('Article' => array('id' => 2, 'title' => 'Second Article')), array('Article' => array('id' => 3, 'title' => 'Third Article')), array('Article' => array('id' => 4, 'title' => 'Fourth Article - New Title')), array('Article' => array('id' => 5, 'title' => 'Fifth Article - New Title 5')) ); $this->assertEquals($expected, $result); } /** * testSaveWithNonExistentFields method * * @return void */ public function testSaveWithNonExistentFields() { $this->loadFixtures('Article'); $TestModel = new Article(); $TestModel->recursive = -1; $data = array( 'non_existent' => 'This field does not exist', 'user_id' => '1', 'title' => 'Fourth Article - New Title', 'body' => 'Fourth Article Body', 'published' => 'N' ); $result = $TestModel->create() && $TestModel->save($data); $this->assertFalse(empty($result)); $expected = array('Article' => array( 'id' => '4', 'user_id' => '1', 'title' => 'Fourth Article - New Title', 'body' => 'Fourth Article Body', 'published' => 'N' )); $result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 4); $this->assertEquals($expected, $result); $data = array( 'user_id' => '1', 'non_existent' => 'This field does not exist', 'title' => 'Fifth Article - New Title', 'body' => 'Fifth Article Body', 'published' => 'N' ); $result = $TestModel->create() && $TestModel->save($data); $this->assertFalse(empty($result)); $expected = array('Article' => array( 'id' => '5', 'user_id' => '1', 'title' => 'Fifth Article - New Title', 'body' => 'Fifth Article Body', 'published' => 'N' )); $result = $TestModel->read(array('id', 'user_id', 'title', 'body', 'published'), 5); $this->assertEquals($expected, $result); } /** * testSaveFromXml method * * @return void */ public function testSaveFromXml() { $this->markTestSkipped('This feature needs to be fixed or dropped'); $this->loadFixtures('Article'); App::uses('Xml', 'Utility'); $Article = new Article(); $result = $Article->save(Xml::build('
')); $this->assertFalse(empty($result)); $results = $Article->find('first', array('conditions' => array('Article.title' => 'test xml'))); $this->assertFalse(empty($results)); $result = $Article->save(Xml::build('
testing6
')); $this->assertFalse(empty($result)); $results = $Article->find('first', array('conditions' => array('Article.title' => 'testing'))); $this->assertFalse(empty($results)); $result = $Article->save(Xml::build('
testing with DOMDocument7
', array('return' => 'domdocument'))); $this->assertFalse(empty($result)); $results = $Article->find('first', array('conditions' => array('Article.title' => 'testing with DOMDocument'))); $this->assertFalse(empty($results)); } /** * testSaveHabtm method * * @return void */ public function testSaveHabtm() { $this->loadFixtures('Article', 'User', 'Comment', 'Tag', 'ArticlesTag'); $TestModel = new Article(); $result = $TestModel->findById(2); $expected = array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'User' => array( 'id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31' ), 'Comment' => array( array( 'id' => '5', 'article_id' => '2', 'user_id' => '1', 'comment' => 'First Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:53:23', 'updated' => '2007-03-18 10:55:31' ), array( 'id' => '6', 'article_id' => '2', 'user_id' => '2', 'comment' => 'Second Comment for Second Article', 'published' => 'Y', 'created' => '2007-03-18 10:55:23', 'updated' => '2007-03-18 10:57:31' )), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ) ) ); $this->assertEquals($expected, $result); $data = array( 'Article' => array( 'id' => '2', 'title' => 'New Second Article' ), 'Tag' => array('Tag' => array(1, 2)) ); $result = $TestModel->set($data); $this->assertFalse(empty($result)); $result = $TestModel->save(); $this->assertFalse(empty($result)); $this->assertEquals($data['Tag'], $result['Tag']); $TestModel->unbindModel(array('belongsTo' => array('User'), 'hasMany' => array('Comment'))); $result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2))); $expected = array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'New Second Article', 'body' => 'Second Article Body' ), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ))); $this->assertEquals($expected, $result); $data = array('Article' => array('id' => '2'), 'Tag' => array('Tag' => array(2, 3))); $result = $TestModel->set($data); $this->assertFalse(empty($result)); $result = $TestModel->save(); $this->assertFalse(empty($result)); $TestModel->unbindModel(array( 'belongsTo' => array('User'), 'hasMany' => array('Comment') )); $result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2))); $expected = array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'New Second Article', 'body' => 'Second Article Body' ), 'Tag' => array( array( 'id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ))); $this->assertEquals($expected, $result); $data = array('Tag' => array('Tag' => array(1, 2, 3))); $result = $TestModel->set($data); $this->assertFalse(empty($result)); $result = $TestModel->save(); $this->assertFalse(empty($result)); $TestModel->unbindModel(array( 'belongsTo' => array('User'), 'hasMany' => array('Comment') )); $result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2))); $expected = array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'New Second Article', 'body' => 'Second Article Body' ), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ))); $this->assertEquals($expected, $result); $data = array('Tag' => array('Tag' => array())); $result = $TestModel->set($data); $this->assertFalse(empty($result)); $result = $TestModel->save(); $this->assertFalse(empty($result)); $data = array('Tag' => array('Tag' => '')); $result = $TestModel->set($data); $this->assertFalse(empty($result)); $result = $TestModel->save(); $this->assertFalse(empty($result)); $TestModel->unbindModel(array( 'belongsTo' => array('User'), 'hasMany' => array('Comment') )); $result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2))); $expected = array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'New Second Article', 'body' => 'Second Article Body' ), 'Tag' => array() ); $this->assertEquals($expected, $result); $data = array('Tag' => array('Tag' => array(2, 3))); $result = $TestModel->set($data); $this->assertFalse(empty($result)); $result = $TestModel->save(); $this->assertFalse(empty($result)); $TestModel->unbindModel(array( 'belongsTo' => array('User'), 'hasMany' => array('Comment') )); $result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2))); $expected = array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'New Second Article', 'body' => 'Second Article Body' ), 'Tag' => array( array( 'id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ))); $this->assertEquals($expected, $result); $data = array( 'Tag' => array( 'Tag' => array(1, 2) ), 'Article' => array( 'id' => '2', 'title' => 'New Second Article' )); $result = $TestModel->set($data); $this->assertFalse(empty($result)); $result = $TestModel->save(); $this->assertFalse(empty($result)); $TestModel->unbindModel(array( 'belongsTo' => array('User'), 'hasMany' => array('Comment') )); $result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2))); $expected = array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'New Second Article', 'body' => 'Second Article Body' ), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ))); $this->assertEquals($expected, $result); $data = array( 'Tag' => array( 'Tag' => array(1, 2) ), 'Article' => array( 'id' => '2', 'title' => 'New Second Article Title' )); $result = $TestModel->set($data); $this->assertFalse(empty($result)); $result = $TestModel->save(); $this->assertFalse(empty($result)); $TestModel->unbindModel(array( 'belongsTo' => array('User'), 'hasMany' => array('Comment') )); $result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2))); $expected = array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'New Second Article Title', 'body' => 'Second Article Body' ), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ) ) ); $this->assertEquals($expected, $result); $data = array( 'Tag' => array( 'Tag' => array(2, 3) ), 'Article' => array( 'id' => '2', 'title' => 'Changed Second Article' )); $result = $TestModel->set($data); $this->assertFalse(empty($result)); $result = $TestModel->save(); $this->assertFalse(empty($result)); $TestModel->unbindModel(array( 'belongsTo' => array('User'), 'hasMany' => array('Comment') )); $result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2))); $expected = array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Changed Second Article', 'body' => 'Second Article Body' ), 'Tag' => array( array( 'id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ) ) ); $this->assertEquals($expected, $result); $data = array( 'Tag' => array( 'Tag' => array(1, 3) ), 'Article' => array('id' => '2'), ); $result = $TestModel->set($data); $this->assertFalse(empty($result)); $result = $TestModel->save(); $this->assertFalse(empty($result)); $TestModel->unbindModel(array( 'belongsTo' => array('User'), 'hasMany' => array('Comment') )); $result = $TestModel->find('first', array('fields' => array('id', 'user_id', 'title', 'body'), 'conditions' => array('Article.id' => 2))); $expected = array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Changed Second Article', 'body' => 'Second Article Body' ), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ))); $this->assertEquals($expected, $result); $data = array( 'Article' => array( 'id' => 10, 'user_id' => '2', 'title' => 'New Article With Tags and fieldList', 'body' => 'New Article Body with Tags and fieldList', 'created' => '2007-03-18 14:55:23', 'updated' => '2007-03-18 14:57:31' ), 'Tag' => array( 'Tag' => array(1, 2, 3) ) ); $result = $TestModel->create() && $TestModel->save($data, true, array('user_id', 'title', 'published')); $this->assertFalse(empty($result)); $TestModel->unbindModel(array( 'belongsTo' => array('User'), 'hasMany' => array('Comment') )); $result = $TestModel->read(); $expected = array( 'Article' => array( 'id' => 4, 'user_id' => 2, 'title' => 'New Article With Tags and fieldList', 'body' => '', 'published' => 'N', 'created' => static::date(), 'updated' => static::date(), ), 'Tag' => array( 0 => array( 'id' => 1, 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), 1 => array( 'id' => 2, 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ), 2 => array( 'id' => 3, 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ))); $this->assertEquals($expected, $result); $this->loadFixtures('JoinA', 'JoinC', 'JoinAC', 'JoinB', 'JoinAB'); $TestModel = new JoinA(); $TestModel->hasBelongsToMany = array('JoinC' => array('unique' => true)); $data = array( 'JoinA' => array( 'id' => 1, 'name' => 'Join A 1', 'body' => 'Join A 1 Body', ), 'JoinC' => array( 'JoinC' => array( array('join_c_id' => 2, 'other' => 'new record'), array('join_c_id' => 3, 'other' => 'new record') ) ) ); $TestModel->save($data); $result = $TestModel->read(null, 1); $expected = array(4, 5); $this->assertEquals($expected, Hash::extract($result, 'JoinC.{n}.JoinAsJoinC.id')); $expected = array('new record', 'new record'); $this->assertEquals($expected, Hash::extract($result, 'JoinC.{n}.JoinAsJoinC.other')); } /** * test that saving HABTM with an empty array will clear existing HABTM if * unique is true * * @return void */ public function testSaveHabtmEmptyData() { $this->loadFixtures('Node', 'Dependency'); $Node = new Node(); $data = array( 'Node' => array('name' => 'New First') ); $Node->id = 1; $Node->save($data); $node = $Node->find('first', array( 'conditions' => array('Node.id' => 1), 'contain' => array('ParentNode') )); $result = Hash::extract($node, 'ParentNode.{n}.id'); $expected = array(2); $this->assertEquals($expected, $result); $data = array( 'ParentNode' => array() ); $Node->id = 1; $Node->save($data); $node = $Node->find('first', array( 'conditions' => array('Node.id' => 1), 'contain' => array('ParentNode') )); $result = Hash::extract($node, 'ParentNode.{n}.id'); $expected = array(); $this->assertEquals($expected, $result); } /** * testSaveHabtmNoPrimaryData method * * @return void */ public function testSaveHabtmNoPrimaryData() { $this->loadFixtures('Article', 'User', 'Comment', 'Tag', 'ArticlesTag'); $TestModel = new Article(); $TestModel->unbindModel(array('belongsTo' => array('User'), 'hasMany' => array('Comment')), false); $result = $TestModel->findById(2); $expected = array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' ), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31' ), array( 'id' => '3', 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ) ) ); $this->assertEquals($expected, $result); $TestModel->id = 2; $data = array('Tag' => array('Tag' => array(2))); $result = $TestModel->save($data); $this->assertEquals($data['Tag'], $result['Tag']); $result = $TestModel->findById(2); $expected = array( 'Article' => array( 'id' => '2', 'user_id' => '3', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => static::date() ), 'Tag' => array( array( 'id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ) ) ); $this->assertEquals($expected, $result); $this->loadFixtures('Portfolio', 'Item', 'ItemsPortfolio'); $TestModel = new Portfolio(); $result = $TestModel->findById(2); $expected = array( 'Portfolio' => array( 'id' => 2, 'seller_id' => 1, 'name' => 'Portfolio 2' ), 'Item' => array( array( 'id' => 2, 'syfile_id' => 2, 'published' => '', 'name' => 'Item 2', 'ItemsPortfolio' => array( 'id' => 2, 'item_id' => 2, 'portfolio_id' => 2 ) ), array( 'id' => 6, 'syfile_id' => 6, 'published' => '', 'name' => 'Item 6', 'ItemsPortfolio' => array( 'id' => 6, 'item_id' => 6, 'portfolio_id' => 2 ) ) ) ); $this->assertEquals($expected, $result); $data = array('Item' => array('Item' => array(1, 2))); $TestModel->id = 2; $result = $TestModel->save($data); $this->assertTrue((bool)$result); $result = $TestModel->findById(2); $result['Item'] = Hash::sort($result['Item'], '{n}.id', 'asc'); $expected = array( 'Portfolio' => array( 'id' => 2, 'seller_id' => 1, 'name' => 'Portfolio 2' ), 'Item' => array( array( 'id' => 1, 'syfile_id' => 1, 'published' => '', 'name' => 'Item 1', 'ItemsPortfolio' => array( 'id' => 7, 'item_id' => 1, 'portfolio_id' => 2 ) ), array( 'id' => 2, 'syfile_id' => 2, 'published' => '', 'name' => 'Item 2', 'ItemsPortfolio' => array( 'id' => 8, 'item_id' => 2, 'portfolio_id' => 2 ) ) ) ); $this->assertEquals($expected, $result); } /** * testSaveHabtmCustomKeys method * * @return void */ public function testSaveHabtmCustomKeys() { $this->loadFixtures('Story', 'StoriesTag', 'Tag'); $Story = new Story(); $data = array( 'Story' => array('story' => '1'), 'Tag' => array( 'Tag' => array(2, 3) )); $result = $Story->set($data); $this->assertFalse(empty($result)); $result = $Story->save(); $this->assertFalse(empty($result)); $result = $Story->find('all', array('order' => array('Story.story'))); $expected = array( array( 'Story' => array( 'story' => 1, 'title' => 'First Story' ), 'Tag' => array( array( 'id' => 2, 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31' ), array( 'id' => 3, 'tag' => 'tag3', 'created' => '2007-03-18 12:26:23', 'updated' => '2007-03-18 12:28:31' ))), array( 'Story' => array( 'story' => 2, 'title' => 'Second Story' ), 'Tag' => array() )); $this->assertEquals($expected, $result); } /** * test that saving habtm records respects conditions set in the 'conditions' key * for the association. * * @return void */ public function testHabtmSaveWithConditionsInAssociation() { $this->loadFixtures('JoinThing', 'Something', 'SomethingElse'); $Something = new Something(); $Something->unbindModel(array('hasAndBelongsToMany' => array('SomethingElse')), false); $Something->bindModel(array( 'hasAndBelongsToMany' => array( 'DoomedSomethingElse' => array( 'className' => 'SomethingElse', 'joinTable' => 'join_things', 'conditions' => array('JoinThing.doomed' => true), 'unique' => true ), 'NotDoomedSomethingElse' => array( 'className' => 'SomethingElse', 'joinTable' => 'join_things', 'conditions' => array('JoinThing.doomed' => 0), 'unique' => true ) ) ), false); $result = $Something->read(null, 1); $this->assertTrue(empty($result['NotDoomedSomethingElse'])); $this->assertEquals(1, count($result['DoomedSomethingElse'])); $data = array( 'Something' => array('id' => 1), 'NotDoomedSomethingElse' => array( 'NotDoomedSomethingElse' => array( array('something_else_id' => 2, 'doomed' => 0), array('something_else_id' => 3, 'doomed' => 0) ) ) ); $Something->create($data); $result = $Something->save(); $this->assertFalse(empty($result)); $result = $Something->read(null, 1); $this->assertEquals(2, count($result['NotDoomedSomethingElse'])); $this->assertEquals(1, count($result['DoomedSomethingElse'])); } /** * testHabtmSaveKeyResolution method * * @return void */ public function testHabtmSaveKeyResolution() { $this->loadFixtures('Apple', 'Device', 'ThePaperMonkies'); $ThePaper = new ThePaper(); $ThePaper->id = 1; $ThePaper->save(array('Monkey' => array(2, 3))); $result = $ThePaper->findById(1); $expected = array( array( 'id' => '2', 'device_type_id' => '1', 'name' => 'Device 2', 'typ' => '1' ), array( 'id' => '3', 'device_type_id' => '1', 'name' => 'Device 3', 'typ' => '2' )); $this->assertEquals($expected, $result['Monkey']); $ThePaper->id = 2; $ThePaper->save(array('Monkey' => array(1, 2, 3))); $result = $ThePaper->findById(2); $expected = array( array( 'id' => '1', 'device_type_id' => '1', 'name' => 'Device 1', 'typ' => '1' ), array( 'id' => '2', 'device_type_id' => '1', 'name' => 'Device 2', 'typ' => '1' ), array( 'id' => '3', 'device_type_id' => '1', 'name' => 'Device 3', 'typ' => '2' )); $this->assertEquals($expected, $result['Monkey']); $ThePaper->id = 2; $ThePaper->save(array('Monkey' => array(1, 3))); $result = $ThePaper->findById(2); $expected = array( array( 'id' => '1', 'device_type_id' => '1', 'name' => 'Device 1', 'typ' => '1' ), array( 'id' => '3', 'device_type_id' => '1', 'name' => 'Device 3', 'typ' => '2' )); $this->assertEquals($expected, $result['Monkey']); $result = $ThePaper->findById(1); $expected = array( array( 'id' => '2', 'device_type_id' => '1', 'name' => 'Device 2', 'typ' => '1' ), array( 'id' => '3', 'device_type_id' => '1', 'name' => 'Device 3', 'typ' => '2' )); $this->assertEquals($expected, $result['Monkey']); } /** * testCreationOfEmptyRecord method * * @return void */ public function testCreationOfEmptyRecord() { $this->loadFixtures('Author'); $TestModel = new Author(); $this->assertEquals(4, $TestModel->find('count')); $TestModel->deleteAll(true, false, false); $this->assertEquals(0, $TestModel->find('count')); $result = $TestModel->save(); $this->assertTrue(isset($result['Author']['created'])); $this->assertTrue(isset($result['Author']['updated'])); $this->assertEquals(1, $TestModel->find('count')); } /** * testCreateWithPKFiltering method * * @return void */ public function testCreateWithPKFiltering() { $TestModel = new Article(); $data = array( 'id' => 5, 'user_id' => 2, 'title' => 'My article', 'body' => 'Some text' ); $result = $TestModel->create($data); $expected = array( 'Article' => array( 'published' => 'N', 'id' => 5, 'user_id' => 2, 'title' => 'My article', 'body' => 'Some text' )); $this->assertEquals($expected, $result); $this->assertEquals(5, $TestModel->id); $result = $TestModel->create($data, true); $expected = array( 'Article' => array( 'published' => 'N', 'id' => false, 'user_id' => 2, 'title' => 'My article', 'body' => 'Some text' )); $this->assertEquals($expected, $result); $this->assertFalse($TestModel->id); $result = $TestModel->create(array('Article' => $data), true); $expected = array( 'Article' => array( 'published' => 'N', 'id' => false, 'user_id' => 2, 'title' => 'My article', 'body' => 'Some text' )); $this->assertEquals($expected, $result); $this->assertFalse($TestModel->id); $data = array( 'id' => 6, 'user_id' => 2, 'title' => 'My article', 'body' => 'Some text', 'created' => '1970-01-01 00:00:00', 'updated' => '1970-01-01 12:00:00', 'modified' => '1970-01-01 12:00:00' ); $result = $TestModel->create($data); $expected = array( 'Article' => array( 'published' => 'N', 'id' => 6, 'user_id' => 2, 'title' => 'My article', 'body' => 'Some text', 'created' => '1970-01-01 00:00:00', 'updated' => '1970-01-01 12:00:00', 'modified' => '1970-01-01 12:00:00' )); $this->assertEquals($expected, $result); $this->assertEquals(6, $TestModel->id); $result = $TestModel->create(array( 'Article' => array_diff_key($data, array( 'created' => true, 'updated' => true, 'modified' => true ))), true); $expected = array( 'Article' => array( 'published' => 'N', 'id' => false, 'user_id' => 2, 'title' => 'My article', 'body' => 'Some text' )); $this->assertEquals($expected, $result); $this->assertFalse($TestModel->id); } /** * testCreationWithMultipleData method * * @return void */ public function testCreationWithMultipleData() { $this->loadFixtures('Article', 'Comment'); $Article = new Article(); $Comment = new Comment(); $articles = $Article->find('all', array( 'fields' => array('id', 'title'), 'recursive' => -1, 'order' => array('Article.id' => 'ASC') )); $expected = array( array('Article' => array( 'id' => 1, 'title' => 'First Article' )), array('Article' => array( 'id' => 2, 'title' => 'Second Article' )), array('Article' => array( 'id' => 3, 'title' => 'Third Article' ))); $this->assertEquals($expected, $articles); $comments = $Comment->find('all', array( 'fields' => array('id', 'article_id', 'user_id', 'comment', 'published'), 'recursive' => -1, 'order' => array('Comment.id' => 'ASC') )); $expected = array( array('Comment' => array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y' )), array('Comment' => array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y' )), array('Comment' => array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y' )), array('Comment' => array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N' )), array('Comment' => array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y' )), array('Comment' => array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y' ))); $this->assertEquals($expected, $comments); $data = array( 'Comment' => array( 'article_id' => 2, 'user_id' => 4, 'comment' => 'Brand New Comment', 'published' => 'N' ), 'Article' => array( 'id' => 2, 'title' => 'Second Article Modified' )); $result = $Comment->create($data); $this->assertFalse(empty($result)); $result = $Comment->save(); $this->assertFalse(empty($result)); $articles = $Article->find('all', array( 'fields' => array('id', 'title'), 'recursive' => -1, 'order' => array('Article.id' => 'ASC') )); $expected = array( array('Article' => array( 'id' => 1, 'title' => 'First Article' )), array('Article' => array( 'id' => 2, 'title' => 'Second Article' )), array('Article' => array( 'id' => 3, 'title' => 'Third Article' ))); $this->assertEquals($expected, $articles); $comments = $Comment->find('all', array( 'fields' => array('id', 'article_id', 'user_id', 'comment', 'published'), 'recursive' => -1, 'order' => array('Comment.id' => 'ASC') )); $expected = array( array('Comment' => array( 'id' => 1, 'article_id' => 1, 'user_id' => 2, 'comment' => 'First Comment for First Article', 'published' => 'Y' )), array('Comment' => array( 'id' => 2, 'article_id' => 1, 'user_id' => 4, 'comment' => 'Second Comment for First Article', 'published' => 'Y' )), array('Comment' => array( 'id' => 3, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Third Comment for First Article', 'published' => 'Y' )), array('Comment' => array( 'id' => 4, 'article_id' => 1, 'user_id' => 1, 'comment' => 'Fourth Comment for First Article', 'published' => 'N' )), array('Comment' => array( 'id' => 5, 'article_id' => 2, 'user_id' => 1, 'comment' => 'First Comment for Second Article', 'published' => 'Y' )), array('Comment' => array( 'id' => 6, 'article_id' => 2, 'user_id' => 2, 'comment' => 'Second Comment for Second Article', 'published' => 'Y' )), array('Comment' => array( 'id' => 7, 'article_id' => 2, 'user_id' => 4, 'comment' => 'Brand New Comment', 'published' => 'N' ))); $this->assertEquals($expected, $comments); } /** * testCreationWithMultipleDataSameModel method * * @return void */ public function testCreationWithMultipleDataSameModel() { $this->loadFixtures('Article'); $Article = new Article(); $result = $Article->field('title', array('id' => 1)); $this->assertEquals('First Article', $result); $data = array( 'Article' => array( 'user_id' => 2, 'title' => 'Brand New Article', 'body' => 'Brand New Article Body', 'published' => 'Y' ), 'SecondaryArticle' => array( 'id' => 1 )); $Article->create(); $result = $Article->save($data); $this->assertFalse(empty($result)); $result = $Article->getInsertID(); $this->assertTrue(!empty($result)); $result = $Article->field('title', array('id' => 1)); $this->assertEquals('First Article', $result); $articles = $Article->find('all', array( 'fields' => array('id', 'title'), 'recursive' => -1, 'order' => array('Article.id' => 'ASC') )); $expected = array( array('Article' => array( 'id' => 1, 'title' => 'First Article' )), array('Article' => array( 'id' => 2, 'title' => 'Second Article' )), array('Article' => array( 'id' => 3, 'title' => 'Third Article' )), array('Article' => array( 'id' => 4, 'title' => 'Brand New Article' ))); $this->assertEquals($expected, $articles); } /** * testCreationWithMultipleDataSameModelManualInstances method * * @return void */ public function testCreationWithMultipleDataSameModelManualInstances() { $this->loadFixtures('PrimaryModel'); $Primary = new PrimaryModel(); $result = $Primary->field('primary_name', array('id' => 1)); $this->assertEquals('Primary Name Existing', $result); $data = array( 'PrimaryModel' => array( 'primary_name' => 'Primary Name New' ), 'SecondaryModel' => array( 'id' => array(1) )); $Primary->create(); $result = $Primary->save($data); $this->assertFalse(empty($result)); $result = $Primary->field('primary_name', array('id' => 1)); $this->assertEquals('Primary Name Existing', $result); $result = $Primary->getInsertID(); $this->assertTrue(!empty($result)); $result = $Primary->field('primary_name', array('id' => $result)); $this->assertEquals('Primary Name New', $result); $result = $Primary->find('count'); $this->assertEquals(2, $result); } /** * testRecordExists method * * @return void */ public function testRecordExists() { $this->loadFixtures('User'); $TestModel = new User(); $this->assertFalse($TestModel->exists()); $TestModel->read(null, 1); $this->assertTrue($TestModel->exists()); $TestModel->create(); $this->assertFalse($TestModel->exists()); $TestModel->id = 4; $this->assertTrue($TestModel->exists()); $TestModel = new TheVoid(); $this->assertFalse($TestModel->exists()); $TestModel->id = 5; $this->assertFalse($TestModel->exists()); } /** * testUpdateExisting method * * @return void */ public function testUpdateExisting() { $this->loadFixtures('User', 'Article', 'Comment'); $TestModel = new User(); $TestModel->create(); $TestModel->save(array( 'User' => array( 'user' => 'some user', 'password' => 'some password' ))); $this->assertTrue(is_int($TestModel->id) || ((int)$TestModel->id === 5)); $id = $TestModel->id; $TestModel->save(array( 'User' => array( 'user' => 'updated user' ))); $this->assertEquals($id, $TestModel->id); $result = $TestModel->findById($id); $this->assertEquals('updated user', $result['User']['user']); $this->assertEquals('some password', $result['User']['password']); $Article = new Article(); $Comment = new Comment(); $data = array( 'Comment' => array( 'id' => 1, 'comment' => 'First Comment for First Article' ), 'Article' => array( 'id' => 2, 'title' => 'Second Article' )); $result = $Article->save($data); $this->assertFalse(empty($result)); $result = $Comment->save($data); $this->assertFalse(empty($result)); } /** * test updating records and saving blank values. * * @return void */ public function testUpdateSavingBlankValues() { $this->loadFixtures('Article'); $Article = new Article(); $Article->validate = array(); $Article->create(); $result = $Article->save(array( 'id' => 1, 'title' => '', 'body' => '' )); $this->assertTrue((bool)$result); $result = $Article->find('first', array('conditions' => array('Article.id' => 1))); $this->assertEquals('', $result['Article']['title'], 'Title is not blank'); $this->assertEquals('', $result['Article']['body'], 'Body is not blank'); } /** * testUpdateMultiple method * * @return void */ public function testUpdateMultiple() { $this->loadFixtures('Comment', 'Article', 'User', 'CategoryThread'); $TestModel = new Comment(); $result = Hash::extract($TestModel->find('all'), '{n}.Comment.user_id'); $expected = array('2', '4', '1', '1', '1', '2'); $this->assertEquals($expected, $result); $TestModel->updateAll(array('Comment.user_id' => 5), array('Comment.user_id' => 2)); $result = Hash::combine($TestModel->find('all'), '{n}.Comment.id', '{n}.Comment.user_id'); $expected = array(1 => 5, 2 => 4, 3 => 1, 4 => 1, 5 => 1, 6 => 5); $this->assertEquals($expected, $result); $result = $TestModel->updateAll( array('Comment.comment' => "'Updated today'"), array('Comment.user_id' => 5) ); $this->assertFalse(empty($result)); $result = Hash::extract( $TestModel->find('all', array( 'conditions' => array( 'Comment.user_id' => 5 ))), '{n}.Comment.comment' ); $expected = array_fill(0, 2, 'Updated today'); $this->assertEquals($expected, $result); } /** * testHabtmUuidWithUuidId method * * @return void */ public function testHabtmUuidWithUuidId() { $this->loadFixtures('Uuidportfolio', 'Uuiditem', 'UuiditemsUuidportfolio', 'UuiditemsUuidportfolioNumericid'); $TestModel = new Uuidportfolio(); $data = array('Uuidportfolio' => array('name' => 'Portfolio 3')); $data['Uuiditem']['Uuiditem'] = array('483798c8-c7cc-430e-8cf9-4fcc40cf8569'); $TestModel->create($data); $TestModel->save(); $id = $TestModel->id; $result = $TestModel->read(null, $id); $this->assertEquals(1, count($result['Uuiditem'])); $this->assertEquals(36, strlen($result['Uuiditem'][0]['UuiditemsUuidportfolio']['id'])); } /** * test HABTM saving when join table has no primary key and only 2 columns. * * @return void */ public function testHabtmSavingWithNoPrimaryKeyUuidJoinTable() { $this->loadFixtures('UuidTag', 'Fruit', 'FruitsUuidTag'); $Fruit = new Fruit(); $Fruit->FruitsUuidTag->order = null; $data = array( 'Fruit' => array( 'color' => 'Red', 'shape' => 'Heart-shaped', 'taste' => 'sweet', 'name' => 'Strawberry', ), 'UuidTag' => array( 'UuidTag' => array( '481fc6d0-b920-43e0-e50f-6d1740cf8569' ) ) ); $result = $Fruit->save($data); $this->assertFalse(empty($result)); } /** * test HABTM saving when join table has no primary key and only 2 columns, no with model is used. * * @return void */ public function testHabtmSavingWithNoPrimaryKeyUuidJoinTableNoWith() { $this->loadFixtures('UuidTag', 'Fruit', 'FruitsUuidTag'); $Fruit = new FruitNoWith(); $data = array( 'Fruit' => array( 'color' => 'Red', 'shape' => 'Heart-shaped', 'taste' => 'sweet', 'name' => 'Strawberry', ), 'UuidTag' => array( 'UuidTag' => array( '481fc6d0-b920-43e0-e50f-6d1740cf8569' ) ) ); $result = $Fruit->save($data); $this->assertFalse(empty($result)); } /** * testHabtmUuidWithNumericId method * * @return void */ public function testHabtmUuidWithNumericId() { $this->loadFixtures('Uuidportfolio', 'Uuiditem', 'UuiditemsUuidportfolioNumericid'); $TestModel = new Uuiditem(); $data = array('Uuiditem' => array('name' => 'Item 7', 'published' => 0)); $data['Uuidportfolio']['Uuidportfolio'] = array('480af662-eb8c-47d3-886b-230540cf8569'); $TestModel->create($data); $TestModel->save(); $id = $TestModel->id; $result = $TestModel->read(null, $id); $this->assertEquals(1, count($result['Uuidportfolio'])); } /** * testSaveMultipleHabtm method * * @return void */ public function testSaveMultipleHabtm() { $this->loadFixtures('JoinA', 'JoinB', 'JoinC', 'JoinAB', 'JoinAC'); $TestModel = new JoinA(); $result = $TestModel->findById(1); $expected = array( 'JoinA' => array( 'id' => 1, 'name' => 'Join A 1', 'body' => 'Join A 1 Body', 'created' => '2008-01-03 10:54:23', 'updated' => '2008-01-03 10:54:23' ), 'JoinB' => array( 0 => array( 'id' => 2, 'name' => 'Join B 2', 'created' => '2008-01-03 10:55:02', 'updated' => '2008-01-03 10:55:02', 'JoinAsJoinB' => array( 'id' => 1, 'join_a_id' => 1, 'join_b_id' => 2, 'other' => 'Data for Join A 1 Join B 2', 'created' => '2008-01-03 10:56:33', 'updated' => '2008-01-03 10:56:33' ))), 'JoinC' => array( 0 => array( 'id' => 2, 'name' => 'Join C 2', 'created' => '2008-01-03 10:56:12', 'updated' => '2008-01-03 10:56:12', 'JoinAsJoinC' => array( 'id' => 1, 'join_a_id' => 1, 'join_c_id' => 2, 'other' => 'Data for Join A 1 Join C 2', 'created' => '2008-01-03 10:57:22', 'updated' => '2008-01-03 10:57:22' )))); $this->assertEquals($expected, $result); $TestModel->id = 1; $data = array( 'JoinA' => array( 'id' => '1', 'name' => 'New name for Join A 1', 'updated' => static::date() ), 'JoinB' => array( array( 'id' => 1, 'join_b_id' => 2, 'other' => 'New data for Join A 1 Join B 2', 'created' => static::date(), 'updated' => static::date() )), 'JoinC' => array( array( 'id' => 1, 'join_c_id' => 2, 'other' => 'New data for Join A 1 Join C 2', 'created' => static::date(), 'updated' => static::date() ))); $TestModel->set($data); $TestModel->save(); $result = $TestModel->findById(1); $expected = array( 'JoinA' => array( 'id' => 1, 'name' => 'New name for Join A 1', 'body' => 'Join A 1 Body', 'created' => '2008-01-03 10:54:23', 'updated' => static::date() ), 'JoinB' => array( 0 => array( 'id' => 2, 'name' => 'Join B 2', 'created' => '2008-01-03 10:55:02', 'updated' => '2008-01-03 10:55:02', 'JoinAsJoinB' => array( 'id' => 1, 'join_a_id' => 1, 'join_b_id' => 2, 'other' => 'New data for Join A 1 Join B 2', 'created' => static::date(), 'updated' => static::date() ))), 'JoinC' => array( 0 => array( 'id' => 2, 'name' => 'Join C 2', 'created' => '2008-01-03 10:56:12', 'updated' => '2008-01-03 10:56:12', 'JoinAsJoinC' => array( 'id' => 1, 'join_a_id' => 1, 'join_c_id' => 2, 'other' => 'New data for Join A 1 Join C 2', 'created' => static::date(), 'updated' => static::date() )))); $this->assertEquals($expected, $result); } /** * testSaveAll method * * @return void */ public function testSaveAll() { $this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User'); $TestModel = new Post(); $result = $TestModel->find('all'); $this->assertEquals(3, count($result)); $this->assertFalse(isset($result[3])); $TestModel->saveAll(array( 'Post' => array( 'title' => 'Post with Author', 'body' => 'This post will be saved with an author' ), 'Author' => array( 'user' => 'bob', 'password' => '5f4dcc3b5aa765d61d8327deb882cf90' ))); $result = $TestModel->find('all'); $expected = array( 'Post' => array( 'id' => '4', 'author_id' => '5', 'title' => 'Post with Author', 'body' => 'This post will be saved with an author', 'published' => 'N' ), 'Author' => array( 'id' => '5', 'user' => 'bob', 'password' => '5f4dcc3b5aa765d61d8327deb882cf90', 'test' => 'working' )); $this->assertEquals(static::date(), $result[3]['Post']['created']); $this->assertEquals(static::date(), $result[3]['Post']['updated']); $this->assertEquals(static::date(), $result[3]['Author']['created']); $this->assertEquals(static::date(), $result[3]['Author']['updated']); unset($result[3]['Post']['created'], $result[3]['Post']['updated']); unset($result[3]['Author']['created'], $result[3]['Author']['updated']); $this->assertEquals($expected, $result[3]); $this->assertEquals(4, count($result)); $TestModel->deleteAll(true); $this->assertEquals(array(), $TestModel->find('all')); // SQLite seems to reset the PK counter when that happens, so we need this to make the tests pass $this->db->truncate($TestModel); $TestModel->saveAll(array( array( 'title' => 'Multi-record post 1', 'body' => 'First multi-record post', 'author_id' => 2 ), array( 'title' => 'Multi-record post 2', 'body' => 'Second multi-record post', 'author_id' => 2 ))); $result = $TestModel->find('all', array( 'recursive' => -1, 'order' => 'Post.id ASC' )); $expected = array( array( 'Post' => array( 'id' => '1', 'author_id' => '2', 'title' => 'Multi-record post 1', 'body' => 'First multi-record post', 'published' => 'N' )), array( 'Post' => array( 'id' => '2', 'author_id' => '2', 'title' => 'Multi-record post 2', 'body' => 'Second multi-record post', 'published' => 'N' ))); $this->assertEquals(static::date(), $result[0]['Post']['created']); $this->assertEquals(static::date(), $result[0]['Post']['updated']); $this->assertEquals(static::date(), $result[1]['Post']['created']); $this->assertEquals(static::date(), $result[1]['Post']['updated']); unset($result[0]['Post']['created'], $result[0]['Post']['updated']); unset($result[1]['Post']['created'], $result[1]['Post']['updated']); $this->assertEquals($expected, $result); $TestModel = new Comment(); $result = $TestModel->saveAll(array( 'Comment' => array( 'article_id' => 2, 'user_id' => 2, 'comment' => 'New comment with attachment', 'published' => 'Y' ), 'Attachment' => array( 'attachment' => 'some_file.tgz' ))); $this->assertFalse(empty($result)); $result = $TestModel->find('all'); $expected = array( 'id' => '7', 'article_id' => '2', 'user_id' => '2', 'comment' => 'New comment with attachment', 'published' => 'Y' ); $this->assertEquals(static::date(), $result[6]['Comment']['created']); $this->assertEquals(static::date(), $result[6]['Comment']['updated']); unset($result[6]['Comment']['created'], $result[6]['Comment']['updated']); $this->assertEquals($expected, $result[6]['Comment']); $expected = array( 'id' => '2', 'comment_id' => '7', 'attachment' => 'some_file.tgz' ); $this->assertEquals(static::date(), $result[6]['Attachment']['created']); $this->assertEquals(static::date(), $result[6]['Attachment']['updated']); unset($result[6]['Attachment']['created'], $result[6]['Attachment']['updated']); $this->assertEquals($expected, $result[6]['Attachment']); } /** * Test SaveAll with Habtm relations * * @return void */ public function testSaveAllHabtm() { $this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag'); $data = array( 'Article' => array( 'user_id' => 1, 'title' => 'Article Has and belongs to Many Tags' ), 'Tag' => array( 'Tag' => array(1, 2) ), 'Comment' => array( array( 'comment' => 'Article comment', 'user_id' => 1 ))); $Article = new Article(); $result = $Article->saveAll($data); $this->assertFalse(empty($result)); $result = $Article->read(); $this->assertEquals(2, count($result['Tag'])); $this->assertEquals('tag1', $result['Tag'][0]['tag']); $this->assertEquals(1, count($result['Comment'])); $this->assertEquals(1, count($result['Comment'][0]['comment'])); } /** * Test SaveAll with Habtm relations and extra join table fields * * @return void */ public function testSaveAllHabtmWithExtraJoinTableFields() { $this->loadFixtures('Something', 'SomethingElse', 'JoinThing'); $data = array( 'Something' => array( 'id' => 4, 'title' => 'Extra Fields', 'body' => 'Extra Fields Body', 'published' => '1' ), 'SomethingElse' => array( array('something_else_id' => 1, 'doomed' => '1'), array('something_else_id' => 2, 'doomed' => '0'), array('something_else_id' => 3, 'doomed' => '1') ) ); $Something = new Something(); $result = $Something->saveAll($data); $this->assertFalse(empty($result)); $result = $Something->read(); $this->assertEquals(3, count($result['SomethingElse'])); $this->assertTrue(Set::matches('/Something[id=4]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=1]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[something_else_id=1]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[doomed=1]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=2]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[something_else_id=2]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[doomed=0]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=3]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[something_else_id=3]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[doomed=1]', $result)); } /** * testSaveAllHasOne method * * @return void */ public function testSaveAllHasOne() { $model = new Comment(); $model->deleteAll(true); $this->assertEquals(array(), $model->find('all')); $model->Attachment->deleteAll(true); $this->assertEquals(array(), $model->Attachment->find('all')); $this->assertTrue($model->saveAll(array( 'Comment' => array( 'comment' => 'Comment with attachment', 'article_id' => 1, 'user_id' => 1 ), 'Attachment' => array( 'attachment' => 'some_file.zip' )))); $result = $model->find('all', array('fields' => array( 'Comment.id', 'Comment.comment', 'Attachment.id', 'Attachment.comment_id', 'Attachment.attachment' ))); $expected = array(array( 'Comment' => array( 'id' => '1', 'comment' => 'Comment with attachment' ), 'Attachment' => array( 'id' => '1', 'comment_id' => '1', 'attachment' => 'some_file.zip' ))); $this->assertEquals($expected, $result); $model->Attachment->bindModel(array('belongsTo' => array('Comment')), false); $data = array( 'Comment' => array( 'comment' => 'Comment with attachment', 'article_id' => 1, 'user_id' => 1 ), 'Attachment' => array( 'attachment' => 'some_file.zip' )); $this->assertTrue($model->saveAll($data, array('validate' => 'first'))); } /** * testSaveAllBelongsTo method * * @return void */ public function testSaveAllBelongsTo() { $model = new Comment(); $model->deleteAll(true); $this->assertEquals(array(), $model->find('all')); $model->Article->deleteAll(true); $this->assertEquals(array(), $model->Article->find('all')); $this->assertTrue($model->saveAll(array( 'Comment' => array( 'comment' => 'Article comment', 'article_id' => 1, 'user_id' => 1 ), 'Article' => array( 'title' => 'Model Associations 101', 'user_id' => 1 )))); $result = $model->find('all', array('fields' => array( 'Comment.id', 'Comment.comment', 'Comment.article_id', 'Article.id', 'Article.title' ))); $expected = array(array( 'Comment' => array( 'id' => '1', 'article_id' => '1', 'comment' => 'Article comment' ), 'Article' => array( 'id' => '1', 'title' => 'Model Associations 101' ))); $this->assertEquals($expected, $result); } /** * testSaveAllHasOneValidation method * * @return void */ public function testSaveAllHasOneValidation() { $model = new Comment(); $model->deleteAll(true); $this->assertEquals(array(), $model->find('all')); $model->Attachment->deleteAll(true); $this->assertEquals(array(), $model->Attachment->find('all')); $model->validate = array('comment' => 'notBlank'); $model->Attachment->validate = array('attachment' => 'notBlank'); $model->Attachment->bindModel(array('belongsTo' => array('Comment'))); $result = $model->saveAll( array( 'Comment' => array( 'comment' => '', 'article_id' => 1, 'user_id' => 1 ), 'Attachment' => array('attachment' => '') ), array('validate' => 'first') ); $this->assertEquals(false, $result); $expected = array( 'comment' => array('This field cannot be left blank'), 'Attachment' => array( 'attachment' => array('This field cannot be left blank') ) ); $this->assertEquals($expected, $model->validationErrors); $this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors); } /** * testSaveAllAtomic method * * @return void */ public function testSaveAllAtomic() { $this->loadFixtures('Article', 'User', 'Comment'); $TestModel = new Article(); $result = $TestModel->saveAll(array( 'Article' => array( 'title' => 'Post with Author', 'body' => 'This post will be saved with an author', 'user_id' => 2 ), 'Comment' => array( array('comment' => 'First new comment', 'user_id' => 2)) ), array('atomic' => false)); $this->assertSame($result, array('Article' => true, 'Comment' => array(true))); $result = $TestModel->saveAll(array( array( 'id' => '1', 'title' => 'Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N' ), array( 'id' => '2', 'title' => 'Just update the title' ), array( 'title' => 'Creating a fourth post', 'body' => 'Fourth post body', 'user_id' => 2 ) ), array('atomic' => false)); $this->assertSame($result, array(true, true, true)); $result = $TestModel->saveAll(array( 'Article' => array('id' => 2), 'Comment' => array( array( 'comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1 ), array( 'comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2 )) ), array('validate' => true, 'atomic' => false)); $this->assertSame($result, array('Article' => true, 'Comment' => array(true, true))); $TestModel->validate = array( 'title' => 'notBlank', 'author_id' => 'numeric' ); $result = $TestModel->saveAll(array( array( 'id' => '1', 'title' => 'Un-Baleeted First Post', 'body' => 'Not Baleeted!', 'published' => 'Y' ), array( 'id' => '2', 'title' => '', 'body' => 'Trying to get away with an empty title' ) ), array('validate' => true, 'atomic' => false)); $this->assertSame(array(true, false), $result); } /** * 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' ); $result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment'); $this->assertEquals($expected, $result); $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' ); $result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment'); $this->assertEquals($expected, $result); $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($expected['Comment'], $result['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($expected, $result); } /** * 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( '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); $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'] = 'notBlank'; $result = $TestModel->saveAll($data, array('deep' => true)); $this->assertFalse($result); $expected = array( 0 => array( 'body' => array('This field cannot be left blank'), 'Comment' => array( 0 => array( 'comment' => array('This field cannot be left blank'), 'User' => array( 'user' => 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); } /** * 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'] = 'notBlank'; $TestModel->Comment->validate['comment'] = 'notBlank'; $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'), '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']['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'), 'Article' => array( 'body' => array('This field cannot be left blank'), '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['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'), 'Comment' => array( 'comment' => array('This field cannot be left blank'), 'Article' => array( 'body' => array('This field cannot be left blank'), 'User' => array( 'user' => 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'), 'Article' => array( 'body' => array('This field cannot be left blank'), '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' => 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'] = 'notBlank'; $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), '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'] = 'notBlank'; $TestModel->Comment->validate['comment'] = 'notBlank'; $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 * * @return void */ public function testSaveAllHasMany() { $this->loadFixtures('Article', 'Comment'); $TestModel = new Article(); $TestModel->hasMany['Comment']['order'] = array('Comment.created' => 'ASC'); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array(); $result = $TestModel->saveAll(array( 'Article' => array('id' => 2), 'Comment' => array( array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1), array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2) ) )); $this->assertFalse(empty($result)); $result = $TestModel->findById(2); $expected = array( 'First Comment for Second Article', 'Second Comment for Second Article', 'First new comment', 'Second new comment' ); $result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment'); $this->assertEquals($expected, $result); $result = $TestModel->saveAll( array( 'Article' => array('id' => 2), 'Comment' => array( array( 'comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 1 ))), array('atomic' => false) ); $this->assertFalse(empty($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' ); $result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment'); $this->assertEquals($expected, $result); $TestModel->beforeSaveReturn = false; $result = $TestModel->saveAll( array( 'Article' => array('id' => 2), 'Comment' => array( array( 'comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 1 ))), array('atomic' => false) ); $this->assertEquals(array('Article' => false), $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' ); $result = Hash::extract(Hash::sort($result['Comment'], '{n}.id', 'ASC'), '{n}.comment'); $this->assertEquals($expected, $result); } /** * testSaveAllHasManyValidation method * * @return void */ public function testSaveAllHasManyValidation() { $this->loadFixtures('Article', 'Comment'); $TestModel = new Article(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array(); $TestModel->Comment->validate = array('comment' => 'notBlank'); $result = $TestModel->saveAll(array( 'Article' => array('id' => 2), 'Comment' => array( array('comment' => '', 'published' => 'Y', 'user_id' => 1), ) ), array('validate' => true)); $this->assertFalse($result); $expected = array('Comment' => array( array('comment' => array('This field cannot be left blank')) )); $this->assertEquals($expected, $TestModel->validationErrors); $expected = array( array('comment' => array('This field cannot be left blank')) ); $this->assertEquals($expected, $TestModel->Comment->validationErrors); $result = $TestModel->saveAll(array( 'Article' => array('id' => 2), 'Comment' => array( array( 'comment' => '', 'published' => 'Y', 'user_id' => 1 )) ), array('validate' => 'first')); $this->assertFalse($result); } /** * test saveAll with transactions and ensure there is no missing rollback. * * @return void */ public function testSaveAllManyRowsTransactionNoRollback() { $this->loadFixtures('Post'); $Post = new TestPost(); $Post->validate = array( 'title' => array('rule' => array('notBlank')) ); // If validation error occurs, rollback() should be called. $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->once())->method('begin')->will($this->returnValue(true)); $db->expects($this->never())->method('commit'); $db->expects($this->once())->method('rollback'); $Post->setDataSourceObject($db); $data = array( array('author_id' => 1, 'title' => 'New Fourth Post'), array('author_id' => 1, 'title' => '') ); $Post->saveAll($data, array('atomic' => true, 'validate' => true)); // If exception thrown, rollback() should be called too. $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->once())->method('begin')->will($this->returnValue(true)); $db->expects($this->never())->method('commit'); $db->expects($this->once())->method('rollback'); $Post->setDataSourceObject($db); $data = array( array('author_id' => 1, 'title' => 'New Fourth Post'), array('author_id' => 1, 'title' => 'New Fifth Post', 'body' => $db->expression('PDO_EXCEPTION()')) ); try { $Post->saveAll($data, array('atomic' => true, 'validate' => true)); $this->fail('No exception thrown'); } catch (PDOException $e) { } // Otherwise, commit() should be called. $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->once())->method('begin')->will($this->returnValue(true)); $db->expects($this->once())->method('commit'); $db->expects($this->never())->method('rollback'); $Post->setDataSourceObject($db); $data = array( array('author_id' => 1, 'title' => 'New Fourth Post'), array('author_id' => 1, 'title' => 'New Fifth Post') ); $Post->saveAll($data, array('atomic' => true, 'validate' => true)); } /** * test saveAll with transactions and ensure there is no missing rollback. * * @return void */ public function testSaveAllAssociatedTransactionNoRollback() { $this->loadFixtures('Post', 'Author'); $Post = new TestPost(); $Post->Author->validate = array( 'user' => array('rule' => array('notBlank')) ); // If validation error occurs, rollback() should be called. $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->once())->method('begin')->will($this->returnValue(true)); $db->expects($this->never())->method('commit'); $db->expects($this->once())->method('rollback'); $Post->setDataSourceObject($db); $Post->Author->setDataSourceObject($db); $data = array( 'Post' => array( 'title' => 'New post', 'body' => 'Content', 'published' => 'Y' ), 'Author' => array( 'user' => '', 'password' => "sekret" ) ); $Post->saveAll($data, array('validate' => true)); // If exception thrown, rollback() should be called too. $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->once())->method('begin')->will($this->returnValue(true)); $db->expects($this->never())->method('commit'); $db->expects($this->once())->method('rollback'); $Post->setDataSourceObject($db); $Post->Author->setDataSourceObject($db); $data = array( 'Post' => array( 'title' => 'New post', 'body' => $db->expression('PDO_EXCEPTION()'), 'published' => 'Y' ), 'Author' => array( 'user' => 'New user', 'password' => "sekret" ) ); try { $Post->saveAll($data, array('validate' => true)); $this->fail('No exception thrown'); } catch (PDOException $e) { } // Otherwise, commit() should be called. $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->once())->method('begin')->will($this->returnValue(true)); $db->expects($this->once())->method('commit'); $db->expects($this->never())->method('rollback'); $Post->setDataSourceObject($db); $Post->Author->setDataSourceObject($db); $data = array( 'Post' => array( 'title' => 'New post', 'body' => 'Content', 'published' => 'Y' ), 'Author' => array( 'user' => 'New user', 'password' => "sekret" ) ); $Post->saveAll($data, array('validate' => true)); } /** * test saveAll with nested saveAll call. * * @return void */ public function testSaveAllNestedSaveAll() { $this->loadFixtures('Sample'); $TransactionTestModel = new TransactionTestModel(); $data = array( array('apple_id' => 1, 'name' => 'sample5'), ); $this->assertTrue($TransactionTestModel->saveAll($data, array('atomic' => true))); } /** * testSaveAllTransaction method * * @return void */ public function testSaveAllTransaction() { $this->loadFixtures('Post', 'Author', 'Comment', 'Attachment'); $TestModel = new Post(); $TestModel->validate = array('title' => 'notBlank'); $data = array( array('author_id' => 1, 'title' => 'New Fourth Post'), array('author_id' => 1, 'title' => 'New Fifth Post'), array('author_id' => 1, 'title' => '') ); $this->assertFalse($TestModel->saveAll($data)); $result = $TestModel->find('all', array('recursive' => -1)); $expected = array( array('Post' => array( 'id' => '1', 'author_id' => 1, 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' )), array('Post' => array( 'id' => '2', 'author_id' => 3, 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' )), array('Post' => array( 'id' => '3', 'author_id' => 1, 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ))); if (count($result) != 3) { // Database doesn't support transactions $expected[] = array( 'Post' => array( 'id' => '4', 'author_id' => 1, 'title' => 'New Fourth Post', 'body' => null, 'published' => 'N', 'created' => static::date(), 'updated' => static::date() )); $expected[] = array( 'Post' => array( 'id' => '5', 'author_id' => 1, 'title' => 'New Fifth Post', 'body' => null, 'published' => 'N', 'created' => static::date(), 'updated' => static::date() )); $this->assertEquals($expected, $result); // Skip the rest of the transactional tests return; } $this->assertEquals($expected, $result); $data = array( array('author_id' => 1, 'title' => 'New Fourth Post'), array('author_id' => 1, 'title' => ''), array('author_id' => 1, 'title' => 'New Sixth Post') ); $this->assertFalse($TestModel->saveAll($data)); $result = $TestModel->find('all', array('recursive' => -1)); $expected = array( array('Post' => array( 'id' => '1', 'author_id' => 1, 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' )), array('Post' => array( 'id' => '2', 'author_id' => 3, 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' )), array('Post' => array( 'id' => '3', 'author_id' => 1, 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ))); if (count($result) != 3) { // Database doesn't support transactions $expected[] = array( 'Post' => array( 'id' => '4', 'author_id' => 1, 'title' => 'New Fourth Post', 'body' => 'Third Post Body', 'published' => 'N', 'created' => static::date(), 'updated' => static::date() )); $expected[] = array( 'Post' => array( 'id' => '5', 'author_id' => 1, 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'N', 'created' => static::date(), 'updated' => static::date() )); } $this->assertEquals($expected, $result); $TestModel->validate = array('title' => 'notBlank'); $data = array( array('author_id' => 1, 'title' => 'New Fourth Post'), array('author_id' => 1, 'title' => 'New Fifth Post'), array('author_id' => 1, 'title' => 'New Sixth Post') ); $this->assertTrue($TestModel->saveAll($data)); $result = $TestModel->find('all', array( 'recursive' => -1, 'fields' => array('author_id', 'title', 'body', 'published'), 'order' => array('Post.created' => 'ASC') )); $expected = array( array('Post' => array( 'author_id' => 1, 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y' )), array('Post' => array( 'author_id' => 3, 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y' )), array('Post' => array( 'author_id' => 1, 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y' )), array('Post' => array( 'author_id' => 1, 'title' => 'New Fourth Post', 'body' => '', 'published' => 'N' )), array('Post' => array( 'author_id' => 1, 'title' => 'New Fifth Post', 'body' => '', 'published' => 'N' )), array('Post' => array( 'author_id' => 1, 'title' => 'New Sixth Post', 'body' => '', 'published' => 'N' ))); $this->assertEquals($expected, $result); } /** * testSaveAllValidation method * * @return void */ public function testSaveAllValidation() { $this->loadFixtures('Post', 'Author', 'Comment', 'Attachment'); $TestModel = new Post(); $data = array( array( 'id' => '1', 'title' => 'Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N' ), array( 'id' => '2', 'title' => 'Just update the title' ), array( 'title' => 'Creating a fourth post', 'body' => 'Fourth post body', 'author_id' => 2 )); $this->assertTrue($TestModel->saveAll($data)); $result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC')); $expected = array( array( 'Post' => array( 'id' => '1', 'author_id' => '1', 'title' => 'Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N', 'created' => '2007-03-18 10:39:23' )), array( 'Post' => array( 'id' => '2', 'author_id' => '3', 'title' => 'Just update the title', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23' )), array( 'Post' => array( 'id' => '3', 'author_id' => '1', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' )), array( 'Post' => array( 'id' => '4', 'author_id' => '2', 'title' => 'Creating a fourth post', 'body' => 'Fourth post body', 'published' => 'N' ))); $this->assertEquals(static::date(), $result[0]['Post']['updated']); $this->assertEquals(static::date(), $result[1]['Post']['updated']); $this->assertEquals(static::date(), $result[3]['Post']['created']); $this->assertEquals(static::date(), $result[3]['Post']['updated']); unset($result[0]['Post']['updated'], $result[1]['Post']['updated']); unset($result[3]['Post']['created'], $result[3]['Post']['updated']); $this->assertEquals($expected, $result); $TestModel->validate = array('title' => 'notBlank', 'author_id' => 'numeric'); $data = array( array( 'id' => '1', 'title' => 'Un-Baleeted First Post', 'body' => 'Not Baleeted!', 'published' => 'Y' ), array( 'id' => '2', 'title' => '', 'body' => 'Trying to get away with an empty title' )); $result = $TestModel->saveAll($data); $this->assertFalse($result); $result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC')); $errors = array(1 => array('title' => array('This field cannot be left blank'))); $transactionWorked = Set::matches('/Post[1][title=Baleeted First Post]', $result); if (!$transactionWorked) { $this->assertTrue(Set::matches('/Post[1][title=Un-Baleeted First Post]', $result)); $this->assertTrue(Set::matches('/Post[2][title=Just update the title]', $result)); } $this->assertEquals($errors, $TestModel->validationErrors); $TestModel->validate = array('title' => 'notBlank', 'author_id' => 'numeric'); $data = array( array( 'id' => '1', 'title' => 'Un-Baleeted First Post', 'body' => 'Not Baleeted!', 'published' => 'Y' ), array( 'id' => '2', 'title' => '', 'body' => 'Trying to get away with an empty title' )); $result = $TestModel->saveAll($data, array('validate' => true, 'atomic' => false)); $this->assertEquals(array(true, false), $result); $result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC')); $errors = array(1 => array('title' => array('This field cannot be left blank'))); $expected = array( array( 'Post' => array( 'id' => '1', 'author_id' => '1', 'title' => 'Un-Baleeted First Post', 'body' => 'Not Baleeted!', 'published' => 'Y', 'created' => '2007-03-18 10:39:23' ) ), array( 'Post' => array( 'id' => '2', 'author_id' => '3', 'title' => 'Just update the title', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23' ) ), array( 'Post' => array( 'id' => '3', 'author_id' => '1', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ) ), array( 'Post' => array( 'id' => '4', 'author_id' => '2', 'title' => 'Creating a fourth post', 'body' => 'Fourth post body', 'published' => 'N' ) ) ); $this->assertEquals(static::date(), $result[0]['Post']['updated']); $this->assertEquals(static::date(), $result[1]['Post']['updated']); $this->assertEquals(static::date(), $result[3]['Post']['updated']); $this->assertEquals(static::date(), $result[3]['Post']['created']); unset( $result[0]['Post']['updated'], $result[1]['Post']['updated'], $result[3]['Post']['updated'], $result[3]['Post']['created'] ); $this->assertEquals($expected, $result); $this->assertEquals($errors, $TestModel->validationErrors); $data = array( array( 'id' => '1', 'title' => 'Re-Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N' ), array( 'id' => '2', 'title' => '', 'body' => 'Trying to get away with an empty title' )); $this->assertFalse($TestModel->saveAll($data, array('validate' => 'first'))); $result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC')); unset( $result[0]['Post']['updated'], $result[1]['Post']['updated'], $result[3]['Post']['updated'], $result[3]['Post']['created'] ); $this->assertEquals($expected, $result); $this->assertEquals($errors, $TestModel->validationErrors); } /** * testSaveAllValidationOnly method * * @return void */ public function testSaveAllValidationOnly() { $this->loadFixtures('Comment', 'Attachment'); $TestModel = new Comment(); $TestModel->Attachment->validate = array('attachment' => 'notBlank'); $data = array( 'Comment' => array( 'comment' => 'This is the comment' ), 'Attachment' => array( 'attachment' => '' ) ); $result = $TestModel->saveAll($data, array('validate' => 'only')); $this->assertFalse($result); $TestModel = new Article(); $TestModel->validate = array('title' => 'notBlank'); $result = $TestModel->saveAll( array( 0 => array('title' => ''), 1 => array('title' => 'title 1'), 2 => array('title' => 'title 2'), ), array('validate' => 'only') ); $this->assertFalse($result); $expected = array( 0 => array('title' => array('This field cannot be left blank')), ); $this->assertEquals($expected, $TestModel->validationErrors); $result = $TestModel->saveAll( array( 0 => array('title' => 'title 0'), 1 => array('title' => ''), 2 => array('title' => 'title 2'), ), array('validate' => 'only') ); $this->assertFalse($result); $expected = array( 1 => array('title' => array('This field cannot be left blank')), ); $this->assertEquals($expected, $TestModel->validationErrors); } /** * testSaveAllValidateFirst method * * @return void */ public function testSaveAllValidateFirst() { $this->loadFixtures('Article', 'Comment', 'Attachment', 'User', 'ArticlesTag', 'Tag'); $model = new Article(); $model->deleteAll(true); $model->Comment->validate = array('comment' => 'notBlank'); $result = $model->saveAll(array( 'Article' => array( 'title' => 'Post with Author', 'body' => 'This post will be saved author' ), 'Comment' => array( array('comment' => 'First new comment'), array('comment' => '') ) ), array('validate' => 'first')); $this->assertFalse($result); $result = $model->find('all'); $this->assertSame(array(), $result); $expected = array('Comment' => array( 1 => array('comment' => array('This field cannot be left blank')) )); $this->assertEquals($expected['Comment'], $model->Comment->validationErrors); $this->assertSame($model->Comment->find('count'), 0); $result = $model->saveAll( array( 'Article' => array( 'title' => 'Post with Author', 'body' => 'This post will be saved with an author', 'user_id' => 2 ), 'Comment' => array( array( 'comment' => 'Only new comment', 'user_id' => 2 ))), array('validate' => 'first') ); $this->assertTrue($result); $result = $model->Comment->find('all'); $this->assertSame(count($result), 1); $result = Hash::extract($result, '{n}.Comment.article_id'); $this->assertEquals(4, $result[0]); $model->deleteAll(true); $data = array( 'Article' => array( 'title' => 'Post with Author saveAlled from comment', 'body' => 'This post will be saved with an author', 'user_id' => 2 ), 'Comment' => array( 'comment' => 'Only new comment', 'user_id' => 2 )); $result = $model->Comment->saveAll($data, array('validate' => 'first')); $this->assertFalse(empty($result)); $result = $model->find('all'); $this->assertEquals( $result[0]['Article']['title'], 'Post with Author saveAlled from comment' ); $this->assertEquals('Only new comment', $result[0]['Comment'][0]['comment']); } /** * test saveAll()'s return is correct when using atomic = false and validate = first. * * @return void */ public function testSaveAllValidateFirstAtomicFalse() { $this->loadFixtures('Something'); $Something = new Something(); $invalidData = array( array( 'title' => 'foo', 'body' => 'bar', 'published' => 'baz', ), array( 'body' => 3, 'published' => 'sd', ), ); $Something->create(); $Something->validate = array( 'title' => array( 'rule' => 'alphaNumeric', 'required' => true, ), 'body' => array( 'rule' => 'alphaNumeric', 'required' => true, 'allowEmpty' => true, ), ); $result = $Something->saveAll($invalidData, array( 'atomic' => false, 'validate' => 'first', )); $expected = array(true, false); $this->assertEquals($expected, $result); $Something = new Something(); $validData = array( array( 'title' => 'title value', 'body' => 'body value', 'published' => 'baz', ), array( 'title' => 'valid', 'body' => 'this body', 'published' => 'sd', ), ); $Something->create(); $result = $Something->saveAll($validData, array( 'atomic' => false, 'validate' => 'first', )); $expected = array(true, true); $this->assertEquals($expected, $result); } /** * testSaveAllHasManyValidationOnly method * * @return void */ public function testSaveAllHasManyValidationOnly() { $this->loadFixtures('Article', 'Comment', 'Attachment'); $TestModel = new Article(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array(); $TestModel->Comment->validate = array('comment' => 'notBlank'); $result = $TestModel->saveAll( array( 'Article' => array('id' => 2), 'Comment' => array( array( 'id' => 1, 'comment' => '', 'published' => 'Y', 'user_id' => 1), array( 'id' => 2, 'comment' => 'comment', 'published' => 'Y', 'user_id' => 1 ))), array('validate' => 'only') ); $this->assertFalse($result); $result = $TestModel->saveAll( array( 'Article' => array('id' => 2), 'Comment' => array( array( 'id' => 1, 'comment' => '', 'published' => 'Y', 'user_id' => 1 ), array( 'id' => 2, 'comment' => 'comment', 'published' => 'Y', 'user_id' => 1 ), array( 'id' => 3, 'comment' => '', 'published' => 'Y', 'user_id' => 1 ))), array( 'validate' => 'only', 'atomic' => false )); $expected = array( 'Article' => true, 'Comment' => array(false, true, false) ); $this->assertSame($expected, $result); $expected = array('Comment' => array( 0 => array('comment' => array('This field cannot be left blank')), 2 => array('comment' => array('This field cannot be left blank')) )); $this->assertEquals($expected, $TestModel->validationErrors); $expected = array( 0 => array('comment' => array('This field cannot be left blank')), 2 => array('comment' => array('This field cannot be left blank')) ); $this->assertEquals($expected, $TestModel->Comment->validationErrors); } /** * test that saveAll still behaves like previous versions (does not necessarily need a first argument) * * @return void */ public function testSaveAllWithSet() { $this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag'); $data = array( 'Article' => array( 'user_id' => 1, 'title' => 'Article Has and belongs to Many Tags' ), 'Tag' => array( 'Tag' => array(1, 2) ), 'Comment' => array( array( 'comment' => 'Article comment', 'user_id' => 1 ))); $Article = new Article(); $Article->set($data); $result = $Article->saveAll(); $this->assertFalse(empty($result)); } /** * test that saveAll behaves like plain save() when supplied empty data * * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data * @return void */ public function testSaveAllEmptyData() { $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.'); $this->loadFixtures('Article', 'ProductUpdateAll', 'Comment', 'Attachment'); $model = new Article(); $result = $model->saveAll(array(), array('validate' => 'first')); $this->assertFalse(empty($result)); $model = new ProductUpdateAll(); $result = $model->saveAll(); $this->assertFalse($result); } /** * testSaveAssociated method * * @return void */ public function testSaveAssociated() { $this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User'); $TestModel = new Post(); $result = $TestModel->find('all'); $this->assertEquals(3, count($result)); $this->assertFalse(isset($result[3])); $TestModel->saveAssociated(array( 'Post' => array( 'title' => 'Post with Author', 'body' => 'This post will be saved with an author' ), 'Author' => array( 'user' => 'bob', 'password' => '5f4dcc3b5aa765d61d8327deb882cf90' ))); $result = $TestModel->find('all', array('order' => array('Post.id ' => 'ASC'))); $expected = array( 'Post' => array( 'id' => '4', 'author_id' => '5', 'title' => 'Post with Author', 'body' => 'This post will be saved with an author', 'published' => 'N' ), 'Author' => array( 'id' => '5', 'user' => 'bob', 'password' => '5f4dcc3b5aa765d61d8327deb882cf90', 'test' => 'working' )); $this->assertEquals(static::date(), $result[3]['Post']['updated']); $this->assertEquals(static::date(), $result[3]['Post']['created']); $this->assertEquals(static::date(), $result[3]['Author']['created']); $this->assertEquals(static::date(), $result[3]['Author']['updated']); unset( $result[3]['Post']['updated'], $result[3]['Post']['created'], $result[3]['Author']['updated'], $result[3]['Author']['created'] ); $this->assertEquals($expected, $result[3]); $this->assertEquals(4, count($result)); $TestModel = new Comment(); $result = $TestModel->saveAssociated(array( 'Comment' => array( 'article_id' => 2, 'user_id' => 2, 'comment' => 'New comment with attachment', 'published' => 'Y' ), 'Attachment' => array( 'attachment' => 'some_file.tgz' ))); $this->assertFalse(empty($result)); $result = $TestModel->find('all'); $expected = array( 'id' => '7', 'article_id' => '2', 'user_id' => '2', 'comment' => 'New comment with attachment', 'published' => 'Y' ); $this->assertEquals(static::date(), $result[6]['Comment']['updated']); $this->assertEquals(static::date(), $result[6]['Comment']['created']); unset($result[6]['Comment']['updated'], $result[6]['Comment']['created']); $this->assertEquals($expected, $result[6]['Comment']); $expected = array( 'id' => '2', 'comment_id' => '7', 'attachment' => 'some_file.tgz' ); $this->assertEquals(static::date(), $result[6]['Attachment']['updated']); $this->assertEquals(static::date(), $result[6]['Attachment']['created']); unset($result[6]['Attachment']['updated'], $result[6]['Attachment']['created']); $this->assertEquals($expected, $result[6]['Attachment']); } /** * Test that validate = first, atomic = false works when associated records * fail validation. * * @return void */ public function testSaveAssociatedAtomicFalseValidateFirstWithErrors() { $this->loadFixtures('Comment', 'Article', 'User'); $Article = ClassRegistry::init('Article'); $Article->Comment->validator()->add('comment', array( array('rule' => 'notBlank') )); $data = array( 'Article' => array( 'user_id' => 1, 'title' => 'Foo', 'body' => 'text', 'published' => 'N' ), 'Comment' => array( array( 'user_id' => 1, 'comment' => '', 'published' => 'N', ) ), ); $Article->saveAssociated( $data, array('validate' => 'first', 'atomic' => false) ); $result = $Article->validationErrors; $expected = array( 'Comment' => array( array( 'comment' => array('This field cannot be left blank') ) ) ); $this->assertEquals($expected, $result); } /** * testSaveMany method * * @return void */ public function testSaveMany() { $this->loadFixtures('Post'); $TestModel = new Post(); $TestModel->deleteAll(true); $this->assertEquals(array(), $TestModel->find('all')); // SQLite seems to reset the PK counter when that happens, so we need this to make the tests pass $this->db->truncate($TestModel); $TestModel->saveMany(array( array( 'title' => 'Multi-record post 1', 'body' => 'First multi-record post', 'author_id' => 2 ), array( 'title' => 'Multi-record post 2', 'body' => 'Second multi-record post', 'author_id' => 2 ))); $result = $TestModel->find('all', array( 'recursive' => -1, 'order' => 'Post.id ASC' )); $expected = array( array( 'Post' => array( 'id' => '1', 'author_id' => '2', 'title' => 'Multi-record post 1', 'body' => 'First multi-record post', 'published' => 'N' ) ), array( 'Post' => array( 'id' => '2', 'author_id' => '2', 'title' => 'Multi-record post 2', 'body' => 'Second multi-record post', 'published' => 'N' ) ) ); $this->assertEquals(static::date(), $result[0]['Post']['updated']); $this->assertEquals(static::date(), $result[0]['Post']['created']); $this->assertEquals(static::date(), $result[1]['Post']['updated']); $this->assertEquals(static::date(), $result[1]['Post']['created']); unset($result[0]['Post']['updated'], $result[0]['Post']['created']); unset($result[1]['Post']['updated'], $result[1]['Post']['created']); $this->assertEquals($expected, $result); } /** * Test SaveMany with validate=false. * * @return void */ public function testSaveManyValidateFalse() { $this->loadFixtures('Post'); $TestModel = new Post(); $TestModel->deleteAll(true); $data = array( array('id' => 1, 'author_id' => 1, 'title' => 'hi'), array('id' => 2, 'author_id' => 1, 'title' => 'bye') ); $result = $TestModel->saveAll($data, array('validate' => false)); $this->assertTrue($result); } /** * Test SaveAssociated with Habtm relations * * @return void */ public function testSaveAssociatedHabtm() { $this->loadFixtures('Article', 'Tag', 'Comment', 'User', 'ArticlesTag'); $data = array( 'Article' => array( 'user_id' => 1, 'title' => 'Article Has and belongs to Many Tags' ), 'Tag' => array( 'Tag' => array(1, 2) ), 'Comment' => array( array( 'comment' => 'Article comment', 'user_id' => 1 ))); $Article = new Article(); $result = $Article->saveAssociated($data); $this->assertFalse(empty($result)); $result = $Article->read(); $this->assertEquals(2, count($result['Tag'])); $this->assertEquals('tag1', $result['Tag'][0]['tag']); $this->assertEquals(1, count($result['Comment'])); $this->assertEquals(1, count($result['Comment'][0]['comment'])); } /** * Test SaveAssociated with Habtm relations and extra join table fields * * @return void */ public function testSaveAssociatedHabtmWithExtraJoinTableFields() { $this->loadFixtures('Something', 'SomethingElse', 'JoinThing'); $data = array( 'Something' => array( 'id' => 4, 'title' => 'Extra Fields', 'body' => 'Extra Fields Body', 'published' => '1' ), 'SomethingElse' => array( array('something_else_id' => 1, 'doomed' => '1'), array('something_else_id' => 2, 'doomed' => '0'), array('something_else_id' => 3, 'doomed' => '1') ) ); $Something = new Something(); $result = $Something->saveAssociated($data); $this->assertFalse(empty($result)); $result = $Something->read(); $this->assertEquals(3, count($result['SomethingElse'])); $this->assertTrue(Set::matches('/Something[id=4]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=1]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[something_else_id=1]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=1]/JoinThing[doomed=1]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=2]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[something_else_id=2]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=2]/JoinThing[doomed=0]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=3]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[something_else_id=3]', $result)); $this->assertTrue(Set::matches('/SomethingElse[id=3]/JoinThing[doomed=1]', $result)); } /** * testSaveAssociatedHasOne method * * @return void */ public function testSaveAssociatedHasOne() { $model = new Comment(); $model->deleteAll(true); $this->assertEquals(array(), $model->find('all')); $model->Attachment->deleteAll(true); $this->assertEquals(array(), $model->Attachment->find('all')); $this->assertTrue($model->saveAssociated(array( 'Comment' => array( 'comment' => 'Comment with attachment', 'article_id' => 1, 'user_id' => 1 ), 'Attachment' => array( 'attachment' => 'some_file.zip' )))); $result = $model->find('all', array('fields' => array( 'Comment.id', 'Comment.comment', 'Attachment.id', 'Attachment.comment_id', 'Attachment.attachment' ))); $expected = array(array( 'Comment' => array( 'id' => '1', 'comment' => 'Comment with attachment' ), 'Attachment' => array( 'id' => '1', 'comment_id' => '1', 'attachment' => 'some_file.zip' ))); $this->assertEquals($expected, $result); $model->Attachment->bindModel(array('belongsTo' => array('Comment')), false); $data = array( 'Comment' => array( 'comment' => 'Comment with attachment', 'article_id' => 1, 'user_id' => 1 ), 'Attachment' => array( 'attachment' => 'some_file.zip' )); $this->assertTrue($model->saveAssociated($data, array('validate' => 'first'))); } /** * testSaveAssociatedBelongsTo method * * @return void */ public function testSaveAssociatedBelongsTo() { $model = new Comment(); $model->deleteAll(true); $this->assertEquals(array(), $model->find('all')); $model->Article->deleteAll(true); $this->assertEquals(array(), $model->Article->find('all')); $this->assertTrue($model->saveAssociated(array( 'Comment' => array( 'comment' => 'Article comment', 'article_id' => 1, 'user_id' => 1 ), 'Article' => array( 'title' => 'Model Associations 101', 'user_id' => 1 )))); $result = $model->find('all', array('fields' => array( 'Comment.id', 'Comment.comment', 'Comment.article_id', 'Article.id', 'Article.title' ))); $expected = array(array( 'Comment' => array( 'id' => '1', 'article_id' => '1', 'comment' => 'Article comment' ), 'Article' => array( 'id' => '1', 'title' => 'Model Associations 101' ))); $this->assertEquals($expected, $result); } /** * testSaveAssociatedHasOneValidation method * * @return void */ public function testSaveAssociatedHasOneValidation() { $model = new Comment(); $model->deleteAll(true); $this->assertEquals(array(), $model->find('all')); $model->Attachment->deleteAll(true); $this->assertEquals(array(), $model->Attachment->find('all')); $model->validate = array('comment' => 'notBlank'); $model->Attachment->validate = array('attachment' => 'notBlank'); $model->Attachment->bindModel(array('belongsTo' => array('Comment'))); $result = $model->saveAssociated( array( 'Comment' => array( 'comment' => '', 'article_id' => 1, 'user_id' => 1 ), 'Attachment' => array('attachment' => '') ) ); $this->assertFalse($result); $expected = array( 'comment' => array( 'This field cannot be left blank' ), 'Attachment' => array( 'attachment' => array( 'This field cannot be left blank' ) ) ); $this->assertEquals($expected, $model->validationErrors); $this->assertEquals($expected['Attachment'], $model->Attachment->validationErrors); } /** * testSaveAssociatedAtomic method * * @return void */ public function testSaveAssociatedAtomic() { $this->loadFixtures('Article', 'User'); $TestModel = new Article(); $result = $TestModel->saveAssociated(array( 'Article' => array( 'title' => 'Post with Author', 'body' => 'This post will be saved with an author', 'user_id' => 2 ), 'Comment' => array( array('comment' => 'First new comment', 'user_id' => 2)) ), array('atomic' => false)); $this->assertSame($result, array('Article' => true, 'Comment' => array(true))); $result = $TestModel->saveAssociated(array( 'Article' => array('id' => 2), 'Comment' => array( array( 'comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1 ), array( 'comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2 )) ), array('validate' => true, 'atomic' => false)); $this->assertSame($result, array('Article' => true, 'Comment' => array(true, true))); } /** * testSaveManyAtomic method * * @return void */ public function testSaveManyAtomic() { $this->loadFixtures('Article', 'User'); $TestModel = new Article(); $result = $TestModel->saveMany(array( array( 'id' => '1', 'title' => 'Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N' ), array( 'id' => '2', 'title' => 'Just update the title' ), array( 'title' => 'Creating a fourth post', 'body' => 'Fourth post body', 'user_id' => 2 ) ), array('atomic' => false)); $this->assertSame($result, array(true, true, true)); $TestModel->validate = array('title' => 'notBlank', 'author_id' => 'numeric'); $result = $TestModel->saveMany(array( array( 'id' => '1', 'title' => 'Un-Baleeted First Post', 'body' => 'Not Baleeted!', 'published' => 'Y' ), array( 'id' => '2', 'title' => '', 'body' => 'Trying to get away with an empty title' ) ), array('validate' => true, 'atomic' => false)); $this->assertSame(array(true, false), $result); } /** * testSaveAssociatedHasMany method * * @return void */ public function testSaveAssociatedHasMany() { $this->loadFixtures('Article', 'Comment'); $TestModel = new Article(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array(); $result = $TestModel->saveAssociated(array( 'Article' => array('id' => 2), 'Comment' => array( array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1), array('comment' => 'Second new comment', 'published' => 'Y', 'user_id' => 2) ) )); $this->assertFalse(empty($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, Hash::extract($result['Comment'], '{n}.comment')); $result = $TestModel->saveAssociated( array( 'Article' => array('id' => 2), 'Comment' => array( array( 'comment' => 'Third new comment', 'published' => 'Y', 'user_id' => 1 ))), array('atomic' => false) ); $this->assertFalse(empty($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' ); $this->assertEquals($expected, Hash::extract($result['Comment'], '{n}.comment')); $TestModel->beforeSaveReturn = false; $result = $TestModel->saveAssociated( array( 'Article' => array('id' => 2), 'Comment' => array( array( 'comment' => 'Fourth new comment', 'published' => 'Y', 'user_id' => 1 ))), array('atomic' => false) ); $this->assertEquals(array('Article' => false), $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' ); $this->assertEquals($expected, Hash::extract($result['Comment'], '{n}.comment')); } /** * testSaveAssociatedHasManyEmpty method * * @return void */ public function testSaveAssociatedHasManyEmpty() { $this->loadFixtures('Article', 'Comment'); $TestModel = new Article(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array(); $TestModel->validate = $TestModel->Comment->validate = array('user_id' => array('notBlank' => array('rule' => 'notBlank', 'required' => true))); //empty hasMany data is ignored in save $result = $TestModel->saveAssociated(array( 'Article' => array('title' => 'title', 'user_id' => 1), 'Comment' => array() ), array('validate' => true)); $this->assertTrue($result); $result = $TestModel->saveAssociated(array( 'Article' => array('title' => 'title', 'user_id' => 1), 'Comment' => array() ), array('validate' => true, 'atomic' => false)); $this->assertEquals(array('Article' => true), $result); //empty primary data is not ignored $result = $TestModel->saveAssociated(array('Article' => array()), array('validate' => true)); $this->assertFalse($result); $result = $TestModel->saveAssociated(array('Article' => array()), array('validate' => true, 'atomic' => false)); $this->assertEquals(array('Article' => false), $result); } /** * testSaveAssociatedHasManyValidation method * * @return void */ public function testSaveAssociatedHasManyValidation() { $this->loadFixtures('Article', 'Comment'); $TestModel = new Article(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array(); $TestModel->Comment->validate = array('comment' => 'notBlank'); $result = $TestModel->saveAssociated(array( 'Article' => array('id' => 2), 'Comment' => array( array('comment' => '', 'published' => 'Y', 'user_id' => 1), ) ), array('validate' => true)); $this->assertFalse($result); $expected = array('Comment' => array( array('comment' => array('This field cannot be left blank')) )); $this->assertEquals($expected, $TestModel->validationErrors); $expected = array( array('comment' => array('This field cannot be left blank')) ); $this->assertEquals($expected, $TestModel->Comment->validationErrors); $result = $TestModel->saveAssociated(array( 'Article' => array('id' => 2), 'Comment' => array( array( 'comment' => '', 'published' => 'Y', 'user_id' => 1 )) ), array('validate' => 'first')); $this->assertFalse($result); } /** * test saveMany with transactions and ensure there is no missing rollback. * * @return void */ public function testSaveManyTransactionNoRollback() { $this->loadFixtures('Post'); $Post = new TestPost(); $Post->validate = array( 'title' => array('rule' => array('notBlank')) ); // If validation error occurs, rollback() should be called. $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->once())->method('begin')->will($this->returnValue(true)); $db->expects($this->never())->method('commit'); $db->expects($this->once())->method('rollback'); $Post->setDataSourceObject($db); $data = array( array('author_id' => 1, 'title' => 'New Fourth Post'), array('author_id' => 1, 'title' => '') ); $Post->saveMany($data, array('validate' => true)); // If exception thrown, rollback() should be called too. $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->once())->method('begin')->will($this->returnValue(true)); $db->expects($this->never())->method('commit'); $db->expects($this->once())->method('rollback'); $Post->setDataSourceObject($db); $data = array( array('author_id' => 1, 'title' => 'New Fourth Post'), array('author_id' => 1, 'title' => 'New Fifth Post', 'body' => $db->expression('PDO_EXCEPTION()')) ); try { $Post->saveMany($data, array('validate' => true)); $this->fail('No exception thrown'); } catch (PDOException $e) { } // Otherwise, commit() should be called. $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->once())->method('begin')->will($this->returnValue(true)); $db->expects($this->once())->method('commit'); $db->expects($this->never())->method('rollback'); $Post->setDataSourceObject($db); $data = array( array('author_id' => 1, 'title' => 'New Fourth Post'), array('author_id' => 1, 'title' => 'New Fifth Post') ); $Post->saveMany($data, array('validate' => true)); } /** * test saveAssociated with transactions and ensure there is no missing rollback. * * @return void */ public function testSaveAssociatedTransactionNoRollback() { $this->loadFixtures('Post', 'Author'); $Post = new TestPost(); $Post->Author->validate = array( 'user' => array('rule' => array('notBlank')) ); // If validation error occurs, rollback() should be called. $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->once())->method('begin')->will($this->returnValue(true)); $db->expects($this->never())->method('commit'); $db->expects($this->once())->method('rollback'); $Post->setDataSourceObject($db); $Post->Author->setDataSourceObject($db); $data = array( 'Post' => array( 'title' => 'New post', 'body' => 'Content', 'published' => 'Y' ), 'Author' => array( 'user' => '', 'password' => "sekret" ) ); $Post->saveAssociated($data, array('validate' => true, 'atomic' => true)); // If exception thrown, commit() should be called. $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->once())->method('begin')->will($this->returnValue(true)); $db->expects($this->never())->method('commit'); $db->expects($this->once())->method('rollback'); $Post->setDataSourceObject($db); $Post->Author->setDataSourceObject($db); $data = array( 'Post' => array( 'title' => 'New post', 'body' => $db->expression('PDO_EXCEPTION()'), 'published' => 'Y' ), 'Author' => array( 'user' => 'New user', 'password' => "sekret" ) ); try { $Post->saveAssociated($data, array('validate' => true, 'atomic' => true)); $this->fail('No exception thrown'); } catch (PDOException $e) { } // Otherwise, commit() should be called. $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->once())->method('begin')->will($this->returnValue(true)); $db->expects($this->once())->method('commit'); $db->expects($this->never())->method('rollback'); $Post->setDataSourceObject($db); $Post->Author->setDataSourceObject($db); $data = array( 'Post' => array( 'title' => 'New post', 'body' => 'Content', 'published' => 'Y' ), 'Author' => array( 'user' => 'New user', 'password' => "sekret" ) ); $Post->saveAssociated($data, array('validate' => true, 'atomic' => true)); } /** * test saveMany with nested saveMany call. * * @return void */ public function testSaveManyNestedSaveMany() { $this->loadFixtures('Sample'); $TransactionManyTestModel = new TransactionManyTestModel(); $data = array( array('apple_id' => 1, 'name' => 'sample5'), ); $this->assertTrue($TransactionManyTestModel->saveMany($data, array('atomic' => true))); } /** * testSaveManyTransaction method * * @return void */ public function testSaveManyTransaction() { $this->loadFixtures('Post', 'Author', 'Comment', 'Attachment'); $TestModel = new Post(); $TestModel->validate = array('title' => 'notBlank'); $data = array( array('author_id' => 1, 'title' => 'New Fourth Post'), array('author_id' => 1, 'title' => 'New Fifth Post'), array('author_id' => 1, 'title' => '') ); $this->assertFalse($TestModel->saveMany($data)); $result = $TestModel->find('all', array('recursive' => -1)); $expected = array( array('Post' => array( 'id' => '1', 'author_id' => 1, 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' )), array('Post' => array( 'id' => '2', 'author_id' => 3, 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' )), array('Post' => array( 'id' => '3', 'author_id' => 1, 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ))); if (count($result) != 3) { // Database doesn't support transactions $expected[] = array( 'Post' => array( 'id' => '4', 'author_id' => 1, 'title' => 'New Fourth Post', 'body' => null, 'published' => 'N' )); $expected[] = array( 'Post' => array( 'id' => '5', 'author_id' => 1, 'title' => 'New Fifth Post', 'body' => null, 'published' => 'N', )); $this->assertEquals(static::date(), $result[3]['Post']['created']); $this->assertEquals(static::date(), $result[3]['Post']['updated']); $this->assertEquals(static::date(), $result[4]['Post']['created']); $this->assertEquals(static::date(), $result[4]['Post']['updated']); unset($result[3]['Post']['created'], $result[3]['Post']['updated']); unset($result[4]['Post']['created'], $result[4]['Post']['updated']); $this->assertEquals($expected, $result); // Skip the rest of the transactional tests return; } $this->assertEquals($expected, $result); $data = array( array('author_id' => 1, 'title' => 'New Fourth Post'), array('author_id' => 1, 'title' => ''), array('author_id' => 1, 'title' => 'New Sixth Post') ); $this->assertFalse($TestModel->saveMany($data)); $result = $TestModel->find('all', array('recursive' => -1)); $expected = array( array('Post' => array( 'id' => '1', 'author_id' => 1, 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31' )), array('Post' => array( 'id' => '2', 'author_id' => 3, 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31' )), array('Post' => array( 'id' => '3', 'author_id' => 1, 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' ))); if (count($result) != 3) { // Database doesn't support transactions $expected[] = array( 'Post' => array( 'id' => '4', 'author_id' => 1, 'title' => 'New Fourth Post', 'body' => 'Third Post Body', 'published' => 'N' )); $expected[] = array( 'Post' => array( 'id' => '5', 'author_id' => 1, 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'N' )); $this->assertEquals(static::date(), $result[3]['Post']['created']); $this->assertEquals(static::date(), $result[3]['Post']['updated']); $this->assertEquals(static::date(), $result[4]['Post']['created']); $this->assertEquals(static::date(), $result[4]['Post']['updated']); unset($result[3]['Post']['created'], $result[3]['Post']['updated']); unset($result[4]['Post']['created'], $result[4]['Post']['updated']); } $this->assertEquals($expected, $result); $TestModel->validate = array('title' => 'notBlank'); $data = array( array('author_id' => 1, 'title' => 'New Fourth Post'), array('author_id' => 1, 'title' => 'New Fifth Post'), array('author_id' => 1, 'title' => 'New Sixth Post') ); $this->assertTrue($TestModel->saveMany($data)); $result = $TestModel->find('all', array( 'recursive' => -1, 'fields' => array('author_id', 'title', 'body', 'published'), 'order' => array('Post.created' => 'ASC') )); $expected = array( array('Post' => array( 'author_id' => 1, 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y' )), array('Post' => array( 'author_id' => 3, 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y' )), array('Post' => array( 'author_id' => 1, 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y' )), array('Post' => array( 'author_id' => 1, 'title' => 'New Fourth Post', 'body' => '', 'published' => 'N' )), array('Post' => array( 'author_id' => 1, 'title' => 'New Fifth Post', 'body' => '', 'published' => 'N' )), array('Post' => array( 'author_id' => 1, 'title' => 'New Sixth Post', 'body' => '', 'published' => 'N' ))); $this->assertEquals($expected, $result); } /** * testSaveManyValidation method * * @return void */ public function testSaveManyValidation() { $this->loadFixtures('Post', 'Author', 'Comment', 'Attachment'); $TestModel = new Post(); $data = array( array( 'id' => '1', 'title' => 'Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N' ), array( 'id' => '2', 'title' => 'Just update the title' ), array( 'title' => 'Creating a fourth post', 'body' => 'Fourth post body', 'author_id' => 2 )); $this->assertTrue($TestModel->saveMany($data)); $result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC')); $expected = array( array( 'Post' => array( 'id' => '1', 'author_id' => '1', 'title' => 'Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N', 'created' => '2007-03-18 10:39:23' ) ), array( 'Post' => array( 'id' => '2', 'author_id' => '3', 'title' => 'Just update the title', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23' ) ), array( 'Post' => array( 'id' => '3', 'author_id' => '1', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31' )), array( 'Post' => array( 'id' => '4', 'author_id' => '2', 'title' => 'Creating a fourth post', 'body' => 'Fourth post body', 'published' => 'N' ) ) ); $this->assertEquals(static::date(), $result[0]['Post']['updated']); $this->assertEquals(static::date(), $result[1]['Post']['updated']); $this->assertEquals(static::date(), $result[3]['Post']['created']); $this->assertEquals(static::date(), $result[3]['Post']['updated']); unset($result[0]['Post']['updated'], $result[1]['Post']['updated']); unset($result[3]['Post']['created'], $result[3]['Post']['updated']); $this->assertEquals($expected, $result); $TestModel->validate = array('title' => 'notBlank', 'author_id' => 'numeric'); $data = array( array( 'id' => '1', 'title' => 'Un-Baleeted First Post', 'body' => 'Not Baleeted!', 'published' => 'Y' ), array( 'id' => '2', 'title' => '', 'body' => 'Trying to get away with an empty title' )); $result = $TestModel->saveMany($data); $this->assertFalse($result); $result = $TestModel->find('all', array('recursive' => -1, 'order' => 'Post.id ASC')); $errors = array(1 => array('title' => array('This field cannot be left blank'))); $transactionWorked = Set::matches('/Post[1][title=Baleeted First Post]', $result); if (!$transactionWorked) { $this->assertTrue(Set::matches('/Post[1][title=Un-Baleeted First Post]', $result)); $this->assertTrue(Set::matches('/Post[2][title=Just update the title]', $result)); } $this->assertEquals($errors, $TestModel->validationErrors); $TestModel->validate = array('title' => 'notBlank', 'author_id' => 'numeric'); $data = array( array( 'id' => '1', 'title' => 'Un-Baleeted First Post', 'body' => 'Not Baleeted!', 'published' => 'Y' ), array( 'id' => '2', 'title' => '', 'body' => 'Trying to get away with an empty title' )); $result = $TestModel->saveMany($data, array('validate' => true, 'atomic' => false)); $this->assertEquals(array(true, false), $result); $result = $TestModel->find('all', array( 'fields' => array('id', 'author_id', 'title', 'body', 'published'), 'recursive' => -1, 'order' => 'Post.id ASC' )); $errors = array(1 => array('title' => array('This field cannot be left blank'))); $expected = array( array( 'Post' => array( 'id' => '1', 'author_id' => '1', 'title' => 'Un-Baleeted First Post', 'body' => 'Not Baleeted!', 'published' => 'Y', )), array( 'Post' => array( 'id' => '2', 'author_id' => '3', 'title' => 'Just update the title', 'body' => 'Second Post Body', 'published' => 'Y', )), array( 'Post' => array( 'id' => '3', 'author_id' => '1', 'title' => 'Third Post', 'body' => 'Third Post Body', 'published' => 'Y', )), array( 'Post' => array( 'id' => '4', 'author_id' => '2', 'title' => 'Creating a fourth post', 'body' => 'Fourth post body', 'published' => 'N', ))); $this->assertEquals($expected, $result); $this->assertEquals($errors, $TestModel->validationErrors); $data = array( array( 'id' => '1', 'title' => 'Re-Baleeted First Post', 'body' => 'Baleeted!', 'published' => 'N' ), array( 'id' => '2', 'title' => '', 'body' => 'Trying to get away with an empty title' )); $this->assertFalse($TestModel->saveMany($data, array('validate' => 'first'))); $result = $TestModel->find('all', array( 'fields' => array('id', 'author_id', 'title', 'body', 'published'), 'recursive' => -1, 'order' => 'Post.id ASC' )); $this->assertEquals($expected, $result); $this->assertEquals($errors, $TestModel->validationErrors); } /** * testValidateMany method * * @return void */ public function testValidateMany() { $TestModel = new Article(); $TestModel->validate = array('title' => 'notBlank'); $data = array( 0 => array('title' => ''), 1 => array('title' => 'title 1'), 2 => array('title' => 'title 2'), ); $result = $TestModel->validateMany($data); $this->assertFalse($result); $expected = array( 0 => array('title' => array('This field cannot be left blank')), ); $this->assertEquals($expected, $TestModel->validationErrors); $data = array( 0 => array('title' => 'title 0'), 1 => array('title' => ''), 2 => array('title' => 'title 2'), ); $result = $TestModel->validateMany($data); $this->assertFalse($result); $expected = array( 1 => array('title' => array('This field cannot be left blank')), ); $this->assertEquals($expected, $TestModel->validationErrors); } /** * testSaveAssociatedValidateFirst method * * @return void */ public function testSaveAssociatedValidateFirst() { $this->loadFixtures('Article', 'Comment', 'Attachment'); $model = new Article(); $model->deleteAll(true); $model->Comment->validate = array('comment' => 'notBlank'); $result = $model->saveAssociated(array( 'Article' => array( 'title' => 'Post with Author', 'body' => 'This post will be saved author' ), 'Comment' => array( array('comment' => 'First new comment'), array('comment' => '') ) ), array('validate' => 'first')); $this->assertFalse($result); $result = $model->find('all'); $this->assertSame(array(), $result); $expected = array('Comment' => array( 1 => array('comment' => array('This field cannot be left blank')) )); $this->assertEquals($expected['Comment'], $model->Comment->validationErrors); $this->assertSame($model->Comment->find('count'), 0); $result = $model->saveAssociated( array( 'Article' => array( 'title' => 'Post with Author', 'body' => 'This post will be saved with an author', 'user_id' => 2 ), 'Comment' => array( array( 'comment' => 'Only new comment', 'user_id' => 2 ))), array('validate' => 'first') ); $this->assertTrue($result); $result = $model->Comment->find('all'); $this->assertSame(count($result), 1); $result = Hash::extract($result, '{n}.Comment.article_id'); $this->assertEquals(4, $result[0]); $model->deleteAll(true); $data = array( 'Article' => array( 'title' => 'Post with Author saveAlled from comment', 'body' => 'This post will be saved with an author', 'user_id' => 2 ), 'Comment' => array( 'comment' => 'Only new comment', 'user_id' => 2 )); $result = $model->Comment->saveAssociated($data, array('validate' => 'first')); $this->assertFalse(empty($result)); $result = $model->find('all'); $this->assertEquals( 'Post with Author saveAlled from comment', $result[0]['Article']['title'] ); $this->assertEquals('Only new comment', $result[0]['Comment'][0]['comment']); } /** * test saveMany()'s return is correct when using atomic = false and validate = first. * * @return void */ public function testSaveManyValidateFirstAtomicFalse() { $Something = new Something(); $invalidData = array( array( 'title' => 'foo', 'body' => 'bar', 'published' => 'baz', ), array( 'body' => 3, 'published' => 'sd', ), ); $Something->create(); $Something->validate = array( 'title' => array( 'rule' => 'alphaNumeric', 'required' => true, ), 'body' => array( 'rule' => 'alphaNumeric', 'required' => true, 'allowEmpty' => true, ), ); $result = $Something->saveMany($invalidData, array( 'atomic' => false, 'validate' => 'first', )); $expected = array(true, false); $this->assertEquals($expected, $result); $Something = new Something(); $validData = array( array( 'title' => 'title value', 'body' => 'body value', 'published' => 'baz', ), array( 'title' => 'valid', 'body' => 'this body', 'published' => 'sd', ), ); $Something->create(); $result = $Something->saveMany($validData, array( 'atomic' => false, 'validate' => 'first', )); $expected = array(true, true); $this->assertEquals($expected, $result); } /** * testValidateAssociated method * * @return void */ public function testValidateAssociated() { $this->loadFixtures('Attachment', 'Article', 'Comment'); $TestModel = new Comment(); $TestModel->Attachment->validate = array('attachment' => 'notBlank'); $data = array( 'Comment' => array( 'comment' => 'This is the comment' ), 'Attachment' => array( 'attachment' => '' ) ); $result = $TestModel->validateAssociated($data); $this->assertFalse($result); $TestModel = new Article(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array(); $TestModel->Comment->validate = array('comment' => 'notBlank'); $data = array( 'Article' => array('id' => 2), 'Comment' => array( array( 'id' => 1, 'comment' => '', 'published' => 'Y', 'user_id' => 1), array( 'id' => 2, 'comment' => 'comment', 'published' => 'Y', 'user_id' => 1 ))); $result = $TestModel->validateAssociated($data); $this->assertFalse($result); $data = array( 'Article' => array('id' => 2), 'Comment' => array( array( 'id' => 1, 'comment' => '', 'published' => 'Y', 'user_id' => 1 ), array( 'id' => 2, 'comment' => 'comment', 'published' => 'Y', 'user_id' => 1 ), array( 'id' => 3, 'comment' => '', 'published' => 'Y', 'user_id' => 1 ))); $result = $TestModel->validateAssociated($data, array( 'atomic' => false )); $expected = array( 'Article' => true, 'Comment' => array(false, true, false) ); $this->assertSame($expected, $result); $expected = array('Comment' => array( 0 => array('comment' => array('This field cannot be left blank')), 2 => array('comment' => array('This field cannot be left blank')) )); $this->assertEquals($expected, $TestModel->validationErrors); $expected = array( 0 => array('comment' => array('This field cannot be left blank')), 2 => array('comment' => array('This field cannot be left blank')) ); $this->assertEquals($expected, $TestModel->Comment->validationErrors); } /** * test that saveMany behaves like plain save() when suplied empty data * * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data * @return void */ public function testSaveManyEmptyData() { $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.'); $this->loadFixtures('Article', 'ProductUpdateAll', 'Comment', 'Attachment'); $model = new Article(); $result = $model->saveMany(array(), array('validate' => true)); $this->assertFalse(empty($result)); $model = new ProductUpdateAll(); $result = $model->saveMany(array()); $this->assertFalse($result); } /** * test that saveAssociated behaves like plain save() when supplied empty data * * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data * @return void */ public function testSaveAssociatedEmptyData() { $this->skipIf($this->db instanceof Sqlserver, 'This test is not compatible with SQL Server.'); $this->loadFixtures('Article', 'ProductUpdateAll', 'Comment', 'Attachment'); $model = new Article(); $result = $model->saveAssociated(array(), array('validate' => true)); $this->assertFalse(empty($result)); $model = new ProductUpdateAll(); $result = $model->saveAssociated(array()); $this->assertFalse($result); } /** * Test that saveAssociated will accept expression object values when saving. * * @return void */ public function testSaveAssociatedExpressionObjects() { $this->loadFixtures('Post', 'Author', 'Comment', 'Attachment', 'Article', 'User'); $TestModel = new Post(); $db = $TestModel->getDataSource(); $TestModel->saveAssociated(array( 'Post' => array( 'title' => $db->expression("(SELECT 'Post with Author')"), 'body' => 'This post will be saved with an author' ), 'Author' => array( 'user' => 'bob', 'password' => '5f4dcc3b5aa765d61d8327deb882cf90' )), array('atomic' => false)); $result = $TestModel->find('first', array( 'order' => array('Post.id ' => 'DESC') )); $this->assertEquals('Post with Author', $result['Post']['title']); } /** * testUpdateWithCalculation method * * @return void */ public function testUpdateWithCalculation() { $this->loadFixtures('DataTest'); $model = new DataTest(); $model->deleteAll(true); $result = $model->saveMany(array( array('count' => 5, 'float' => 1.1), array('count' => 3, 'float' => 1.2), array('count' => 4, 'float' => 1.3), array('count' => 1, 'float' => 2.0), )); $this->assertFalse(empty($result)); $result = Hash::extract($model->find('all', array('fields' => 'count')), '{n}.DataTest.count'); $this->assertEquals(array(5, 3, 4, 1), $result); $this->assertTrue($model->updateAll(array('count' => 'count + 2'))); $result = Hash::extract($model->find('all', array('fields' => 'count')), '{n}.DataTest.count'); $this->assertEquals(array(7, 5, 6, 3), $result); $this->assertTrue($model->updateAll(array('DataTest.count' => 'DataTest.count - 1'))); $result = Hash::extract($model->find('all', array('fields' => 'count')), '{n}.DataTest.count'); $this->assertEquals(array(6, 4, 5, 2), $result); } /** * testToggleBoolFields method * * @return void */ public function testToggleBoolFields() { $this->loadFixtures('CounterCacheUser', 'CounterCachePost'); $Post = new CounterCachePost(); $Post->unbindModel(array('belongsTo' => array('User')), true); $true = array('Post' => array('published' => true, 'id' => 2)); $false = array('Post' => array('published' => false, 'id' => 2)); $fields = array('Post.published', 'Post.id'); $updateConditions = array('Post.id' => 2); // check its true $result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields)); $this->assertEquals($true, $result); // Testing without the alias $this->assertTrue($Post->updateAll(array('published' => 'NOT published'), $updateConditions)); $result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields)); $this->assertEquals($false, $result); $this->assertTrue($Post->updateAll(array('published' => 'NOT published'), $updateConditions)); $result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields)); $this->assertEquals($true, $result); $db = ConnectionManager::getDataSource('test'); $alias = $db->name('Post.published'); // Testing with the alias $this->assertTrue($Post->updateAll(array('Post.published' => "NOT $alias"), $updateConditions)); $result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields)); $this->assertEquals($false, $result); $this->assertTrue($Post->updateAll(array('Post.published' => "NOT $alias"), $updateConditions)); $result = $Post->find('first', array('conditions' => $updateConditions, 'fields' => $fields)); $this->assertEquals($true, $result); } /** * TestFindAllWithoutForeignKey * * @return void */ public function testFindAllForeignKey() { $this->loadFixtures('ProductUpdateAll', 'GroupUpdateAll'); $ProductUpdateAll = new ProductUpdateAll(); $conditions = array('Group.name' => 'group one'); $ProductUpdateAll->bindModel(array( 'belongsTo' => array( 'Group' => array('className' => 'GroupUpdateAll') ) )); $ProductUpdateAll->belongsTo = array( 'Group' => array('className' => 'GroupUpdateAll', 'foreignKey' => 'group_id') ); $results = $ProductUpdateAll->find('all', compact('conditions')); $this->assertTrue(!empty($results)); $ProductUpdateAll->bindModel(array('belongsTo' => array('Group'))); $ProductUpdateAll->belongsTo = array( 'Group' => array( 'className' => 'GroupUpdateAll', 'foreignKey' => false, 'conditions' => 'ProductUpdateAll.groupcode = Group.code' )); $resultsFkFalse = $ProductUpdateAll->find('all', compact('conditions')); $this->assertTrue(!empty($resultsFkFalse)); $expected = array( '0' => array( 'ProductUpdateAll' => array( 'id' => 1, 'name' => 'product one', 'groupcode' => 120, 'group_id' => 1), 'Group' => array( 'id' => 1, 'name' => 'group one', 'code' => 120) ), '1' => array( 'ProductUpdateAll' => array( 'id' => 2, 'name' => 'product two', 'groupcode' => 120, 'group_id' => 1), 'Group' => array( 'id' => 1, 'name' => 'group one', 'code' => 120) ) ); $this->assertEquals($expected, $results); $this->assertEquals($expected, $resultsFkFalse); } /** * test updateAll with empty values. * * @return void */ public function testUpdateAllEmptyValues() { $this->skipIf($this->db instanceof Sqlserver || $this->db instanceof Postgres, 'This test is not compatible with Postgres or SQL Server.'); $this->loadFixtures('Author', 'Post'); $model = new Author(); $result = $model->updateAll(array('user' => '""')); $this->assertTrue($result); } /** * testUpdateAllWithJoins * * @return void */ public function testUpdateAllWithJoins() { $this->skipIf(!$this->db instanceof Mysql, 'Currently, there is no way of doing joins in an update statement in postgresql or sqlite'); $this->loadFixtures('ProductUpdateAll', 'GroupUpdateAll'); $ProductUpdateAll = new ProductUpdateAll(); $conditions = array('Group.name' => 'group one'); $ProductUpdateAll->bindModel(array('belongsTo' => array( 'Group' => array('className' => 'GroupUpdateAll'))) ); $ProductUpdateAll->updateAll(array('name' => "'new product'"), $conditions); $results = $ProductUpdateAll->find('all', array( 'conditions' => array('ProductUpdateAll.name' => 'new product') )); $expected = array( '0' => array( 'ProductUpdateAll' => array( 'id' => 1, 'name' => 'new product', 'groupcode' => 120, 'group_id' => 1), 'Group' => array( 'id' => 1, 'name' => 'group one', 'code' => 120) ), '1' => array( 'ProductUpdateAll' => array( 'id' => 2, 'name' => 'new product', 'groupcode' => 120, 'group_id' => 1), 'Group' => array( 'id' => 1, 'name' => 'group one', 'code' => 120))); $this->assertEquals($expected, $results); } /** * testUpdateAllWithoutForeignKey * * @return void */ public function testUpdateAllWithoutForeignKey() { $this->skipIf(!$this->db instanceof Mysql, 'Currently, there is no way of doing joins in an update statement in postgresql'); $this->loadFixtures('ProductUpdateAll', 'GroupUpdateAll'); $ProductUpdateAll = new ProductUpdateAll(); $conditions = array('Group.name' => 'group one'); $ProductUpdateAll->bindModel(array('belongsTo' => array( 'Group' => array('className' => 'GroupUpdateAll') ))); $ProductUpdateAll->belongsTo = array( 'Group' => array( 'className' => 'GroupUpdateAll', 'foreignKey' => false, 'conditions' => 'ProductUpdateAll.groupcode = Group.code' ) ); $ProductUpdateAll->updateAll(array('name' => "'new product'"), $conditions); $resultsFkFalse = $ProductUpdateAll->find('all', array('conditions' => array('ProductUpdateAll.name' => 'new product'))); $expected = array( '0' => array( 'ProductUpdateAll' => array( 'id' => 1, 'name' => 'new product', 'groupcode' => 120, 'group_id' => 1), 'Group' => array( 'id' => 1, 'name' => 'group one', 'code' => 120) ), '1' => array( 'ProductUpdateAll' => array( 'id' => 2, 'name' => 'new product', 'groupcode' => 120, 'group_id' => 1), 'Group' => array( 'id' => 1, 'name' => 'group one', 'code' => 120))); $this->assertEquals($expected, $resultsFkFalse); } /** * test writing floats in german locale. * * @return void */ public function testWriteFloatAsGerman() { $restore = setlocale(LC_NUMERIC, 0); $this->skipIf(setlocale(LC_NUMERIC, 'de_DE') === false, "The German locale isn't available."); $model = new DataTest(); $result = $model->save(array( 'count' => 1, 'float' => 3.14593 )); $this->assertTrue((bool)$result); setlocale(LC_NUMERIC, $restore); } /** * Test returned array contains primary key when save creates a new record * * @return void */ public function testPkInReturnArrayForCreate() { $this->loadFixtures('Article'); $TestModel = new Article(); $data = array('Article' => array( 'user_id' => '1', 'title' => 'Fourth Article', 'body' => 'Fourth Article Body', 'published' => 'Y' )); $result = $TestModel->save($data); $this->assertSame($result['Article']['id'], $TestModel->id); } /** * testSaveAllFieldListValidateBelongsTo * * @return void */ public function testSaveAllFieldListValidateBelongsTo() { $this->loadFixtures('Post', 'Author', 'Comment', 'Attachment'); $TestModel = new Post(); $result = $TestModel->find('all'); $this->assertEquals(3, count($result)); $this->assertFalse(isset($result[3])); // test belongsTo $fieldList = array( 'Post' => array('title'), 'Author' => array('user') ); $data = array( 'Post' => array( 'title' => 'Post without body', 'body' => 'This will not be saved', ), 'Author' => array( 'user' => 'bob', 'test' => 'This will not be saved', )); $TestModel->saveAll($data, array('fieldList' => $fieldList)); $result = $TestModel->find('all', array( 'order' => 'Post.id ASC', )); $expected = array( 'Post' => array( 'id' => '4', 'author_id' => '5', 'title' => 'Post without body', 'body' => null, 'published' => 'N', 'created' => static::date(), 'updated' => static::date(), ), 'Author' => array( 'id' => '5', 'user' => 'bob', 'password' => null, 'created' => static::date(), 'updated' => static::date(), 'test' => 'working', ), ); $this->assertEquals($expected, $result[3]); $this->assertEquals(4, count($result)); $this->assertEquals('', $result[3]['Post']['body']); $this->assertEquals('working', $result[3]['Author']['test']); $fieldList = array( 'Post' => array('title') ); $data = array( 'Post' => array( 'title' => 'Post without body 2', 'body' => 'This will not be saved' ), 'Author' => array( 'user' => 'jack' ) ); $TestModel->saveAll($data, array('fieldList' => $fieldList)); $result = $TestModel->find('all', array( 'order' => 'Post.id ASC', )); $this->assertNull($result[4]['Post']['body']); $fieldList = array( 'Author' => array('password') ); $data = array( 'Post' => array( 'id' => '5', 'title' => 'Post title', 'body' => 'Post body' ), 'Author' => array( 'id' => '6', 'user' => 'will not change', 'password' => 'foobar' ) ); $result = $TestModel->saveAll($data, array('fieldList' => $fieldList)); $this->assertTrue($result); $result = $TestModel->find('all', array( 'order' => 'Post.id ASC', )); $expected = array( 'Post' => array( 'id' => '5', 'author_id' => '6', 'title' => 'Post title', 'body' => 'Post body', 'published' => 'N', 'created' => static::date(), 'updated' => static::date() ), 'Author' => array( 'id' => '6', 'user' => 'jack', 'password' => 'foobar', 'created' => static::date(), 'updated' => static::date(), 'test' => 'working' ), ); $this->assertEquals($expected, $result[4]); // test multirecord $this->db->truncate($TestModel); $fieldList = array('title', 'author_id'); $TestModel->saveAll(array( array( 'title' => 'Multi-record post 1', 'body' => 'First multi-record post', 'author_id' => 2 ), array( 'title' => 'Multi-record post 2', 'body' => 'Second multi-record post', 'author_id' => 2 )), array('fieldList' => $fieldList)); $result = $TestModel->find('all', array( 'recursive' => -1, 'order' => 'Post.id ASC' )); $expected = array( array( 'Post' => array( 'id' => '1', 'author_id' => '2', 'title' => 'Multi-record post 1', 'body' => '', 'published' => 'N', 'created' => static::date(), 'updated' => static::date() ) ), array( 'Post' => array( 'id' => '2', 'author_id' => '2', 'title' => 'Multi-record post 2', 'body' => '', 'published' => 'N', 'created' => static::date(), 'updated' => static::date() ) ) ); $this->assertEquals($expected, $result); } /** * testSaveAllFieldListHasMany method * * @return void */ public function testSaveAllFieldListHasMany() { $this->loadFixtures('Article', 'Comment'); $TestModel = new Article(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array(); $this->db->truncate($TestModel); $this->db->truncate(new Comment()); $data = array( 'Article' => array('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) ) ); $fieldList = array( 'Article' => array('id'), 'Comment' => array('article_id', 'user_id') ); $TestModel->saveAll($data, array('fieldList' => $fieldList)); $result = $TestModel->find('all'); $this->assertEquals('', $result[0]['Article']['title']); $this->assertEquals('', $result[0]['Comment'][0]['comment']); $this->assertEquals('', $result[0]['Comment'][1]['comment']); $fieldList = array( 'Article' => array('id'), 'Comment' => array('user_id') ); $TestModel->saveAll($data, array('fieldList' => $fieldList)); $result = $TestModel->find('all'); $this->assertEquals('', $result[1]['Article']['title']); $this->assertEquals(2, count($result[1]['Comment'])); $TestModel->whitelist = array('id'); $TestModel->Comment->whitelist = array('user_id'); $TestModel->saveAll($data); $result = $TestModel->find('all'); $this->assertEquals('', $result[2]['Article']['title']); $this->assertEquals(2, count($result[2]['Comment'])); } /** * testSaveAllFieldListHasOne method * * @return void */ public function testSaveAllFieldListHasOne() { $this->loadFixtures('Attachment', 'Comment', 'Article', 'User'); $TestModel = new Comment(); $TestModel->validate = array('comment' => 'notBlank'); $TestModel->Attachment->validate = array('attachment' => 'notBlank'); $record = array( 'Comment' => array( 'user_id' => 1, 'article_id' => 1, 'comment' => '', ), 'Attachment' => array( 'attachment' => '' ) ); $result = $TestModel->saveAll($record, array('validate' => 'only')); $this->assertFalse($result); $fieldList = array( 'Comment' => array('id', 'article_id', 'user_id'), 'Attachment' => array('comment_id') ); $result = $TestModel->saveAll($record, array( 'fieldList' => $fieldList, 'validate' => 'only' )); $this->assertTrue($result); $this->assertEmpty($TestModel->validationErrors); } /** * testSaveAllFieldListHasOneAddFkToWhitelist method * * @return void */ public function testSaveAllFieldListHasOneAddFkToWhitelist() { $this->loadFixtures('ArticleFeatured', 'Featured'); $Article = new ArticleFeatured(); $Article->belongsTo = $Article->hasMany = array(); $Article->Featured->validate = array('end_date' => 'notBlank'); $record = array( 'ArticleFeatured' => array( 'user_id' => 1, 'title' => 'First Article', 'body' => '', 'published' => 'Y' ), 'Featured' => array( 'category_id' => 1, 'end_date' => '' ) ); $result = $Article->saveAll($record, array('validate' => 'only')); $this->assertFalse($result); $expected = array( 'body' => array( 'This field cannot be left blank' ), 'Featured' => array( 'end_date' => array( 'This field cannot be left blank' ) ) ); $this->assertEquals($expected, $Article->validationErrors); $fieldList = array( 'ArticleFeatured' => array('user_id', 'title'), 'Featured' => array('category_id') ); $result = $Article->saveAll($record, array( 'fieldList' => $fieldList, 'validate' => 'first' )); $this->assertTrue($result); $this->assertEmpty($Article->validationErrors); $Article->recursive = 0; $result = $Article->find('first', array('order' => array('ArticleFeatured.created' => 'DESC'))); $this->assertSame($result['ArticleFeatured']['id'], $result['Featured']['article_featured_id']); } /** * 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->assertEquals(3, count($result)); $this->assertFalse(isset($result[3])); // 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); } /** * testSaveAllDeepHasManyBelongsTo method * * @return void */ public function testSaveAllDeepHasManyBelongsTo() { $this->loadFixtures('Article', 'Comment', 'User'); $TestModel = new Article(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = array(); $this->db->truncate($TestModel); $this->db->truncate(new Comment()); $result = $TestModel->saveAll(array( 'Article' => array('id' => 2, 'title' => 'The title'), 'Comment' => array( array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1), array( 'comment' => 'belongsto', 'published' => 'Y', 'User' => array('user' => 'findme', 'password' => 'somepass') ) ) ), array('deep' => true)); $result = $TestModel->Comment->User->find('first', array( 'conditions' => array('User.user' => 'findme'), 'fields' => array('id', 'user', 'password') )); $expected = array( 'User' => array( 'id' => 5, 'user' => 'findme', 'password' => 'somepass', ) ); $this->assertEquals($expected, $result); $result = $TestModel->Comment->find('first', array( 'conditions' => array('Comment.user_id' => 5), 'fields' => array('id', 'comment', 'published', 'user_id') )); $expected = array( 'Comment' => array( 'id' => 2, 'comment' => 'belongsto', 'published' => 'Y', 'user_id' => 5 ) ); $this->assertEquals($expected, $result); } /** * testSaveAllDeepHasManyhasMany method * * @return void */ public function testSaveAllDeepHasManyHasMany() { $this->loadFixtures('Article', 'Comment', 'User', 'Attachment'); $TestModel = new Article(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array(); $TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false); $TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false); $this->db->truncate($TestModel); $this->db->truncate(new Comment()); $this->db->truncate(new Attachment()); $result = $TestModel->saveAll(array( 'Article' => array('id' => 2, 'title' => 'The title'), 'Comment' => array( array('comment' => 'First new comment', 'published' => 'Y', 'user_id' => 1), array( 'comment' => 'hasmany', 'published' => 'Y', 'user_id' => 5, 'Attachment' => array( array('attachment' => 'first deep attachment'), array('attachment' => 'second deep attachment'), ) ) ) ), array('deep' => true)); $result = $TestModel->Comment->find('first', array( 'conditions' => array('Comment.comment' => 'hasmany'), 'fields' => array('id', 'comment', 'published', 'user_id'), 'recursive' => -1 )); $expected = array( 'Comment' => array( 'id' => 2, 'comment' => 'hasmany', 'published' => 'Y', 'user_id' => 5 ) ); $this->assertEquals($expected, $result); $result = $TestModel->Comment->Attachment->find('all', array( 'fields' => array('attachment', 'comment_id'), 'order' => array('Attachment.id' => 'ASC') )); $expected = array( array('Attachment' => array('attachment' => 'first deep attachment', 'comment_id' => 2)), array('Attachment' => array('attachment' => 'second deep attachment', 'comment_id' => 2)), ); $this->assertEquals($expected, $result); } /** * testSaveAllDeepOrderHasManyHasMany method * * @return void */ public function testSaveAllDeepOrderHasManyHasMany() { $this->loadFixtures('Article', 'Comment', 'User', 'Attachment'); $TestModel = new Article(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array(); $TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false); $TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false); $this->db->truncate($TestModel); $this->db->truncate(new Comment()); $this->db->truncate(new Attachment()); $result = $TestModel->saveAll(array( 'Article' => array('id' => 2, 'title' => 'Comment has its data after Attachment'), 'Comment' => array( array( 'Attachment' => array( array('attachment' => 'attachment should be created with comment_id'), array('attachment' => 'comment should be created with article_id'), ), 'comment' => 'after associated data', 'user_id' => 1 ) ) ), array('deep' => true)); $result = $TestModel->Comment->find('first', array( 'conditions' => array('Comment.article_id' => 2), )); $this->assertEquals(2, $result['Comment']['article_id']); $this->assertEquals(2, count($result['Attachment'])); } /** * testSaveAllDeepEmptyHasManyHasMany method * * @return void */ public function testSaveAllDeepEmptyHasManyHasMany() { $this->skipIf(!$this->db instanceof Mysql, 'This test is only compatible with Mysql.'); $this->loadFixtures('Article', 'Comment', 'User', 'Attachment'); $TestModel = new Article(); $TestModel->belongsTo = $TestModel->hasAndBelongsToMany = $TestModel->Comment->belongsTo = array(); $TestModel->Comment->unbindModel(array('hasOne' => array('Attachment')), false); $TestModel->Comment->bindModel(array('hasMany' => array('Attachment')), false); $this->db->truncate($TestModel); $this->db->truncate(new Comment()); $this->db->truncate(new Attachment()); $result = $TestModel->saveAll(array( 'Article' => array('id' => 3, 'user_id' => 1, 'title' => 'Comment has no data'), 'Comment' => array( array( 'user_id' => 1, 'Attachment' => array( array('attachment' => 'attachment should be created with comment_id'), array('attachment' => 'comment should be created with article_id'), ), ) ) ), array('deep' => true)); $result = $TestModel->Comment->find('first', array( 'conditions' => array('Comment.article_id' => 3), )); $this->assertEquals(3, $result['Comment']['article_id']); $this->assertEquals(2, count($result['Attachment'])); } /** * Test that boolean fields don't cause saveMany to fail * * @return void */ public function testSaveManyBooleanFields() { $this->loadFixtures('Item', 'Syfile', 'Image'); $data = array( array( 'Item' => array( 'name' => 'testing', 'syfile_id' => 1, 'published' => false ) ), array( 'Item' => array( 'name' => 'testing 2', 'syfile_id' => 1, 'published' => true ) ), ); $item = ClassRegistry::init('Item'); $result = $item->saveMany($data, array('atomic' => false)); $this->assertCount(2, $result, '2 records should have been saved.'); $this->assertTrue($result[0], 'Both should have succeded'); $this->assertTrue($result[1], 'Both should have succeded'); } /** * testSaveManyDeepHasManyValidationFailure method * * @return void */ public function testSaveManyDeepHasManyValidationFailure() { $this->loadFixtures('Article', 'Comment'); $TestModel = new Article(); $TestModel->Comment->validate = array( 'comment' => array( 'notBlank' => array( 'rule' => array('notBlank'), ) ) ); $result = $TestModel->saveMany(array( array( 'user_id' => 1, 'title' => 'New Article', 'body' => 'This article contains a invalid comment', 'Comment' => array( array( 'user_id' => 1, 'comment' => '' ) ) ) ), array('deep' => true)); $this->assertFalse($result); $this->assertEquals(array( array( 'Comment' => array( array('comment' => array('notBlank')) ) ) ), $TestModel->validationErrors); } /** * testSaveAssociatedDeepHasOneHasManyValidateTrueValidationFailure method * * @return void */ public function testSaveAssociatedDeepHasOneHasManyValidateTrueValidationFailure() { $this->loadFixtures('User', 'Article', 'Comment'); $TestModel = new UserHasOneArticle(); $TestModel->Article->Comment->validate = array( 'comment' => array( 'notBlank' => array( 'rule' => array('notBlank'), ) ) ); $result = $TestModel->saveAssociated(array( 'User' => array( 'user' => 'hiromi', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', ), 'Article' => array( 'title' => 'Article with User', 'body' => 'This article will be saved with an user and contains a invalid comment', 'Comment' => array( array( 'user_id' => 1, 'comment' => '' ) ) ) ), array('deep' => true, 'validate' => true)); $this->assertFalse($result); $this->assertEquals(array( 'Article' => array( 'Comment' => array( array('comment' => array('notBlank')) ) ) ), $TestModel->validationErrors); } /** * testSaveAssociatedDeepBelongsToHasManyValidateTrueValidationFailure method * * @return void */ public function testSaveAssociatedDeepBelongsToHasManyValidateTrueValidationFailure() { $this->loadFixtures('ArticlesTag', 'Article', 'Comment'); $TestModel = new ArticlesTagBelongsToArticle(); $TestModel->Article->Comment->validate = array( 'comment' => array( 'notBlank' => array( 'rule' => array('notBlank'), ) ) ); $result = $TestModel->saveAssociated(array( 'ArticlesTagBelongsToArticle' => array( 'tag_id' => 1, ), 'Article' => array( 'title' => 'Article with User', 'body' => 'This article will be saved with an user and contains a invalid comment', 'Comment' => array( array( 'user_id' => 1, 'comment' => '' ) ) ) ), array('deep' => true, 'validate' => true)); $this->assertFalse($result); $this->assertEquals(array( 'Article' => array( 'Comment' => array( array('comment' => array('notBlank')) ) ) ), $TestModel->validationErrors); } /** * Test that boolean fields don't cause saveAssociated to fail * * @return void */ public function testSaveAssociatedHasOneBooleanFields() { $this->loadFixtures('Item', 'Syfile', 'Image'); $data = array( 'Syfile' => array( 'image_id' => 1, 'name' => 'Some file', ), 'Item' => array( 'name' => 'testing', 'published' => false ), ); $syfile = ClassRegistry::init('Syfile'); $syfile->bindModel(array('hasOne' => array('Item')), false); $result = $syfile->saveAssociated($data, array('atomic' => false)); $this->assertCount(2, $result, '2 records should have been saved.'); $this->assertTrue($result['Syfile'], 'Both should have succeded'); $this->assertTrue($result['Item'], 'Both should have succeded'); } /** * Test that boolean fields don't cause saveAssociated to fail * * @return void */ public function testSaveAssociatedBelongsToBooleanFields() { $this->loadFixtures('Item', 'Syfile', 'Image'); $data = array( 'Syfile' => array( 'image_id' => 1, 'name' => 'Some file', ), 'Item' => array( 'name' => 'testing', 'syfile_id' => 2, 'published' => false ), ); $item = ClassRegistry::init('Item'); $item->bindModel(array( 'belongsTo' => array( 'Item' => array( 'foreignKey' => 'image_id' ) ) ), false); $result = $item->saveAssociated($data, array('atomic' => false)); $this->assertCount(2, $result, '2 records should have been saved.'); $this->assertTrue($result['Syfile'], 'Both should have succeded'); $this->assertTrue($result['Item'], 'Both should have succeded'); } /** * testUpdateAllBoolean * * @return void */ public function testUpdateAllBoolean() { $this->loadFixtures('Item', 'Syfile', 'Portfolio', 'Image', 'ItemsPortfolio'); $TestModel = new Item(); $result = $TestModel->updateAll(array('published' => true)); $this->assertTrue($result); $result = $TestModel->find('first', array('fields' => array('id', 'published'))); $this->assertEquals(true, $result['Item']['published']); } /** * testUpdateAllBooleanConditions * * @return void */ public function testUpdateAllBooleanConditions() { $this->loadFixtures('Item', 'Syfile', 'Portfolio', 'Image', 'ItemsPortfolio'); $TestModel = new Item(); $result = $TestModel->updateAll(array('published' => true), array('Item.id' => 1)); $this->assertTrue($result); $result = $TestModel->find('first', array( 'fields' => array('id', 'published'), 'conditions' => array('Item.id' => 1))); $this->assertEquals(true, $result['Item']['published']); } /** * testUpdateBoolean * * @return void */ public function testUpdateBoolean() { $this->loadFixtures('Item', 'Syfile', 'Portfolio', 'Image', 'ItemsPortfolio'); $TestModel = new Item(); $result = $TestModel->save(array('published' => true, 'id' => 1)); $this->assertTrue((bool)$result); $result = $TestModel->find('first', array( 'fields' => array('id', 'published'), 'conditions' => array('Item.id' => 1))); $this->assertEquals(true, $result['Item']['published']); } /** * Test the clear() method. * * @return void */ public function testClear() { $this->loadFixtures('Bid'); $model = ClassRegistry::init('Bid'); $model->set(array('name' => 'Testing', 'message_id' => 3)); $this->assertTrue(isset($model->data['Bid']['name'])); $this->assertTrue($model->clear()); $this->assertFalse(isset($model->data['Bid']['name'])); $this->assertFalse(isset($model->data['Bid']['message_id'])); } /** * Test that Model::save() doesn't generate a query with WHERE 1 = 1 on race condition. * * @link https://github.com/cakephp/cakephp/issues/3857 * @return void */ public function testSafeUpdateMode() { $this->loadFixtures('User'); $User = ClassRegistry::init('User'); $this->assertFalse($User->__safeUpdateMode); $User->getEventManager()->attach(array($this, 'deleteMe'), 'Model.beforeSave'); $User->id = 1; $User->set(array('user' => 'nobody')); $User->save(); $users = $User->find('list', array('fields' => 'User.user')); $expected = array( 2 => 'nate', 3 => 'larry', 4 => 'garrett', ); $this->assertEquals($expected, $users); $this->assertFalse($User->__safeUpdateMode); $User->id = 2; $User->set(array('user' => $User->getDataSource()->expression('PDO_EXCEPTION()'))); try { $User->save(null, false); $this->fail('No exception thrown'); } catch (PDOException $e) { $this->assertFalse($User->__safeUpdateMode); } } /** * Emulates race condition * * @param CakeEvent $event containing the Model * @return void */ public function deleteMe($event) { $Model = $event->subject; $Model->getDataSource()->delete($Model, array($Model->alias . '.' . $Model->primaryKey => $Model->id)); } /** * Creates a convenient mock DboSource * * We cannot call several methods via mock DboSource, such as DboSource::value() * because mock DboSource has no $_connection. * This method helps us to avoid this problem. * * @param array $methods Configurable method names. * @return DboSource */ protected function _getMockDboSource($methods = array()) { $testDb = ConnectionManager::getDataSource('test'); $passthrough = array_diff(array('value', 'begin', 'rollback', 'commit', 'describe', 'lastInsertId', 'execute'), $methods); $methods = array_merge($methods, $passthrough); if (!in_array('connect', $methods)) { $methods[] = 'connect'; // This will be called by DboSource::__construct(). } $db = $this->getMock('DboSource', $methods); $db->columns = $testDb->columns; $db->startQuote = $testDb->startQuote; $db->endQuote = $testDb->endQuote; foreach ($passthrough as $method) { $db->expects($this->any()) ->method($method) ->will($this->returnCallback(array($testDb, $method))); } return $db; } /** * Test that transactions behave correctly on nested saveMany calls. * * @return void */ public function testTransactionOnNestedSaveMany() { $this->loadFixtures('Post'); $Post = new TestPost(); $Post->getEventManager()->attach(array($this, 'nestedSaveMany'), 'Model.afterSave'); // begin -> [ begin -> commit ] -> commit $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->exactly(2))->method('begin')->will($this->returnValue(true)); $db->expects($this->exactly(2))->method('commit'); $db->expects($this->never())->method('rollback'); $Post->setDataSourceObject($db); $data = array( array('author_id' => 1, 'title' => 'Outer Post'), ); $Post->dataForAfterSave = array( array('author_id' => 1, 'title' => 'Inner Post'), ); $this->assertTrue($Post->saveMany($data)); // begin -> [ begin(false) ] -> commit $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->at(0))->method('begin')->will($this->returnValue(true)); $db->expects($this->at(1))->method('begin')->will($this->returnValue(false)); $db->expects($this->once())->method('commit'); $db->expects($this->never())->method('rollback'); $Post->setDataSourceObject($db); $data = array( array('author_id' => 1, 'title' => 'Outer Post'), ); $Post->dataForAfterSave = array( array('author_id' => 1, 'title' => 'Inner Post'), ); $this->assertTrue($Post->saveMany($data)); // begin -> [ begin -> rollback ] -> rollback $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->exactly(2))->method('begin')->will($this->returnValue(true)); $db->expects($this->never())->method('commit'); $db->expects($this->exactly(2))->method('rollback'); $Post->setDataSourceObject($db); $data = array( array('author_id' => 1, 'title' => 'Outer Post'), ); $Post->dataForAfterSave = array( array('author_id' => 1, 'title' => 'Inner Post', 'body' => $db->expression('PDO_EXCEPTION()')), ); try { $Post->saveMany($data); $this->fail('No exception thrown'); } catch(Exception $e) { } } /** * Test that transaction behaves correctly on nested saveAssociated calls. * * @return void */ public function testTransactionOnNestedSaveAssociated() { $this->loadFixtures('Author', 'Post'); $Author = new TestAuthor(); $Author->getEventManager()->attach(array($this, 'nestedSaveAssociated'), 'Model.afterSave'); // begin -> [ begin -> commit ] -> commit $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->exactly(2))->method('begin')->will($this->returnValue(true)); $db->expects($this->exactly(2))->method('commit'); $db->expects($this->never())->method('rollback'); $Author->setDataSourceObject($db); $Author->Post->setDataSourceObject($db); $data = array( 'Author' => array('user' => 'outer'), 'Post' => array( array('title' => 'Outer Post'), ) ); $Author->dataForAfterSave = array( 'Author' => array('user' => 'inner'), 'Post' => array( array('title' => 'Inner Post'), ) ); $this->assertTrue($Author->saveAssociated($data)); // begin -> [ begin(false) ] -> commit $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->at(0))->method('begin')->will($this->returnValue(true)); $db->expects($this->at(1))->method('begin')->will($this->returnValue(false)); $db->expects($this->once())->method('commit'); $db->expects($this->never())->method('rollback'); $Author->setDataSourceObject($db); $Author->Post->setDataSourceObject($db); $data = array( 'Author' => array('user' => 'outer'), 'Post' => array( array('title' => 'Outer Post'), ) ); $Author->dataForAfterSave = array( 'Author' => array('user' => 'inner'), 'Post' => array( array('title' => 'Inner Post'), ) ); $this->assertTrue($Author->saveAssociated($data)); // begin -> [ begin -> rollback ] -> rollback $db = $this->_getMockDboSource(array('begin', 'commit', 'rollback')); $db->expects($this->exactly(2))->method('begin')->will($this->returnValue(true)); $db->expects($this->never())->method('commit'); $db->expects($this->exactly(2))->method('rollback'); $Author->setDataSourceObject($db); $Author->Post->setDataSourceObject($db); $data = array( 'Author' => array('user' => 'outer'), 'Post' => array( array('title' => 'Outer Post'), ) ); $Author->dataForAfterSave = array( 'Author' => array('user' => 'inner', 'password' => $db->expression('PDO_EXCEPTION()')), 'Post' => array( array('title' => 'Inner Post'), ) ); try { $Author->saveAssociated($data); $this->fail('No exception thrown'); } catch(Exception $e) { } } /** * A callback for testing nested saveMany. * * @param CakeEvent $event containing the Model * @return void */ public function nestedSaveMany($event) { $Model = $event->subject; $Model->saveMany($Model->dataForAfterSave, array('callbacks' => false)); } /** * A callback for testing nested saveAssociated. * * @param CakeEvent $event containing the Model * @return void */ public function nestedSaveAssociated($event) { $Model = $event->subject; $Model->saveAssociated($Model->dataForAfterSave, array('callbacks' => false)); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Validator/000077500000000000000000000000001265552240500213325ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Model/Validator/CakeValidationRuleTest.php000066400000000000000000000123311265552240500264110ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests * @package Cake.Test.Case.Model.Validator * @since CakePHP(tm) v 2.2.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('CakeValidationRule', 'Model/Validator'); /** * CakeValidationRuleTest * * @package Cake.Test.Case.Model.Validator */ class CakeValidationRuleTest extends CakeTestCase { /** * Auxiliary method to test custom validators * * @return bool */ public function myTestRule() { return false; } /** * Auxiliary method to test custom validators * * @return bool */ public function myTestRule2() { return true; } /** * Auxiliary method to test custom validators * * @return string */ public function myTestRule3() { return 'string'; } /** * Test isValid method * * @return void */ public function testIsValid() { $def = array('rule' => 'notBlank', 'message' => 'Can not be empty'); $data = array( 'fieldName' => '' ); $methods = array(); $Rule = new CakeValidationRule($def); $Rule->process('fieldName', $data, $methods); $this->assertFalse($Rule->isValid()); $data = array('fieldName' => 'not empty'); $Rule->process('fieldName', $data, $methods); $this->assertTrue($Rule->isValid()); } /** * tests that passing custom validation methods work * * @return void */ public function testCustomMethods() { $def = array('rule' => 'myTestRule'); $data = array( 'fieldName' => 'some data' ); $methods = array('mytestrule' => array($this, 'myTestRule')); $Rule = new CakeValidationRule($def); $Rule->process('fieldName', $data, $methods); $this->assertFalse($Rule->isValid()); $methods = array('mytestrule' => array($this, 'myTestRule2')); $Rule->process('fieldName', $data, $methods); $this->assertTrue($Rule->isValid()); $methods = array('mytestrule' => array($this, 'myTestRule3')); $Rule->process('fieldName', $data, $methods); $this->assertFalse($Rule->isValid()); } /** * Make sure errors are triggered when validation is missing. * * @expectedException PHPUnit_Framework_Error_Warning * @expectedExceptionMessage Could not find validation handler totallyMissing for fieldName * @return void */ public function testCustomMethodMissingError() { $def = array('rule' => array('totallyMissing')); $data = array( 'fieldName' => 'some data' ); $methods = array('mytestrule' => array($this, 'myTestRule')); $Rule = new CakeValidationRule($def); $Rule->process('fieldName', $data, $methods); } /** * Test isRequired method * * @return void */ public function testIsRequired() { $def = array('rule' => 'notBlank', 'required' => true); $Rule = new CakeValidationRule($def); $this->assertTrue($Rule->isRequired()); $def = array('rule' => 'notBlank', 'required' => false); $Rule = new CakeValidationRule($def); $this->assertFalse($Rule->isRequired()); $def = array('rule' => 'notBlank', 'required' => 'create'); $Rule = new CakeValidationRule($def); $this->assertTrue($Rule->isRequired()); $def = array('rule' => 'notBlank', 'required' => 'update'); $Rule = new CakeValidationRule($def); $this->assertFalse($Rule->isRequired()); $Rule->isUpdate(true); $this->assertTrue($Rule->isRequired()); } /** * Test isEmptyAllowed method * * @return void */ public function testIsEmptyAllowed() { $def = array('rule' => 'aRule', 'allowEmpty' => true); $Rule = new CakeValidationRule($def); $this->assertTrue($Rule->isEmptyAllowed()); $def = array('rule' => 'aRule', 'allowEmpty' => false); $Rule = new CakeValidationRule($def); $this->assertFalse($Rule->isEmptyAllowed()); $def = array('rule' => 'notBlank', 'allowEmpty' => false, 'on' => 'update'); $Rule = new CakeValidationRule($def); $this->assertTrue($Rule->isEmptyAllowed()); $Rule->isUpdate(true); $this->assertFalse($Rule->isEmptyAllowed()); $def = array('rule' => 'notBlank', 'allowEmpty' => false, 'on' => 'create'); $Rule = new CakeValidationRule($def); $this->assertFalse($Rule->isEmptyAllowed()); $Rule->isUpdate(true); $this->assertTrue($Rule->isEmptyAllowed()); } /** * Test checkRequired method * * @return void */ public function testCheckRequiredWhenRequiredAndAllowEmpty() { $Rule = $this->getMock('CakeValidationRule', array('isRequired')); $Rule->expects($this->any()) ->method('isRequired') ->will($this->returnValue(true)); $Rule->allowEmpty = true; $fieldname = 'field'; $data = array( $fieldname => null ); $this->assertFalse($Rule->checkRequired($fieldname, $data), "A null but present field should not fail requirement check if allowEmpty is true"); $Rule->allowEmpty = false; $this->assertTrue($Rule->checkRequired($fieldname, $data), "A null but present field should fail requirement check if allowEmpty is false"); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/Validator/CakeValidationSetTest.php000066400000000000000000000232751265552240500262460ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests * @package Cake.Test.Case.Model.Validator * @since CakePHP(tm) v 2.2.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('CakeValidationSet', 'Model/Validator'); /** * CakeValidationSetTest * * @package Cake.Test.Case.Model.Validator */ class CakeValidationSetTest extends CakeTestCase { /** * override locale to the default (eng). * * @return void */ public function setUp() { parent::setUp(); Configure::write('Config.language', 'eng'); } /** * testValidate method * * @return void */ public function testValidate() { $Field = new CakeValidationSet('title', 'notBlank'); $data = array( 'title' => '', 'body' => 'a body' ); $result = $Field->validate($data); $expected = array('This field cannot be left blank'); $this->assertEquals($expected, $result); $Field = new CakeValidationSet('body', 'notBlank'); $result = $Field->validate($data); $this->assertEmpty($result); $Field = new CakeValidationSet('nothere', array( 'notBlank' => array( 'rule' => 'notBlank', 'required' => true ) )); $result = $Field->validate($data); $expected = array('notBlank'); $this->assertEquals($expected, $result); $Field = new CakeValidationSet('body', array( 'inList' => array( 'rule' => array('inList', array('test')) ) )); $result = $Field->validate($data); $expected = array('inList'); $this->assertEquals($expected, $result); } /** * testGetRule method * * @return void */ public function testGetRule() { $rules = array('notBlank' => array('rule' => 'notBlank', 'message' => 'Can not be empty')); $Field = new CakeValidationSet('title', $rules); $result = $Field->getRule('notBlank'); $this->assertInstanceOf('CakeValidationRule', $result); $this->assertEquals('notBlank', $result->rule); $this->assertEquals(null, $result->required); $this->assertEquals(false, $result->allowEmpty); $this->assertEquals(null, $result->on); $this->assertEquals(true, $result->last); $this->assertEquals('Can not be empty', $result->message); } /** * testGetRules method * * @return void */ public function testGetRules() { $rules = array('notBlank' => array('rule' => 'notBlank', 'message' => 'Can not be empty')); $Field = new CakeValidationSet('title', $rules); $result = $Field->getRules(); $this->assertEquals(array('notBlank'), array_keys($result)); $this->assertInstanceOf('CakeValidationRule', $result['notBlank']); } /** * testSetRule method * * @return void */ public function testSetRule() { $rules = array('notBlank' => array('rule' => 'notBlank', 'message' => 'Can not be empty')); $Field = new CakeValidationSet('title', $rules); $Rule = new CakeValidationRule($rules['notBlank']); $this->assertEquals($Rule, $Field->getRule('notBlank')); $rules = array('validEmail' => array('rule' => 'email', 'message' => 'Invalid email')); $Rule = new CakeValidationRule($rules['validEmail']); $Field->setRule('validEmail', $Rule); $result = $Field->getRules(); $this->assertEquals(array('notBlank', 'validEmail'), array_keys($result)); $rules = array('validEmail' => array('rule' => 'email', 'message' => 'Other message')); $Rule = new CakeValidationRule($rules['validEmail']); $Field->setRule('validEmail', $Rule); $result = $Field->getRules(); $this->assertEquals(array('notBlank', 'validEmail'), array_keys($result)); $result = $Field->getRule('validEmail'); $this->assertInstanceOf('CakeValidationRule', $result); $this->assertEquals('email', $result->rule); $this->assertEquals(null, $result->required); $this->assertEquals(false, $result->allowEmpty); $this->assertEquals(null, $result->on); $this->assertEquals(true, $result->last); $this->assertEquals('Other message', $result->message); } /** * testSetRules method * * @return void */ public function testSetRules() { $rule = array('notBlank' => array('rule' => 'notBlank', 'message' => 'Can not be empty')); $Field = new CakeValidationSet('title', $rule); $RuleEmpty = new CakeValidationRule($rule['notBlank']); $rule = array('validEmail' => array('rule' => 'email', 'message' => 'Invalid email')); $RuleEmail = new CakeValidationRule($rule['validEmail']); $rules = array('validEmail' => $RuleEmail); $Field->setRules($rules, false); $result = $Field->getRules(); $this->assertEquals(array('validEmail'), array_keys($result)); $Field->setRules(array('validEmail' => $rule), false); $result = $Field->getRules(); $this->assertEquals(array('validEmail'), array_keys($result)); $this->assertTrue(array_pop($result) instanceof CakeValidationRule); $rules = array('notBlank' => $RuleEmpty); $Field->setRules($rules, true); $result = $Field->getRules(); $this->assertEquals(array('validEmail', 'notBlank'), array_keys($result)); $rules = array('notBlank' => array('rule' => 'notBlank')); $Field->setRules($rules, true); $result = $Field->getRules(); $this->assertEquals(array('validEmail', 'notBlank'), array_keys($result)); $this->assertTrue(array_pop($result) instanceof CakeValidationRule); $this->assertTrue(array_pop($result) instanceof CakeValidationRule); } /** * Tests getting a rule from the set using array access * * @return void */ public function testArrayAccessGet() { $Set = new CakeValidationSet('title', array( 'notBlank' => array('rule' => 'notBlank', 'required' => true), 'numeric' => array('rule' => 'numeric'), 'other' => array('rule' => array('other', 1)), )); $rule = $Set['notBlank']; $this->assertInstanceOf('CakeValidationRule', $rule); $this->assertEquals('notBlank', $rule->rule); $rule = $Set['numeric']; $this->assertInstanceOf('CakeValidationRule', $rule); $this->assertEquals('numeric', $rule->rule); $rule = $Set['other']; $this->assertInstanceOf('CakeValidationRule', $rule); $this->assertEquals(array('other', 1), $rule->rule); } /** * Tests checking a rule from the set using array access * * @return void */ public function testArrayAccessExists() { $Set = new CakeValidationSet('title', array( 'notBlank' => array('rule' => 'notBlank', 'required' => true), 'numeric' => array('rule' => 'numeric'), 'other' => array('rule' => array('other', 1)), )); $this->assertTrue(isset($Set['notBlank'])); $this->assertTrue(isset($Set['numeric'])); $this->assertTrue(isset($Set['other'])); $this->assertFalse(isset($Set['fail'])); } /** * Tests setting a rule in the set using array access * * @return void */ public function testArrayAccessSet() { $Set = new CakeValidationSet('title', array( 'notBlank' => array('rule' => 'notBlank', 'required' => true), )); $this->assertFalse(isset($Set['other'])); $Set['other'] = array('rule' => array('other', 1)); $rule = $Set['other']; $this->assertInstanceOf('CakeValidationRule', $rule); $this->assertEquals(array('other', 1), $rule->rule); $this->assertFalse(isset($Set['numeric'])); $Set['numeric'] = new CakeValidationRule(array('rule' => 'numeric')); $rule = $Set['numeric']; $this->assertInstanceOf('CakeValidationRule', $rule); $this->assertEquals('numeric', $rule->rule); } /** * Tests unseting a rule from the set using array access * * @return void */ public function testArrayAccessUnset() { $Set = new CakeValidationSet('title', array( 'notBlank' => array('rule' => 'notBlank', 'required' => true), 'numeric' => array('rule' => 'numeric'), 'other' => array('rule' => array('other', 1)), )); unset($Set['notBlank']); $this->assertFalse(isset($Set['notBlank'])); unset($Set['numeric']); $this->assertFalse(isset($Set['notBlank'])); unset($Set['other']); $this->assertFalse(isset($Set['notBlank'])); } /** * Tests it is possible to iterate a validation set object * * @return void */ public function testIterator() { $Set = new CakeValidationSet('title', array( 'notBlank' => array('rule' => 'notBlank', 'required' => true), 'numeric' => array('rule' => 'numeric'), 'other' => array('rule' => array('other', 1)), )); $i = 0; foreach ($Set as $name => $rule) { if ($i === 0) { $this->assertEquals('notBlank', $name); } if ($i === 1) { $this->assertEquals('numeric', $name); } if ($i === 2) { $this->assertEquals('other', $name); } $this->assertInstanceOf('CakeValidationRule', $rule); $i++; } $this->assertEquals(3, $i); } /** * Tests countable interface * * @return void */ public function testCount() { $Set = new CakeValidationSet('title', array( 'notBlank' => array('rule' => 'notBlank', 'required' => true), 'numeric' => array('rule' => 'numeric'), 'other' => array('rule' => array('other', 1)), )); $this->assertCount(3, $Set); unset($Set['other']); $this->assertCount(2, $Set); } /** * Test removeRule method * * @return void */ public function testRemoveRule() { $Set = new CakeValidationSet('title', array( 'notBlank' => array('rule' => 'notBlank', 'required' => true), 'numeric' => array('rule' => 'numeric'), 'other' => array('rule' => array('other', 1)), )); $Set->removeRule('notBlank'); $this->assertFalse(isset($Set['notBlank'])); $Set->removeRule('numeric'); $this->assertFalse(isset($Set['numeric'])); $Set->removeRule('other'); $this->assertFalse(isset($Set['other'])); } } cakephp-2.8.0/lib/Cake/Test/Case/Model/models.php000066400000000000000000002464451265552240500214200ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Model * @since CakePHP(tm) v 1.2.0.6464 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Model', 'Model'); /** * AppModel class * * @package Cake.Test.Case.Model */ class AppModel extends Model { /** * findMethods property * * @var array */ public $findMethods = array('published' => true); /** * useDbConfig property * * @var array */ public $useDbConfig = 'test'; /** * _findPublished custom find * * @return array */ protected function _findPublished($state, $query, $results = array()) { if ($state === 'before') { $query['conditions']['published'] = 'Y'; return $query; } return $results; } } /** * Test class * * @package Cake.Test.Case.Model */ class Test extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; /** * name property * * @var string */ public $name = 'Test'; /** * schema property * * @var array */ protected $_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '1', 'length' => '8', 'key' => 'primary'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'email' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'notes' => array('type' => 'text', 'null' => '1', 'default' => 'write some notes here', 'length' => ''), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); } /** * TestAlias class * * @package Cake.Test.Case.Model */ class TestAlias extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; /** * name property * * @var string */ public $name = 'TestAlias'; /** * schema property * * @var array */ protected $_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '1', 'length' => '8', 'key' => 'primary'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'email' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'notes' => array('type' => 'text', 'null' => '1', 'default' => 'write some notes here', 'length' => ''), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); } /** * TestValidate class * * @package Cake.Test.Case.Model */ class TestValidate extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; /** * name property * * @var string */ public $name = 'TestValidate'; /** * schema property * * @var array */ protected $_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'title' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'body' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => ''), 'number' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'modified' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); /** * validateNumber method * * @param mixed $value * @param mixed $options * @return void */ public function validateNumber($value, $options) { $options += array('min' => 0, 'max' => 100); $valid = ($value['number'] >= $options['min'] && $value['number'] <= $options['max']); return $valid; } /** * validateTitle method * * @param mixed $value * @return void */ public function validateTitle($value) { return (!empty($value) && strpos(strtolower($value['title']), 'title-') === 0); } } /** * User class * * @package Cake.Test.Case.Model */ class User extends CakeTestModel { /** * name property * * @var string */ public $name = 'User'; /** * validate property * * @var array */ public $validate = array('user' => 'notBlank', 'password' => 'notBlank'); /** * beforeFind() callback used to run ContainableBehaviorTest::testLazyLoad() * * @return bool * @throws Exception */ public function beforeFind($queryData) { if (!empty($queryData['lazyLoad'])) { if (!isset($this->Article, $this->Comment, $this->ArticleFeatured)) { throw new Exception('Unavailable associations'); } } return true; } } /** * Article class * * @package Cake.Test.Case.Model */ class Article extends CakeTestModel { /** * name property * * @var string */ public $name = 'Article'; /** * belongsTo property * * @var array */ public $belongsTo = array('User'); /** * hasMany property * * @var array */ public $hasMany = array('Comment' => array('dependent' => true)); /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('Tag'); /** * validate property * * @var array */ public $validate = array( 'user_id' => 'numeric', 'title' => array('required' => false, 'rule' => 'notBlank'), 'body' => array('required' => false, 'rule' => 'notBlank'), ); /** * beforeSaveReturn property * * @var bool */ public $beforeSaveReturn = true; /** * beforeSave method * * @return void */ public function beforeSave($options = array()) { return $this->beforeSaveReturn; } /** * titleDuplicate method * * @param string $title * @return void */ public static function titleDuplicate($title) { if ($title === 'My Article Title') { return false; } return true; } } /** * Model stub for beforeDelete testing * * @see #250 * @package Cake.Test.Case.Model */ class BeforeDeleteComment extends CakeTestModel { public $name = 'BeforeDeleteComment'; public $useTable = 'comments'; public function beforeDelete($cascade = true) { $db = $this->getDataSource(); $db->delete($this, array($this->alias . '.' . $this->primaryKey => array(1, 3))); return true; } } /** * NumericArticle class * * @package Cake.Test.Case.Model */ class NumericArticle extends CakeTestModel { /** * name property * * @var string */ public $name = 'NumericArticle'; /** * useTable property * * @var string */ public $useTable = 'numeric_articles'; } /** * Article10 class * * @package Cake.Test.Case.Model */ class Article10 extends CakeTestModel { /** * name property * * @var string */ public $name = 'Article10'; /** * useTable property * * @var string */ public $useTable = 'articles'; /** * hasMany property * * @var array */ public $hasMany = array('Comment' => array('dependent' => true, 'exclusive' => true)); } /** * ArticleFeatured class * * @package Cake.Test.Case.Model */ class ArticleFeatured extends CakeTestModel { /** * name property * * @var string */ public $name = 'ArticleFeatured'; /** * belongsTo property * * @var array */ public $belongsTo = array('User', 'Category'); /** * hasOne property * * @var array */ public $hasOne = array('Featured'); /** * hasMany property * * @var array */ public $hasMany = array('Comment' => array('className' => 'Comment', 'dependent' => true)); /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('Tag'); /** * validate property * * @var array */ public $validate = array('user_id' => 'numeric', 'title' => 'notBlank', 'body' => 'notBlank'); } /** * Featured class * * @package Cake.Test.Case.Model */ class Featured extends CakeTestModel { /** * name property * * @var string */ public $name = 'Featured'; /** * belongsTo property * * @var array */ public $belongsTo = array('ArticleFeatured', 'Category'); } /** * Tag class * * @package Cake.Test.Case.Model */ class Tag extends CakeTestModel { /** * name property * * @var string */ public $name = 'Tag'; } /** * ArticlesTag class * * @package Cake.Test.Case.Model */ class ArticlesTag extends CakeTestModel { /** * name property * * @var string */ public $name = 'ArticlesTag'; } /** * ArticleFeaturedsTag class * * @package Cake.Test.Case.Model */ class ArticleFeaturedsTag extends CakeTestModel { /** * name property * * @var string */ public $name = 'ArticleFeaturedsTag'; } /** * Comment class * * @package Cake.Test.Case.Model */ class Comment extends CakeTestModel { /** * name property * * @var string */ public $name = 'Comment'; /** * belongsTo property * * @var array */ public $belongsTo = array('Article', 'User'); /** * hasOne property * * @var array */ public $hasOne = array('Attachment' => array('dependent' => true)); } /** * Modified Comment Class has afterFind Callback * * @package Cake.Test.Case.Model */ class ModifiedComment extends CakeTestModel { /** * name property * * @var string */ public $name = 'Comment'; /** * useTable property * * @var string */ public $useTable = 'comments'; /** * Property used to toggle filtering of results * * @var bool */ public $remove = false; /** * belongsTo property * * @var array */ public $belongsTo = array('Article'); /** * afterFind callback * * @return void */ public function afterFind($results, $primary = false) { if (isset($results[0])) { $results[0]['Comment']['callback'] = 'Fire'; } if ($this->remove) { return array(); } return $results; } } /** * Modified Comment Class has afterFind Callback * * @package Cake.Test.Case.Model */ class AgainModifiedComment extends CakeTestModel { /** * name property * * @var string */ public $name = 'Comment'; /** * useTable property * * @var string */ public $useTable = 'comments'; /** * belongsTo property * * @var array */ public $belongsTo = array('Article'); /** * afterFind callback * * @return void */ public function afterFind($results, $primary = false) { if (isset($results[0])) { $results[0]['Comment']['querytype'] = $this->findQueryType; } return $results; } } /** * MergeVarPluginAppModel class * * @package Cake.Test.Case.Model */ class MergeVarPluginAppModel extends AppModel { /** * actsAs parameter * * @var array */ public $actsAs = array( 'Containable' ); } /** * MergeVarPluginPost class * * @package Cake.Test.Case.Model */ class MergeVarPluginPost extends MergeVarPluginAppModel { /** * actsAs parameter * * @var array */ public $actsAs = array( 'Tree' ); /** * useTable parameter * * @var string */ public $useTable = 'posts'; } /** * MergeVarPluginComment class * * @package Cake.Test.Case.Model */ class MergeVarPluginComment extends MergeVarPluginAppModel { /** * actsAs parameter * * @var array */ public $actsAs = array( 'Containable' => array('some_settings') ); /** * useTable parameter * * @var string */ public $useTable = 'comments'; } /** * Attachment class * * @package Cake.Test.Case.Model */ class Attachment extends CakeTestModel { /** * name property * * @var string */ public $name = 'Attachment'; /** * belongsTo property * * @var array */ public $belongsTo = array('Comment'); } /** * ModifiedAttachment class * * @package Cake.Test.Case.Model */ class ModifiedAttachment extends CakeTestModel { /** * name property * * @var string */ public $name = 'ModifiedAttachment'; /** * useTable property * * @var string */ public $useTable = 'attachments'; /** * afterFind callback * * @return void */ public function afterFind($results, $primary = false) { if ($this->useConsistentAfterFind) { if (isset($results[0][$this->alias]['id'])) { $results[0][$this->alias]['callback'] = 'Fired'; } } else { if (isset($results['id'])) { $results['callback'] = 'Fired'; } } return $results; } } /** * Category class * * @package Cake.Test.Case.Model */ class Category extends CakeTestModel { /** * name property * * @var string */ public $name = 'Category'; } /** * CategoryThread class * * @package Cake.Test.Case.Model */ class CategoryThread extends CakeTestModel { /** * name property * * @var string */ public $name = 'CategoryThread'; /** * belongsTo property * * @var array */ public $belongsTo = array('ParentCategory' => array('className' => 'CategoryThread', 'foreignKey' => 'parent_id')); } /** * Apple class * * @package Cake.Test.Case.Model */ class Apple extends CakeTestModel { /** * name property * * @var string */ public $name = 'Apple'; /** * validate property * * @var array */ public $validate = array('name' => 'notBlank'); /** * hasOne property * * @var array */ public $hasOne = array('Sample'); /** * hasMany property * * @var array */ public $hasMany = array('Child' => array('className' => 'Apple', 'dependent' => true)); /** * belongsTo property * * @var array */ public $belongsTo = array('Parent' => array('className' => 'Apple', 'foreignKey' => 'apple_id')); } /** * Sample class * * @package Cake.Test.Case.Model */ class Sample extends CakeTestModel { /** * name property * * @var string */ public $name = 'Sample'; /** * belongsTo property * * @var string */ public $belongsTo = 'Apple'; } /** * AnotherArticle class * * @package Cake.Test.Case.Model */ class AnotherArticle extends CakeTestModel { /** * name property * * @var string */ public $name = 'AnotherArticle'; /** * hasMany property * * @var string */ public $hasMany = 'Home'; } /** * Advertisement class * * @package Cake.Test.Case.Model */ class Advertisement extends CakeTestModel { /** * name property * * @var string */ public $name = 'Advertisement'; /** * hasMany property * * @var string */ public $hasMany = 'Home'; } /** * Home class * * @package Cake.Test.Case.Model */ class Home extends CakeTestModel { /** * name property * * @var string */ public $name = 'Home'; /** * belongsTo property * * @var array */ public $belongsTo = array('AnotherArticle', 'Advertisement'); } /** * Post class * * @package Cake.Test.Case.Model */ class Post extends CakeTestModel { /** * name property * * @var string */ public $name = 'Post'; /** * belongsTo property * * @var array */ public $belongsTo = array('Author'); /** * @param array $queryData * @return bool true */ public function beforeFind($queryData) { if (isset($queryData['connection'])) { $this->useDbConfig = $queryData['connection']; } return true; } /** * @param array $results * @param bool $primary * @return array results */ public function afterFind($results, $primary = false) { $this->useDbConfig = 'test'; return $results; } } /** * Author class * * @package Cake.Test.Case.Model */ class Author extends CakeTestModel { /** * name property * * @var string */ public $name = 'Author'; /** * hasMany property * * @var array */ public $hasMany = array('Post'); /** * afterFind method * * @param array $results * @return void */ public function afterFind($results, $primary = false) { $results[0]['Author']['test'] = 'working'; return $results; } } /** * ModifiedAuthor class * * @package Cake.Test.Case.Model */ class ModifiedAuthor extends Author { /** * name property * * @var string */ public $name = 'Author'; /** * afterFind method * * @param array $results * @return void */ public function afterFind($results, $primary = false) { foreach ($results as $index => $result) { $results[$index]['Author']['user'] .= ' (CakePHP)'; } return $results; } } /** * Project class * * @package Cake.Test.Case.Model */ class Project extends CakeTestModel { /** * name property * * @var string */ public $name = 'Project'; /** * hasMany property * * @var array */ public $hasMany = array('Thread'); } /** * Thread class * * @package Cake.Test.Case.Model */ class Thread extends CakeTestModel { /** * name property * * @var string */ public $name = 'Thread'; /** * hasMany property * * @var array */ public $belongsTo = array('Project'); /** * hasMany property * * @var array */ public $hasMany = array('Message'); } /** * Message class * * @package Cake.Test.Case.Model */ class Message extends CakeTestModel { /** * name property * * @var string */ public $name = 'Message'; /** * hasOne property * * @var array */ public $hasOne = array('Bid'); } /** * Bid class * * @package Cake.Test.Case.Model */ class Bid extends CakeTestModel { /** * name property * * @var string */ public $name = 'Bid'; /** * belongsTo property * * @var array */ public $belongsTo = array('Message'); } /** * BiddingMessage class * * @package Cake.Test.Case.Model */ class BiddingMessage extends CakeTestModel { /** * name property * * @var string */ public $name = 'BiddingMessage'; /** * primaryKey property * * @var string */ public $primaryKey = 'bidding'; /** * belongsTo property * * @var array */ public $belongsTo = array( 'Bidding' => array( 'foreignKey' => false, 'conditions' => array('BiddingMessage.bidding = Bidding.bid') ) ); } /** * Bidding class * * @package Cake.Test.Case.Model */ class Bidding extends CakeTestModel { /** * name property * * @var string */ public $name = 'Bidding'; /** * hasOne property * * @var array */ public $hasOne = array( 'BiddingMessage' => array( 'foreignKey' => false, 'conditions' => array('BiddingMessage.bidding = Bidding.bid'), 'dependent' => true ) ); } /** * NodeAfterFind class * * @package Cake.Test.Case.Model */ class NodeAfterFind extends CakeTestModel { /** * name property * * @var string */ public $name = 'NodeAfterFind'; /** * validate property * * @var array */ public $validate = array('name' => 'notBlank'); /** * useTable property * * @var string */ public $useTable = 'apples'; /** * hasOne property * * @var array */ public $hasOne = array('Sample' => array('className' => 'NodeAfterFindSample')); /** * hasMany property * * @var array */ public $hasMany = array('Child' => array('className' => 'NodeAfterFind', 'dependent' => true)); /** * belongsTo property * * @var array */ public $belongsTo = array('Parent' => array('className' => 'NodeAfterFind', 'foreignKey' => 'apple_id')); /** * afterFind method * * @param mixed $results * @return array */ public function afterFind($results, $primary = false) { return $results; } } /** * NodeAfterFindSample class * * @package Cake.Test.Case.Model */ class NodeAfterFindSample extends CakeTestModel { /** * name property * * @var string */ public $name = 'NodeAfterFindSample'; /** * useTable property * * @var string */ public $useTable = 'samples'; /** * belongsTo property * * @var string */ public $belongsTo = 'NodeAfterFind'; } /** * NodeNoAfterFind class * * @package Cake.Test.Case.Model */ class NodeNoAfterFind extends CakeTestModel { /** * name property * * @var string */ public $name = 'NodeAfterFind'; /** * validate property * * @var array */ public $validate = array('name' => 'notBlank'); /** * useTable property * * @var string */ public $useTable = 'apples'; /** * hasOne property * * @var array */ public $hasOne = array('Sample' => array('className' => 'NodeAfterFindSample')); /** * hasMany property * * @var array */ public $hasMany = array('Child' => array('className' => 'NodeAfterFind', 'dependent' => true)); /** * belongsTo property * * @var array */ public $belongsTo = array('Parent' => array('className' => 'NodeAfterFind', 'foreignKey' => 'apple_id')); } /** * Node class * * @package Cake.Test.Case.Model */ class Node extends CakeTestModel { /** * name property * * @var string */ public $name = 'Node'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array( 'ParentNode' => array( 'className' => 'Node', 'joinTable' => 'dependency', 'with' => 'Dependency', 'foreignKey' => 'child_id', 'associationForeignKey' => 'parent_id', ) ); } /** * Dependency class * * @package Cake.Test.Case.Model */ class Dependency extends CakeTestModel { /** * name property * * @var string */ public $name = 'Dependency'; } /** * ModelA class * * @package Cake.Test.Case.Model */ class ModelA extends CakeTestModel { /** * name property * * @var string */ public $name = 'ModelA'; /** * useTable property * * @var string */ public $useTable = 'apples'; /** * hasMany property * * @var array */ public $hasMany = array('ModelB', 'ModelC'); } /** * ModelB class * * @package Cake.Test.Case.Model */ class ModelB extends CakeTestModel { /** * name property * * @var string */ public $name = 'ModelB'; /** * useTable property * * @var string */ public $useTable = 'messages'; /** * hasMany property * * @var array */ public $hasMany = array('ModelD'); } /** * ModelC class * * @package Cake.Test.Case.Model */ class ModelC extends CakeTestModel { /** * name property * * @var string */ public $name = 'ModelC'; /** * useTable property * * @var string */ public $useTable = 'bids'; /** * hasMany property * * @var array */ public $hasMany = array('ModelD'); } /** * ModelD class * * @package Cake.Test.Case.Model */ class ModelD extends CakeTestModel { /** * name property * * @var string */ public $name = 'ModelD'; /** * useTable property * * @var string */ public $useTable = 'threads'; } /** * Something class * * @package Cake.Test.Case.Model */ class Something extends CakeTestModel { /** * name property * * @var string */ public $name = 'Something'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('SomethingElse' => array('with' => array('JoinThing' => array('doomed')))); } /** * SomethingElse class * * @package Cake.Test.Case.Model */ class SomethingElse extends CakeTestModel { /** * name property * * @var string */ public $name = 'SomethingElse'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('Something' => array('with' => 'JoinThing')); /** * afterFind callBack * * @param array $results * @param bool $primary * @return array */ public function afterFind($results, $primary = false) { foreach ($results as $key => $result) { if (!empty($result[$this->alias]) && is_array($result[$this->alias])) { $results[$key][$this->alias]['afterFind'] = 'Successfully added by AfterFind'; } } return $results; } } /** * JoinThing class * * @package Cake.Test.Case.Model */ class JoinThing extends CakeTestModel { /** * name property * * @var string */ public $name = 'JoinThing'; /** * belongsTo property * * @var array */ public $belongsTo = array('Something', 'SomethingElse'); /** * afterFind callBack * * @param array $results * @param bool $primary * @return array */ public function afterFind($results, $primary = false) { foreach ($results as $key => $result) { if (!empty($result[$this->alias]) && is_array($result[$this->alias])) { $results[$key][$this->alias]['afterFind'] = 'Successfully added by AfterFind'; } } return $results; } } /** * Portfolio class * * @package Cake.Test.Case.Model */ class Portfolio extends CakeTestModel { /** * name property * * @var string */ public $name = 'Portfolio'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('Item'); } /** * Item class * * @package Cake.Test.Case.Model */ class Item extends CakeTestModel { /** * name property * * @var string */ public $name = 'Item'; /** * belongsTo property * * @var array */ public $belongsTo = array('Syfile' => array('counterCache' => true)); /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('Portfolio' => array('unique' => false)); } /** * ItemsPortfolio class * * @package Cake.Test.Case.Model */ class ItemsPortfolio extends CakeTestModel { /** * name property * * @var string */ public $name = 'ItemsPortfolio'; } /** * Syfile class * * @package Cake.Test.Case.Model */ class Syfile extends CakeTestModel { /** * name property * * @var string */ public $name = 'Syfile'; /** * belongsTo property * * @var array */ public $belongsTo = array('Image'); } /** * Image class * * @package Cake.Test.Case.Model */ class Image extends CakeTestModel { /** * name property * * @var string */ public $name = 'Image'; } /** * DeviceType class * * @package Cake.Test.Case.Model */ class DeviceType extends CakeTestModel { /** * name property * * @var string */ public $name = 'DeviceType'; /** * order property * * @var array */ public $order = array('DeviceType.order' => 'ASC'); /** * belongsTo property * * @var array */ public $belongsTo = array( 'DeviceTypeCategory', 'FeatureSet', 'ExteriorTypeCategory', 'Image' => array('className' => 'Document'), 'Extra1' => array('className' => 'Document'), 'Extra2' => array('className' => 'Document')); /** * hasMany property * * @var array */ public $hasMany = array('Device' => array('order' => array('Device.id' => 'ASC'))); } /** * DeviceTypeCategory class * * @package Cake.Test.Case.Model */ class DeviceTypeCategory extends CakeTestModel { /** * name property * * @var string */ public $name = 'DeviceTypeCategory'; } /** * FeatureSet class * * @package Cake.Test.Case.Model */ class FeatureSet extends CakeTestModel { /** * name property * * @var string */ public $name = 'FeatureSet'; } /** * ExteriorTypeCategory class * * @package Cake.Test.Case.Model */ class ExteriorTypeCategory extends CakeTestModel { /** * name property * * @var string */ public $name = 'ExteriorTypeCategory'; /** * belongsTo property * * @var array */ public $belongsTo = array('Image' => array('className' => 'Device')); } /** * Document class * * @package Cake.Test.Case.Model */ class Document extends CakeTestModel { /** * name property * * @var string */ public $name = 'Document'; /** * belongsTo property * * @var array */ public $belongsTo = array('DocumentDirectory'); } /** * Device class * * @package Cake.Test.Case.Model */ class Device extends CakeTestModel { /** * name property * * @var string */ public $name = 'Device'; } /** * DocumentDirectory class * * @package Cake.Test.Case.Model */ class DocumentDirectory extends CakeTestModel { /** * name property * * @var string */ public $name = 'DocumentDirectory'; } /** * PrimaryModel class * * @package Cake.Test.Case.Model */ class PrimaryModel extends CakeTestModel { /** * name property * * @var string */ public $name = 'PrimaryModel'; } /** * SecondaryModel class * * @package Cake.Test.Case.Model */ class SecondaryModel extends CakeTestModel { /** * name property * * @var string */ public $name = 'SecondaryModel'; } /** * JoinA class * * @package Cake.Test.Case.Model */ class JoinA extends CakeTestModel { /** * name property * * @var string */ public $name = 'JoinA'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('JoinB', 'JoinC'); } /** * JoinB class * * @package Cake.Test.Case.Model */ class JoinB extends CakeTestModel { /** * name property * * @var string */ public $name = 'JoinB'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('JoinA'); } /** * JoinC class * * @package Cake.Test.Case.Model */ class JoinC extends CakeTestModel { /** * name property * * @var string */ public $name = 'JoinC'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('JoinA'); } /** * ThePaper class * * @package Cake.Test.Case.Model */ class ThePaper extends CakeTestModel { /** * name property * * @var string */ public $name = 'ThePaper'; /** * useTable property * * @var string */ public $useTable = 'apples'; /** * hasOne property * * @var array */ public $hasOne = array('Itself' => array('className' => 'ThePaper', 'foreignKey' => 'apple_id')); /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('Monkey' => array('joinTable' => 'the_paper_monkies', 'order' => 'id')); } /** * Monkey class * * @package Cake.Test.Case.Model */ class Monkey extends CakeTestModel { /** * name property * * @var string */ public $name = 'Monkey'; /** * useTable property * * @var string */ public $useTable = 'devices'; } /** * AssociationTest1 class * * @package Cake.Test.Case.Model */ class AssociationTest1 extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'join_as'; /** * name property * * @var string */ public $name = 'AssociationTest1'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('AssociationTest2' => array( 'unique' => false, 'joinTable' => 'join_as_join_bs', 'foreignKey' => false )); } /** * AssociationTest2 class * * @package Cake.Test.Case.Model */ class AssociationTest2 extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'join_bs'; /** * name property * * @var string */ public $name = 'AssociationTest2'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('AssociationTest1' => array( 'unique' => false, 'joinTable' => 'join_as_join_bs' )); } /** * Callback class * * @package Cake.Test.Case.Model */ class Callback extends CakeTestModel { } /** * CallbackPostTestModel class * * @package Cake.Test.Case.Model */ class CallbackPostTestModel extends CakeTestModel { public $useTable = 'posts'; /** * variable to control return of beforeValidate * * @var bool */ public $beforeValidateReturn = true; /** * variable to control return of beforeSave * * @var bool */ public $beforeSaveReturn = true; /** * variable to control return of beforeDelete * * @var bool */ public $beforeDeleteReturn = true; /** * beforeSave callback * * @return bool */ public function beforeSave($options = array()) { return $this->beforeSaveReturn; } /** * beforeValidate callback * * @param array $options Options passed from Model::save(). * @return bool True if validate operation should continue, false to abort * @see Model::save() */ public function beforeValidate($options = array()) { return $this->beforeValidateReturn; } /** * beforeDelete callback * * @return bool */ public function beforeDelete($cascade = true) { return $this->beforeDeleteReturn; } } /** * Uuid class * * @package Cake.Test.Case.Model */ class Uuid extends CakeTestModel { /** * name property * * @var string */ public $name = 'Uuid'; } /** * DataTest class * * @package Cake.Test.Case.Model */ class DataTest extends CakeTestModel { /** * name property * * @var string */ public $name = 'DataTest'; } /** * TheVoid class * * @package Cake.Test.Case.Model */ class TheVoid extends CakeTestModel { /** * name property * * @var string */ public $name = 'TheVoid'; /** * useTable property * * @var bool */ public $useTable = false; } /** * ValidationTest1 class * * @package Cake.Test.Case.Model */ class ValidationTest1 extends CakeTestModel { /** * name property * * @var string */ public $name = 'ValidationTest1'; /** * useTable property * * @var bool */ public $useTable = false; /** * schema property * * @var array */ protected $_schema = array(); /** * validate property * * @var array */ public $validate = array( 'title' => 'notBlank', 'published' => 'customValidationMethod', 'body' => array( 'notBlank', '/^.{5,}$/s' => 'no matchy', '/^[0-9A-Za-z \\.]{1,}$/s' ) ); /** * customValidationMethod method * * @param mixed $data * @return void */ public function customValidationMethod($data) { return $data === 1; } /** * Custom validator with parameters + default values * * @return array */ public function customValidatorWithParams($data, $validator, $or = true, $ignoreOnSame = 'id') { $this->validatorParams = get_defined_vars(); unset($this->validatorParams['this']); return true; } /** * Custom validator with message * * @return array */ public function customValidatorWithMessage($data) { return 'This field will *never* validate! Muhahaha!'; } /** * Test validation with many parameters * * @return void */ public function customValidatorWithSixParams($data, $one = 1, $two = 2, $three = 3, $four = 4, $five = 5, $six = 6) { $this->validatorParams = get_defined_vars(); unset($this->validatorParams['this']); return true; } } /** * ValidationTest2 class * * @package Cake.Test.Case.Model */ class ValidationTest2 extends CakeTestModel { /** * name property * * @var string */ public $name = 'ValidationTest2'; /** * useTable property * * @var bool */ public $useTable = false; /** * validate property * * @var array */ public $validate = array( 'title' => 'notBlank', 'published' => 'customValidationMethod', 'body' => array( 'notBlank', '/^.{5,}$/s' => 'no matchy', '/^[0-9A-Za-z \\.]{1,}$/s' ) ); /** * customValidationMethod method * * @param mixed $data * @return void */ public function customValidationMethod($data) { return $data === 1; } /** * schema method * * @return void */ public function schema($field = false) { return array(); } } /** * Person class * * @package Cake.Test.Case.Model */ class Person extends CakeTestModel { /** * name property * * @var string */ public $name = 'Person'; /** * belongsTo property * * @var array */ public $belongsTo = array( 'Mother' => array( 'className' => 'Person', 'foreignKey' => 'mother_id' ), 'Father' => array( 'className' => 'Person', 'foreignKey' => 'father_id' ) ); } /** * UnderscoreField class * * @package Cake.Test.Case.Model */ class UnderscoreField extends CakeTestModel { /** * name property * * @var string */ public $name = 'UnderscoreField'; } /** * Product class * * @package Cake.Test.Case.Model */ class Product extends CakeTestModel { /** * name property * * @var string */ public $name = 'Product'; } /** * Story class * * @package Cake.Test.Case.Model */ class Story extends CakeTestModel { /** * name property * * @var string */ public $name = 'Story'; /** * primaryKey property * * @var string */ public $primaryKey = 'story'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('Tag' => array('foreignKey' => 'story')); /** * validate property * * @var array */ public $validate = array('title' => 'notBlank'); } /** * Cd class * * @package Cake.Test.Case.Model */ class Cd extends CakeTestModel { /** * name property * * @var string */ public $name = 'Cd'; /** * hasOne property * * @var array */ public $hasOne = array( 'OverallFavorite' => array( 'foreignKey' => 'model_id', 'dependent' => true, 'conditions' => array('model_type' => 'Cd') ) ); } /** * Book class * * @package Cake.Test.Case.Model */ class Book extends CakeTestModel { /** * name property * * @var string */ public $name = 'Book'; /** * hasOne property * * @var array */ public $hasOne = array( 'OverallFavorite' => array( 'foreignKey' => 'model_id', 'dependent' => true, 'conditions' => 'OverallFavorite.model_type = \'Book\'' ) ); } /** * OverallFavorite class * * @package Cake.Test.Case.Model */ class OverallFavorite extends CakeTestModel { /** * name property * * @var string */ public $name = 'OverallFavorite'; } /** * MyUser class * * @package Cake.Test.Case.Model */ class MyUser extends CakeTestModel { /** * name property * * @var string */ public $name = 'MyUser'; /** * undocumented variable * * @var string */ public $hasAndBelongsToMany = array('MyCategory'); } /** * MyCategory class * * @package Cake.Test.Case.Model */ class MyCategory extends CakeTestModel { /** * name property * * @var string */ public $name = 'MyCategory'; /** * undocumented variable * * @var string */ public $hasAndBelongsToMany = array('MyProduct', 'MyUser'); } /** * MyProduct class * * @package Cake.Test.Case.Model */ class MyProduct extends CakeTestModel { /** * name property * * @var string */ public $name = 'MyProduct'; /** * undocumented variable * * @var string */ public $hasAndBelongsToMany = array('MyCategory'); } /** * MyCategoriesMyUser class * * @package Cake.Test.Case.Model */ class MyCategoriesMyUser extends CakeTestModel { /** * name property * * @var string */ public $name = 'MyCategoriesMyUser'; } /** * MyCategoriesMyProduct class * * @package Cake.Test.Case.Model */ class MyCategoriesMyProduct extends CakeTestModel { /** * name property * * @var string */ public $name = 'MyCategoriesMyProduct'; } /** * NumberTree class * * @package Cake.Test.Case.Model */ class NumberTree extends CakeTestModel { /** * name property * * @var string */ public $name = 'NumberTree'; /** * actsAs property * * @var array */ public $actsAs = array('Tree'); /** * initialize method * * @param int $levelLimit * @param int $childLimit * @param mixed $currentLevel * @param mixed $parent_id * @param string $prefix * @param bool $hierarchal * @return void */ public function initialize($levelLimit = 3, $childLimit = 3, $currentLevel = null, $parentId = null, $prefix = '1', $hierarchal = true) { if (!$parentId) { $db = ConnectionManager::getDataSource($this->useDbConfig); $db->truncate($this->table); $this->save(array($this->name => array('name' => '1. Root'))); $this->initialize($levelLimit, $childLimit, 1, $this->id, '1', $hierarchal); $this->create(array()); } if (!$currentLevel || $currentLevel > $levelLimit) { return; } for ($i = 1; $i <= $childLimit; $i++) { $name = $prefix . '.' . $i; $data = array($this->name => array('name' => $name)); $this->create($data); if ($hierarchal) { if ($this->name === 'UnconventionalTree') { $data[$this->name]['join'] = $parentId; } else { $data[$this->name]['parent_id'] = $parentId; } } $this->save($data); $this->initialize($levelLimit, $childLimit, $currentLevel + 1, $this->id, $name, $hierarchal); } } } /** * NumberTreeTwo class * * @package Cake.Test.Case.Model */ class NumberTreeTwo extends NumberTree { /** * name property * * @var string */ public $name = 'NumberTreeTwo'; /** * actsAs property * * @var array */ public $actsAs = array(); } /** * FlagTree class * * @package Cake.Test.Case.Model */ class FlagTree extends NumberTree { /** * name property * * @var string */ public $name = 'FlagTree'; } /** * UnconventionalTree class * * @package Cake.Test.Case.Model */ class UnconventionalTree extends NumberTree { /** * name property * * @var string */ public $name = 'UnconventionalTree'; public $actsAs = array( 'Tree' => array( 'parent' => 'join', 'left' => 'left', 'right' => 'right' ) ); } /** * UuidTree class * * @package Cake.Test.Case.Model */ class UuidTree extends NumberTree { /** * name property * * @var string */ public $name = 'UuidTree'; } /** * Campaign class * * @package Cake.Test.Case.Model */ class Campaign extends CakeTestModel { /** * name property * * @var string */ public $name = 'Campaign'; /** * hasMany property * * @var array */ public $hasMany = array('Ad' => array('fields' => array('id', 'campaign_id', 'name'))); } /** * Ad class * * @package Cake.Test.Case.Model */ class Ad extends CakeTestModel { /** * name property * * @var string */ public $name = 'Ad'; /** * actsAs property * * @var array */ public $actsAs = array('Tree'); /** * belongsTo property * * @var array */ public $belongsTo = array('Campaign'); } /** * AfterTree class * * @package Cake.Test.Case.Model */ class AfterTree extends NumberTree { /** * name property * * @var string */ public $name = 'AfterTree'; /** * actsAs property * * @var array */ public $actsAs = array('Tree'); /** * @param bool $created * @param array $options * @return void */ public function afterSave($created, $options = array()) { if ($created && isset($this->data['AfterTree'])) { $this->data['AfterTree']['name'] = 'Six and One Half Changed in AfterTree::afterSave() but not in database'; } } } /** * Nonconformant Content class * * @package Cake.Test.Case.Model */ class Content extends CakeTestModel { /** * name property * * @var string */ public $name = 'Content'; /** * useTable property * * @var string */ public $useTable = 'Content'; /** * primaryKey property * * @var string */ public $primaryKey = 'iContentId'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('Account' => array('className' => 'Account', 'with' => 'ContentAccount', 'joinTable' => 'ContentAccounts', 'foreignKey' => 'iContentId', 'associationForeignKey', 'iAccountId')); } /** * Nonconformant Account class * * @package Cake.Test.Case.Model */ class Account extends CakeTestModel { /** * name property * * @var string */ public $name = 'Account'; /** * useTable property * * @var string */ public $useTable = 'Accounts'; /** * primaryKey property * * @var string */ public $primaryKey = 'iAccountId'; } /** * Nonconformant ContentAccount class * * @package Cake.Test.Case.Model */ class ContentAccount extends CakeTestModel { /** * name property * * @var string */ public $name = 'ContentAccount'; /** * useTable property * * @var string */ public $useTable = 'ContentAccounts'; /** * primaryKey property * * @var string */ public $primaryKey = 'iContentAccountsId'; } /** * FilmFile class * * @package Cake.Test.Case.Model */ class FilmFile extends CakeTestModel { public $name = 'FilmFile'; } /** * Basket test model * * @package Cake.Test.Case.Model */ class Basket extends CakeTestModel { public $name = 'Basket'; public $belongsTo = array( 'FilmFile' => array( 'className' => 'FilmFile', 'foreignKey' => 'object_id', 'conditions' => "Basket.type = 'file'", 'fields' => '', 'order' => '' ) ); } /** * TestPluginArticle class * * @package Cake.Test.Case.Model */ class TestPluginArticle extends CakeTestModel { /** * name property * * @var string */ public $name = 'TestPluginArticle'; /** * belongsTo property * * @var array */ public $belongsTo = array('User'); /** * hasMany property * * @var array */ public $hasMany = array( 'TestPluginComment' => array( 'className' => 'TestPlugin.TestPluginComment', 'foreignKey' => 'article_id', 'dependent' => true ) ); } /** * TestPluginComment class * * @package Cake.Test.Case.Model */ class TestPluginComment extends CakeTestModel { /** * name property * * @var string */ public $name = 'TestPluginComment'; /** * belongsTo property * * @var array */ public $belongsTo = array( 'TestPluginArticle' => array( 'className' => 'TestPlugin.TestPluginArticle', 'foreignKey' => 'article_id', ), 'TestPlugin.User' ); } /** * Uuidportfolio class * * @package Cake.Test.Case.Model */ class Uuidportfolio extends CakeTestModel { /** * name property * * @var string */ public $name = 'Uuidportfolio'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('Uuiditem'); } /** * Uuiditem class * * @package Cake.Test.Case.Model */ class Uuiditem extends CakeTestModel { /** * name property * * @var string */ public $name = 'Uuiditem'; /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('Uuidportfolio' => array('with' => 'UuiditemsUuidportfolioNumericid')); } /** * UuiditemsPortfolio class * * @package Cake.Test.Case.Model */ class UuiditemsUuidportfolio extends CakeTestModel { /** * name property * * @var string */ public $name = 'UuiditemsUuidportfolio'; } /** * UuiditemsPortfolioNumericid class * * @package Cake.Test.Case.Model */ class UuiditemsUuidportfolioNumericid extends CakeTestModel { /** * name property * * @var string */ public $name = 'UuiditemsUuidportfolioNumericid'; } /** * TranslateTestModel class. * * @package Cake.Test.Case.Model */ class TranslateTestModel extends CakeTestModel { /** * name property * * @var string */ public $name = 'TranslateTestModel'; /** * useTable property * * @var string */ public $useTable = 'i18n'; /** * displayField property * * @var string */ public $displayField = 'field'; } /** * TranslateTestModel class. * * @package Cake.Test.Case.Model */ class TranslateWithPrefix extends CakeTestModel { /** * name property * * @var string */ public $name = 'TranslateWithPrefix'; /** * tablePrefix property * * @var string */ public $tablePrefix = 'i18n_'; /** * displayField property * * @var string */ public $displayField = 'field'; } /** * TranslatedItem class. * * @package Cake.Test.Case.Model */ class TranslatedItem extends CakeTestModel { /** * name property * * @var string */ public $name = 'TranslatedItem'; /** * cacheQueries property * * @var bool */ public $cacheQueries = false; /** * actsAs property * * @var array */ public $actsAs = array('Translate' => array('content', 'title')); /** * translateModel property * * @var string */ public $translateModel = 'TranslateTestModel'; } /** * TranslatedItem class. * * @package Cake.Test.Case.Model */ class TranslatedItem2 extends CakeTestModel { /** * name property * * @var string */ public $name = 'TranslatedItem'; /** * cacheQueries property * * @var bool */ public $cacheQueries = false; /** * actsAs property * * @var array */ public $actsAs = array('Translate' => array('content', 'title')); /** * translateModel property * * @var string */ public $translateModel = 'TranslateWithPrefix'; } /** * TranslatedItemWithTable class. * * @package Cake.Test.Case.Model */ class TranslatedItemWithTable extends CakeTestModel { /** * name property * * @var string */ public $name = 'TranslatedItemWithTable'; /** * useTable property * * @var string */ public $useTable = 'translated_items'; /** * cacheQueries property * * @var bool */ public $cacheQueries = false; /** * actsAs property * * @var array */ public $actsAs = array('Translate' => array('content', 'title')); /** * translateModel property * * @var string */ public $translateModel = 'TranslateTestModel'; /** * translateTable property * * @var string */ public $translateTable = 'another_i18n'; } /** * TranslateArticleModel class. * * @package Cake.Test.Case.Model */ class TranslateArticleModel extends CakeTestModel { /** * name property * * @var string */ public $name = 'TranslateArticleModel'; /** * useTable property * * @var string */ public $useTable = 'article_i18n'; /** * displayField property * * @var string */ public $displayField = 'field'; } /** * TranslatedArticle class. * * @package Cake.Test.Case.Model */ class TranslatedArticle extends CakeTestModel { /** * name property * * @var string */ public $name = 'TranslatedArticle'; /** * cacheQueries property * * @var bool */ public $cacheQueries = false; /** * actsAs property * * @var array */ public $actsAs = array('Translate' => array('title', 'body')); /** * translateModel property * * @var string */ public $translateModel = 'TranslateArticleModel'; /** * belongsTo property * * @var array */ public $belongsTo = array('User'); /** * hasMany property * * @var array */ public $hasMany = array('TranslatedItem'); } class CounterCacheUser extends CakeTestModel { public $name = 'CounterCacheUser'; public $alias = 'User'; public $hasMany = array( 'Post' => array( 'className' => 'CounterCachePost', 'foreignKey' => 'user_id' ) ); } class CounterCachePost extends CakeTestModel { public $name = 'CounterCachePost'; public $alias = 'Post'; public $belongsTo = array( 'User' => array( 'className' => 'CounterCacheUser', 'foreignKey' => 'user_id', 'counterCache' => true ) ); } class CounterCacheUserNonstandardPrimaryKey extends CakeTestModel { public $name = 'CounterCacheUserNonstandardPrimaryKey'; public $alias = 'User'; public $primaryKey = 'uid'; public $hasMany = array( 'Post' => array( 'className' => 'CounterCachePostNonstandardPrimaryKey', 'foreignKey' => 'uid' ) ); } class CounterCachePostNonstandardPrimaryKey extends CakeTestModel { public $name = 'CounterCachePostNonstandardPrimaryKey'; public $alias = 'Post'; public $primaryKey = 'pid'; public $belongsTo = array( 'User' => array( 'className' => 'CounterCacheUserNonstandardPrimaryKey', 'foreignKey' => 'uid', 'counterCache' => true ) ); } class ArticleB extends CakeTestModel { public $name = 'ArticleB'; public $useTable = 'articles'; public $hasAndBelongsToMany = array( 'TagB' => array( 'className' => 'TagB', 'joinTable' => 'articles_tags', 'foreignKey' => 'article_id', 'associationForeignKey' => 'tag_id' ) ); } class TagB extends CakeTestModel { public $name = 'TagB'; public $useTable = 'tags'; public $hasAndBelongsToMany = array( 'ArticleB' => array( 'className' => 'ArticleB', 'joinTable' => 'articles_tags', 'foreignKey' => 'tag_id', 'associationForeignKey' => 'article_id' ) ); } class Fruit extends CakeTestModel { public $name = 'Fruit'; public $hasAndBelongsToMany = array( 'UuidTag' => array( 'className' => 'UuidTag', 'joinTable' => 'fruits_uuid_tags', 'foreignKey' => 'fruit_id', 'associationForeignKey' => 'uuid_tag_id', 'with' => 'FruitsUuidTag' ) ); } class FruitsUuidTag extends CakeTestModel { public $name = 'FruitsUuidTag'; public $primaryKey = false; public $belongsTo = array( 'UuidTag' => array( 'className' => 'UuidTag', 'foreignKey' => 'uuid_tag_id', ), 'Fruit' => array( 'className' => 'Fruit', 'foreignKey' => 'fruit_id', ) ); } class UuidTag extends CakeTestModel { public $name = 'UuidTag'; public $hasAndBelongsToMany = array( 'Fruit' => array( 'className' => 'Fruit', 'joinTable' => 'fruits_uuid_tags', 'foreign_key' => 'uuid_tag_id', 'associationForeignKey' => 'fruit_id', 'with' => 'FruitsUuidTag' ) ); } class FruitNoWith extends CakeTestModel { public $name = 'Fruit'; public $useTable = 'fruits'; public $hasAndBelongsToMany = array( 'UuidTag' => array( 'className' => 'UuidTagNoWith', 'joinTable' => 'fruits_uuid_tags', 'foreignKey' => 'fruit_id', 'associationForeignKey' => 'uuid_tag_id', ) ); } class UuidTagNoWith extends CakeTestModel { public $name = 'UuidTag'; public $useTable = 'uuid_tags'; public $hasAndBelongsToMany = array( 'Fruit' => array( 'className' => 'FruitNoWith', 'joinTable' => 'fruits_uuid_tags', 'foreign_key' => 'uuid_tag_id', 'associationForeignKey' => 'fruit_id', ) ); } class ProductUpdateAll extends CakeTestModel { public $name = 'ProductUpdateAll'; public $useTable = 'product_update_all'; } class GroupUpdateAll extends CakeTestModel { public $name = 'GroupUpdateAll'; public $useTable = 'group_update_all'; } class TransactionTestModel extends CakeTestModel { public $name = 'TransactionTestModel'; public $useTable = 'samples'; public function afterSave($created, $options = array()) { $data = array( array('apple_id' => 1, 'name' => 'sample6'), ); $this->saveAll($data, array('atomic' => true, 'callbacks' => false)); } } class TransactionManyTestModel extends CakeTestModel { public $name = 'TransactionManyTestModel'; public $useTable = 'samples'; public function afterSave($created, $options = array()) { $data = array( array('apple_id' => 1, 'name' => 'sample6'), ); $this->saveMany($data, array('atomic' => true, 'callbacks' => false)); } } class Site extends CakeTestModel { public $name = 'Site'; public $useTable = 'sites'; public $hasAndBelongsToMany = array( 'Domain' => array('unique' => 'keepExisting'), ); } class Domain extends CakeTestModel { public $name = 'Domain'; public $useTable = 'domains'; public $hasAndBelongsToMany = array( 'Site' => array('unique' => 'keepExisting'), ); } /** * TestModel class * * @package Cake.Test.Case.Model */ class TestModel extends CakeTestModel { /** * name property * * @var string */ public $name = 'TestModel'; /** * useTable property * * @var bool */ public $useTable = false; /** * schema property * * @var array */ protected $_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'client_id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '11'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'login' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'passwd' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'), 'addr_1' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'), 'addr_2' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '25'), 'zip_code' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'city' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'country' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'phone' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'fax' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'url' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'), 'email' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'comments' => array('type' => 'text', 'null' => '1', 'default' => '', 'length' => '155'), 'last_login' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => ''), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); /** * find method * * @param mixed $conditions * @param mixed $fields * @param mixed $order * @param mixed $recursive * @return void */ public function find($conditions = null, $fields = null, $order = null, $recursive = null) { return array($conditions, $fields); } /** * findAll method * * @param mixed $conditions * @param mixed $fields * @param mixed $order * @param mixed $recursive * @return void */ public function findAll($conditions = null, $fields = null, $order = null, $recursive = null) { return $conditions; } } /** * TestModel2 class * * @package Cake.Test.Case.Model */ class TestModel2 extends CakeTestModel { /** * name property * * @var string */ public $name = 'TestModel2'; /** * useTable property * * @var bool */ public $useTable = false; } /** * TestModel4 class * * @package Cake.Test.Case.Model */ class TestModel3 extends CakeTestModel { /** * name property * * @var string */ public $name = 'TestModel3'; /** * useTable property * * @var bool */ public $useTable = false; } /** * TestModel4 class * * @package Cake.Test.Case.Model */ class TestModel4 extends CakeTestModel { /** * name property * * @var string */ public $name = 'TestModel4'; /** * table property * * @var string */ public $table = 'test_model4'; /** * useTable property * * @var bool */ public $useTable = false; /** * belongsTo property * * @var array */ public $belongsTo = array( 'TestModel4Parent' => array( 'className' => 'TestModel4', 'foreignKey' => 'parent_id' ) ); /** * hasOne property * * @var array */ public $hasOne = array( 'TestModel5' => array( 'className' => 'TestModel5', 'foreignKey' => 'test_model4_id' ) ); /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('TestModel7' => array( 'className' => 'TestModel7', 'joinTable' => 'test_model4_test_model7', 'foreignKey' => 'test_model4_id', 'associationForeignKey' => 'test_model7_id', 'with' => 'TestModel4TestModel7' )); /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); } return $this->_schema; } } /** * TestModel4TestModel7 class * * @package Cake.Test.Case.Model */ class TestModel4TestModel7 extends CakeTestModel { /** * name property * * @var string */ public $name = 'TestModel4TestModel7'; /** * table property * * @var string */ public $table = 'test_model4_test_model7'; /** * useTable property * * @var bool */ public $useTable = false; /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'test_model4_id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'test_model7_id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8') ); } return $this->_schema; } } /** * TestModel5 class * * @package Cake.Test.Case.Model */ class TestModel5 extends CakeTestModel { /** * name property * * @var string */ public $name = 'TestModel5'; /** * table property * * @var string */ public $table = 'test_model5'; /** * useTable property * * @var bool */ public $useTable = false; /** * belongsTo property * * @var array */ public $belongsTo = array('TestModel4' => array( 'className' => 'TestModel4', 'foreignKey' => 'test_model4_id' )); /** * hasMany property * * @var array */ public $hasMany = array('TestModel6' => array( 'className' => 'TestModel6', 'foreignKey' => 'test_model5_id' )); /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'test_model4_id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); } return $this->_schema; } } /** * TestModel6 class * * @package Cake.Test.Case.Model */ class TestModel6 extends CakeTestModel { /** * name property * * @var string */ public $name = 'TestModel6'; /** * table property * * @var string */ public $table = 'test_model6'; /** * useTable property * * @var bool */ public $useTable = false; /** * belongsTo property * * @var array */ public $belongsTo = array( 'TestModel5' => array( 'className' => 'TestModel5', 'foreignKey' => 'test_model5_id' ) ); /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'test_model5_id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); } return $this->_schema; } } /** * TestModel7 class * * @package Cake.Test.Case.Model */ class TestModel7 extends CakeTestModel { /** * name property * * @var string */ public $name = 'TestModel7'; /** * table property * * @var string */ public $table = 'test_model7'; /** * useTable property * * @var bool */ public $useTable = false; /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); } return $this->_schema; } } /** * TestModel8 class * * @package Cake.Test.Case.Model */ class TestModel8 extends CakeTestModel { /** * name property * * @var string */ public $name = 'TestModel8'; /** * table property * * @var string */ public $table = 'test_model8'; /** * useTable property * * @var bool */ public $useTable = false; /** * hasOne property * * @var array */ public $hasOne = array( 'TestModel9' => array( 'className' => 'TestModel9', 'foreignKey' => 'test_model8_id', 'conditions' => 'TestModel9.name != \'mariano\'' ) ); /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'test_model9_id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); } return $this->_schema; } } /** * TestModel9 class * * @package Cake.Test.Case.Model */ class TestModel9 extends CakeTestModel { /** * name property * * @var string */ public $name = 'TestModel9'; /** * table property * * @var string */ public $table = 'test_model9'; /** * useTable property * * @var bool */ public $useTable = false; /** * belongsTo property * * @var array */ public $belongsTo = array( 'TestModel8' => array( 'className' => 'TestModel8', 'foreignKey' => 'test_model8_id', 'conditions' => 'TestModel8.name != \'larry\'' ) ); /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'test_model8_id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '11'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); } return $this->_schema; } } /** * Level class * * @package Cake.Test.Case.Model */ class Level extends CakeTestModel { /** * name property * * @var string */ public $name = 'Level'; /** * table property * * @var string */ public $table = 'level'; /** * useTable property * * @var bool */ public $useTable = false; /** * hasMany property * * @var array */ public $hasMany = array( 'Group' => array( 'className' => 'Group' ), 'User2' => array( 'className' => 'User2' ) ); /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => '10'), 'name' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => '20'), ); } return $this->_schema; } } /** * Group class * * @package Cake.Test.Case.Model */ class Group extends CakeTestModel { /** * name property * * @var string */ public $name = 'Group'; /** * table property * * @var string */ public $table = 'group'; /** * useTable property * * @var bool */ public $useTable = false; /** * belongsTo property * * @var array */ public $belongsTo = array('Level'); /** * hasMany property * * @var array */ public $hasMany = array('Category2', 'User2'); /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => '10'), 'level_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => '10'), 'name' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => '20'), ); } return $this->_schema; } } /** * User2 class * * @package Cake.Test.Case.Model */ class User2 extends CakeTestModel { /** * name property * * @var string */ public $name = 'User2'; /** * table property * * @var string */ public $table = 'user'; /** * useTable property * * @var bool */ public $useTable = false; /** * belongsTo property * * @var array */ public $belongsTo = array( 'Group' => array( 'className' => 'Group' ), 'Level' => array( 'className' => 'Level' ) ); /** * hasMany property * * @var array */ public $hasMany = array( 'Article2' => array( 'className' => 'Article2' ), ); /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => '10'), 'group_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => '10'), 'level_id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => '10'), 'name' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => '20'), ); } return $this->_schema; } } /** * Category2 class * * @package Cake.Test.Case.Model */ class Category2 extends CakeTestModel { /** * name property * * @var string */ public $name = 'Category2'; /** * table property * * @var string */ public $table = 'category'; /** * useTable property * * @var bool */ public $useTable = false; /** * belongsTo property * * @var array */ public $belongsTo = array( 'Group' => array( 'className' => 'Group', 'foreignKey' => 'group_id' ), 'ParentCat' => array( 'className' => 'Category2', 'foreignKey' => 'parent_id' ) ); /** * hasMany property * * @var array */ public $hasMany = array( 'ChildCat' => array( 'className' => 'Category2', 'foreignKey' => 'parent_id' ), 'Article2' => array( 'className' => 'Article2', 'order' => 'Article2.published_date DESC', 'foreignKey' => 'category_id', 'limit' => '3') ); /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => '', 'length' => '10'), 'group_id' => array('type' => 'integer', 'null' => false, 'default' => '', 'length' => '10'), 'parent_id' => array('type' => 'integer', 'null' => false, 'default' => '', 'length' => '10'), 'name' => array('type' => 'string', 'null' => false, 'default' => '', 'length' => '255'), 'icon' => array('type' => 'string', 'null' => false, 'default' => '', 'length' => '255'), 'description' => array('type' => 'text', 'null' => false, 'default' => '', 'length' => null), ); } return $this->_schema; } } /** * Article2 class * * @package Cake.Test.Case.Model */ class Article2 extends CakeTestModel { /** * name property * * @var string */ public $name = 'Article2'; /** * table property * * @var string */ public $table = 'articles'; /** * useTable property * * @var bool */ public $useTable = false; /** * belongsTo property * * @var array */ public $belongsTo = array( 'Category2' => array('className' => 'Category2'), 'User2' => array('className' => 'User2') ); /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => '', 'length' => '10'), 'category_id' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => '10'), 'user_id' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => '10'), 'rate_count' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => '10'), 'rate_sum' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => '10'), 'viewed' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => '10'), 'version' => array('type' => 'string', 'null' => true, 'default' => '', 'length' => '45'), 'title' => array('type' => 'string', 'null' => false, 'default' => '', 'length' => '200'), 'intro' => array('text' => 'string', 'null' => true, 'default' => '', 'length' => null), 'comments' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => '4'), 'body' => array('text' => 'string', 'null' => true, 'default' => '', 'length' => null), 'isdraft' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'length' => '1'), 'allow_comments' => array('type' => 'boolean', 'null' => false, 'default' => '1', 'length' => '1'), 'moderate_comments' => array('type' => 'boolean', 'null' => false, 'default' => '1', 'length' => '1'), 'published' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'length' => '1'), 'multipage' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'length' => '1'), 'published_date' => array('type' => 'datetime', 'null' => true, 'default' => '', 'length' => null), 'created' => array('type' => 'datetime', 'null' => false, 'default' => '0000-00-00 00:00:00', 'length' => null), 'modified' => array('type' => 'datetime', 'null' => false, 'default' => '0000-00-00 00:00:00', 'length' => null) ); } return $this->_schema; } } /** * CategoryFeatured2 class * * @package Cake.Test.Case.Model */ class CategoryFeatured2 extends CakeTestModel { /** * name property * * @var string */ public $name = 'CategoryFeatured2'; /** * table property * * @var string */ public $table = 'category_featured'; /** * useTable property * * @var bool */ public $useTable = false; /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => '', 'length' => '10'), 'parent_id' => array('type' => 'integer', 'null' => false, 'default' => '', 'length' => '10'), 'name' => array('type' => 'string', 'null' => false, 'default' => '', 'length' => '255'), 'icon' => array('type' => 'string', 'null' => false, 'default' => '', 'length' => '255'), 'description' => array('text' => 'string', 'null' => false, 'default' => '', 'length' => null) ); } return $this->_schema; } } /** * Featured2 class * * @package Cake.Test.Case.Model */ class Featured2 extends CakeTestModel { /** * name property * * @var string */ public $name = 'Featured2'; /** * table property * * @var string */ public $table = 'featured2'; /** * useTable property * * @var bool */ public $useTable = false; /** * belongsTo property * * @var array */ public $belongsTo = array( 'CategoryFeatured2' => array( 'className' => 'CategoryFeatured2' ) ); /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => '10'), 'article_id' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => '10'), 'category_id' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => '10'), 'name' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => '20') ); } return $this->_schema; } } /** * Comment2 class * * @package Cake.Test.Case.Model */ class Comment2 extends CakeTestModel { /** * name property * * @var string */ public $name = 'Comment2'; /** * table property * * @var string */ public $table = 'comment'; /** * belongsTo property * * @var array */ public $belongsTo = array('ArticleFeatured2', 'User2'); /** * useTable property * * @var bool */ public $useTable = false; /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => '10'), 'article_featured_id' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => '10'), 'user_id' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => '10'), 'name' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => '20') ); } return $this->_schema; } } /** * ArticleFeatured2 class * * @package Cake.Test.Case.Model */ class ArticleFeatured2 extends CakeTestModel { /** * name property * * @var string */ public $name = 'ArticleFeatured2'; /** * table property * * @var string */ public $table = 'article_featured'; /** * useTable property * * @var bool */ public $useTable = false; /** * belongsTo property * * @var array */ public $belongsTo = array( 'CategoryFeatured2' => array('className' => 'CategoryFeatured2'), 'User2' => array('className' => 'User2') ); /** * hasOne property * * @var array */ public $hasOne = array( 'Featured2' => array('className' => 'Featured2') ); /** * hasMany property * * @var array */ public $hasMany = array( 'Comment2' => array('className' => 'Comment2', 'dependent' => true) ); /** * schema method * * @return void */ public function schema($field = false) { if (!isset($this->_schema)) { $this->_schema = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => null, 'length' => '10'), 'category_featured_id' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => '10'), 'user_id' => array('type' => 'integer', 'null' => false, 'default' => '0', 'length' => '10'), 'title' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => '20'), 'body' => array('text' => 'string', 'null' => true, 'default' => '', 'length' => null), 'published' => array('type' => 'boolean', 'null' => false, 'default' => '0', 'length' => '1'), 'published_date' => array('type' => 'datetime', 'null' => true, 'default' => '', 'length' => null), 'created' => array('type' => 'datetime', 'null' => false, 'default' => '0000-00-00 00:00:00', 'length' => null), 'modified' => array('type' => 'datetime', 'null' => false, 'default' => '0000-00-00 00:00:00', 'length' => null) ); } return $this->_schema; } } /** * MysqlTestModel class * * @package Cake.Test.Case.Model */ class MysqlTestModel extends Model { /** * name property * * @var string */ public $name = 'MysqlTestModel'; /** * useTable property * * @var bool */ public $useTable = false; /** * find method * * @param mixed $conditions * @param mixed $fields * @param mixed $order * @param mixed $recursive * @return void */ public function find($conditions = null, $fields = null, $order = null, $recursive = null) { return $conditions; } /** * findAll method * * @param mixed $conditions * @param mixed $fields * @param mixed $order * @param mixed $recursive * @return void */ public function findAll($conditions = null, $fields = null, $order = null, $recursive = null) { return $conditions; } /** * schema method * * @return void */ public function schema($field = false) { return array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'client_id' => array('type' => 'integer', 'null' => '', 'default' => '0', 'length' => '11'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'login' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'passwd' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'), 'addr_1' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'), 'addr_2' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '25'), 'zip_code' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'city' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'country' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'phone' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'fax' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'url' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '255'), 'email' => array('type' => 'string', 'null' => '1', 'default' => '', 'length' => '155'), 'comments' => array('type' => 'text', 'null' => '1', 'default' => '', 'length' => ''), 'last_login' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => ''), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); } } /** * Test model for datasource prefixes */ class PrefixTestModel extends CakeTestModel { } class PrefixTestUseTableModel extends CakeTestModel { public $name = 'PrefixTest'; public $useTable = 'prefix_tests'; } /** * ScaffoldMock class * * @package Cake.Test.Case.Controller */ class ScaffoldMock extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'articles'; /** * belongsTo property * * @var array */ public $belongsTo = array( 'User' => array( 'className' => 'ScaffoldUser', 'foreignKey' => 'user_id', ) ); /** * hasMany property * * @var array */ public $hasMany = array( 'Comment' => array( 'className' => 'ScaffoldComment', 'foreignKey' => 'article_id', ) ); /** * hasAndBelongsToMany property * * @var string */ public $hasAndBelongsToMany = array( 'ScaffoldTag' => array( 'className' => 'ScaffoldTag', 'foreignKey' => 'something_id', 'associationForeignKey' => 'something_else_id', 'joinTable' => 'join_things' ) ); } /** * ScaffoldUser class * * @package Cake.Test.Case.Controller */ class ScaffoldUser extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'users'; /** * hasMany property * * @var array */ public $hasMany = array( 'Article' => array( 'className' => 'ScaffoldMock', 'foreignKey' => 'article_id', ) ); } /** * ScaffoldComment class * * @package Cake.Test.Case.Controller */ class ScaffoldComment extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'comments'; /** * belongsTo property * * @var array */ public $belongsTo = array( 'Article' => array( 'className' => 'ScaffoldMock', 'foreignKey' => 'article_id', ) ); } /** * ScaffoldTag class * * @package Cake.Test.Case.Controller */ class ScaffoldTag extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'tags'; } /** * Player class * * @package Cake.Test.Case.Model */ class Player extends CakeTestModel { public $hasAndBelongsToMany = array( 'Guild' => array( 'with' => 'GuildsPlayer', 'unique' => true, ), ); } /** * Guild class * * @package Cake.Test.Case.Model */ class Guild extends CakeTestModel { public $hasAndBelongsToMany = array( 'Player' => array( 'with' => 'GuildsPlayer', 'unique' => true, ), ); } /** * GuildsPlayer class * * @package Cake.Test.Case.Model */ class GuildsPlayer extends CakeTestModel { public $useDbConfig = 'test2'; public $belongsTo = array( 'Player', 'Guild', ); } /** * Armor class * * @package Cake.Test.Case.Model */ class Armor extends CakeTestModel { public $useDbConfig = 'test2'; public $hasAndBelongsToMany = array( 'Player' => array('with' => 'ArmorsPlayer'), ); } /** * ArmorsPlayer class * * @package Cake.Test.Case.Model */ class ArmorsPlayer extends CakeTestModel { public $useDbConfig = 'test_database_three'; } /** * CustomArticle class * * @package Cake.Test.Case.Model */ class CustomArticle extends AppModel { /** * useTable property * * @var string */ public $useTable = 'articles'; /** * findMethods property * * @var array */ public $findMethods = array('unPublished' => true); /** * belongsTo property * * @var array */ public $belongsTo = array('User'); /** * _findUnPublished custom find * * @return array */ protected function _findUnPublished($state, $query, $results = array()) { if ($state === 'before') { $query['conditions']['published'] = 'N'; return $query; } return $results; } /** * Alters title data * * @param array $options Options passed from Model::save(). * @return bool True if validate operation should continue, false to abort * @see Model::save() */ public function beforeValidate($options = array()) { $this->data[$this->alias]['title'] = 'foo'; if ($this->findMethods['unPublished'] === true) { $this->findMethods['unPublished'] = false; } else { $this->findMethods['unPublished'] = 'true again'; } } } /** * Example class * * @package Cake.Test.Case.Model */ class Example extends AppModel { /** * useTable property * * @var string */ public $useTable = false; /** * schema property * * @var array */ protected $_schema = array( 'filefield' => array( 'type' => 'string', 'length' => 254, 'default' => null, 'null' => true, 'comment' => null ), ); } /** * UserHasOneArticle class * * @package Cake.Test.Case.Model */ class UserHasOneArticle extends AppModel { /** * useTable property * * @var string */ public $useTable = 'users'; /** * hasOne property * * @var array */ public $hasOne = array('Article'); } /** * ArticlesTagBelongsToArticle class * * @package Cake.Test.Case.Model */ class ArticlesTagBelongsToArticle extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'articles_tags'; /** * belongsTo property * * @var array */ public $belongsTo = array('Article'); } cakephp-2.8.0/lib/Cake/Test/Case/Network/000077500000000000000000000000001265552240500177765ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Network/CakeRequestTest.php000066400000000000000000002110501265552240500235620ustar00rootroot00000000000000_base(); if (empty($url)) { $url = $this->_url(); } if ($url[0] === '/') { $url = substr($url, 1); } $this->url = $url; if ($parseEnvironment) { $this->_processPost(); $this->_processGet(); $this->_processFiles(); } $this->here = $this->base . '/' . $this->url; } } /** * Class CakeRequestTest */ class CakeRequestTest extends CakeTestCase { /** * Setup callback * * @return void */ public function setUp() { parent::setUp(); $this->_app = Configure::read('App'); $this->_case = null; if (isset($_GET['case'])) { $this->_case = $_GET['case']; unset($_GET['case']); } Configure::write('App.baseUrl', false); } /** * TearDown * * @return void */ public function tearDown() { parent::tearDown(); if (!empty($this->_case)) { $_GET['case'] = $this->_case; } Configure::write('App', $this->_app); } /** * Test the header detector. * * @return void */ public function testHeaderDetector() { $request = new CakeRequest('some/path'); $request->addDetector('host', array('header' => array('host' => 'cakephp.org'))); $_SERVER['HTTP_HOST'] = 'cakephp.org'; $this->assertTrue($request->is('host')); $_SERVER['HTTP_HOST'] = 'php.net'; $this->assertFalse($request->is('host')); } /** * Test the accept header detector. * * @return void */ public function testExtensionDetector() { $request = new CakeRequest('some/path'); $request->params['ext'] = 'json'; $this->assertTrue($request->is('json')); $request->params['ext'] = 'xml'; $this->assertFalse($request->is('json')); } /** * Test the accept header detector. * * @return void */ public function testAcceptHeaderDetector() { $request = new CakeRequest('some/path'); $_SERVER['HTTP_ACCEPT'] = 'application/json, text/plain, */*'; $this->assertTrue($request->is('json')); $_SERVER['HTTP_ACCEPT'] = 'text/plain, */*'; $this->assertFalse($request->is('json')); } /** * Test that the autoparse = false constructor works. * * @return void */ public function testNoAutoParseConstruction() { $_GET = array( 'one' => 'param' ); $request = new CakeRequest(null, false); $this->assertFalse(isset($request->query['one'])); } /** * Test construction * * @return void */ public function testConstructionGetParsing() { $_GET = array( 'one' => 'param', 'two' => 'banana' ); $request = new CakeRequest('some/path'); $this->assertEquals($request->query, $_GET); $_GET = array( 'one' => 'param', 'two' => 'banana', ); $request = new CakeRequest('some/path'); $this->assertEquals($request->query, $_GET); $this->assertEquals('some/path', $request->url); } /** * Test that querystring args provided in the URL string are parsed. * * @return void */ public function testQueryStringParsingFromInputUrl() { $_GET = array(); $request = new CakeRequest('some/path?one=something&two=else'); $expected = array('one' => 'something', 'two' => 'else'); $this->assertEquals($expected, $request->query); $this->assertEquals('some/path?one=something&two=else', $request->url); } /** * Test that named arguments + querystrings are handled correctly. * * @return void */ public function testQueryStringAndNamedParams() { $_SERVER['REQUEST_URI'] = '/tasks/index/page:1?ts=123456'; $request = new CakeRequest(); $this->assertEquals('tasks/index/page:1', $request->url); $_SERVER['REQUEST_URI'] = '/tasks/index/page:1/?ts=123456'; $request = new CakeRequest(); $this->assertEquals('tasks/index/page:1/', $request->url); $_SERVER['REQUEST_URI'] = '/some/path?url=http://cakephp.org'; $request = new CakeRequest(); $this->assertEquals('some/path', $request->url); $_SERVER['REQUEST_URI'] = Configure::read('App.fullBaseUrl') . '/other/path?url=http://cakephp.org'; $request = new CakeRequest(); $this->assertEquals('other/path', $request->url); } /** * Test addParams() method * * @return void */ public function testAddParams() { $request = new CakeRequest('some/path'); $request->params = array('controller' => 'posts', 'action' => 'view'); $result = $request->addParams(array('plugin' => null, 'action' => 'index')); $this->assertSame($result, $request, 'Method did not return itself. %s'); $this->assertEquals('posts', $request->controller); $this->assertEquals('index', $request->action); $this->assertEquals(null, $request->plugin); } /** * Test splicing in paths. * * @return void */ public function testAddPaths() { $request = new CakeRequest('some/path'); $request->webroot = '/some/path/going/here/'; $result = $request->addPaths(array( 'random' => '/something', 'webroot' => '/', 'here' => '/', 'base' => '/base_dir' )); $this->assertSame($result, $request, 'Method did not return itself. %s'); $this->assertEquals('/', $request->webroot); $this->assertEquals('/base_dir', $request->base); $this->assertEquals('/', $request->here); $this->assertFalse(isset($request->random)); } /** * Test parsing POST data into the object. * * @return void */ public function testPostParsing() { $_POST = array('data' => array( 'Article' => array('title') )); $request = new CakeRequest('some/path'); $this->assertEquals($_POST['data'], $request->data); $_POST = array('one' => 1, 'two' => 'three'); $request = new CakeRequest('some/path'); $this->assertEquals($_POST, $request->data); $_POST = array( 'data' => array( 'Article' => array('title' => 'Testing'), ), 'action' => 'update' ); $request = new CakeRequest('some/path'); $expected = array( 'Article' => array('title' => 'Testing'), 'action' => 'update' ); $this->assertEquals($expected, $request->data); $_POST = array('data' => array( 'Article' => array('title'), 'Tag' => array('Tag' => array(1, 2)) )); $request = new CakeRequest('some/path'); $this->assertEquals($_POST['data'], $request->data); $_POST = array('data' => array( 'Article' => array('title' => 'some title'), 'Tag' => array('Tag' => array(1, 2)) )); $request = new CakeRequest('some/path'); $this->assertEquals($_POST['data'], $request->data); $_POST = array( 'a' => array(1, 2), 'b' => array(1, 2) ); $request = new CakeRequest('some/path'); $this->assertEquals($_POST, $request->data); } /** * Test parsing PUT data into the object. * * @return void */ public function testPutParsing() { $_SERVER['REQUEST_METHOD'] = 'PUT'; $_SERVER['CONTENT_TYPE'] = 'application/x-www-form-urlencoded; charset=UTF-8'; $data = array('data' => array( 'Article' => array('title') )); $request = $this->getMock('TestCakeRequest', array('_readInput')); $request->expects($this->at(0))->method('_readInput') ->will($this->returnValue('data[Article][]=title')); $request->reConstruct(); $this->assertEquals($data['data'], $request->data); $data = array('one' => 1, 'two' => 'three'); $request = $this->getMock('TestCakeRequest', array('_readInput')); $request->expects($this->at(0))->method('_readInput') ->will($this->returnValue('one=1&two=three')); $request->reConstruct(); $this->assertEquals($data, $request->data); $request = $this->getMock('TestCakeRequest', array('_readInput')); $request->expects($this->at(0))->method('_readInput') ->will($this->returnValue('data[Article][title]=Testing&action=update')); $request->reConstruct(); $expected = array( 'Article' => array('title' => 'Testing'), 'action' => 'update' ); $this->assertEquals($expected, $request->data); $_SERVER['REQUEST_METHOD'] = 'DELETE'; $data = array('data' => array( 'Article' => array('title'), 'Tag' => array('Tag' => array(1, 2)) )); $request = $this->getMock('TestCakeRequest', array('_readInput')); $request->expects($this->at(0))->method('_readInput') ->will($this->returnValue('data[Article][]=title&Tag[Tag][]=1&Tag[Tag][]=2')); $request->reConstruct(); $this->assertEquals($data['data'], $request->data); $data = array('data' => array( 'Article' => array('title' => 'some title'), 'Tag' => array('Tag' => array(1, 2)) )); $request = $this->getMock('TestCakeRequest', array('_readInput')); $request->expects($this->at(0))->method('_readInput') ->will($this->returnValue('data[Article][title]=some%20title&Tag[Tag][]=1&Tag[Tag][]=2')); $request->reConstruct(); $this->assertEquals($data['data'], $request->data); $data = array( 'a' => array(1, 2), 'b' => array(1, 2) ); $request = $this->getMock('TestCakeRequest', array('_readInput')); $request->expects($this->at(0))->method('_readInput') ->will($this->returnValue('a[]=1&a[]=2&b[]=1&b[]=2')); $request->reConstruct(); $this->assertEquals($data, $request->data); } /** * Test parsing json PUT data into the object. * * @return void */ public function testPutParsingJSON() { $_SERVER['REQUEST_METHOD'] = 'PUT'; $_SERVER['CONTENT_TYPE'] = 'application/json'; $request = $this->getMock('TestCakeRequest', array('_readInput')); $request->expects($this->at(0))->method('_readInput') ->will($this->returnValue('{"Article":["title"]}')); $request->reConstruct(); $result = $request->input('json_decode', true); $this->assertEquals(array('title'), $result['Article']); } /** * Test parsing of FILES array * * @return void */ public function testFilesParsing() { $_FILES = array( 'data' => array( 'name' => array( 'File' => array( array('data' => 'cake_sqlserver_patch.patch'), array('data' => 'controller.diff'), array('data' => ''), array('data' => ''), ), 'Post' => array('attachment' => 'jquery-1.2.1.js'), ), 'type' => array( 'File' => array( array('data' => ''), array('data' => ''), array('data' => ''), array('data' => ''), ), 'Post' => array('attachment' => 'application/x-javascript'), ), 'tmp_name' => array( 'File' => array( array('data' => '/private/var/tmp/phpy05Ywj'), array('data' => '/private/var/tmp/php7MBztY'), array('data' => ''), array('data' => ''), ), 'Post' => array('attachment' => '/private/var/tmp/phpEwlrIo'), ), 'error' => array( 'File' => array( array('data' => 0), array('data' => 0), array('data' => 4), array('data' => 4) ), 'Post' => array('attachment' => 0) ), 'size' => array( 'File' => array( array('data' => 6271), array('data' => 350), array('data' => 0), array('data' => 0), ), 'Post' => array('attachment' => 80469) ), ) ); $request = new CakeRequest('some/path'); $expected = array( 'File' => array( array( 'data' => array( 'name' => 'cake_sqlserver_patch.patch', 'type' => '', 'tmp_name' => '/private/var/tmp/phpy05Ywj', 'error' => 0, 'size' => 6271, ) ), array( 'data' => array( 'name' => 'controller.diff', 'type' => '', 'tmp_name' => '/private/var/tmp/php7MBztY', 'error' => 0, 'size' => 350, ) ), array( 'data' => array( 'name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0, ) ), array( 'data' => array( 'name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0, ) ), ), 'Post' => array( 'attachment' => array( 'name' => 'jquery-1.2.1.js', 'type' => 'application/x-javascript', 'tmp_name' => '/private/var/tmp/phpEwlrIo', 'error' => 0, 'size' => 80469, ) ) ); $this->assertEquals($expected, $request->data); $_FILES = array( 'data' => array( 'name' => array( 'Document' => array( 1 => array( 'birth_cert' => 'born on.txt', 'passport' => 'passport.txt', 'drivers_license' => 'ugly pic.jpg' ), 2 => array( 'birth_cert' => 'aunt betty.txt', 'passport' => 'betty-passport.txt', 'drivers_license' => 'betty-photo.jpg' ), ), ), 'type' => array( 'Document' => array( 1 => array( 'birth_cert' => 'application/octet-stream', 'passport' => 'application/octet-stream', 'drivers_license' => 'application/octet-stream', ), 2 => array( 'birth_cert' => 'application/octet-stream', 'passport' => 'application/octet-stream', 'drivers_license' => 'application/octet-stream', ) ) ), 'tmp_name' => array( 'Document' => array( 1 => array( 'birth_cert' => '/private/var/tmp/phpbsUWfH', 'passport' => '/private/var/tmp/php7f5zLt', 'drivers_license' => '/private/var/tmp/phpMXpZgT', ), 2 => array( 'birth_cert' => '/private/var/tmp/php5kHZt0', 'passport' => '/private/var/tmp/phpnYkOuM', 'drivers_license' => '/private/var/tmp/php9Rq0P3', ) ) ), 'error' => array( 'Document' => array( 1 => array( 'birth_cert' => 0, 'passport' => 0, 'drivers_license' => 0, ), 2 => array( 'birth_cert' => 0, 'passport' => 0, 'drivers_license' => 0, ) ) ), 'size' => array( 'Document' => array( 1 => array( 'birth_cert' => 123, 'passport' => 458, 'drivers_license' => 875, ), 2 => array( 'birth_cert' => 876, 'passport' => 976, 'drivers_license' => 9783, ) ) ) ) ); $request = new CakeRequest('some/path'); $expected = array( 'Document' => array( 1 => array( 'birth_cert' => array( 'name' => 'born on.txt', 'tmp_name' => '/private/var/tmp/phpbsUWfH', 'error' => 0, 'size' => 123, 'type' => 'application/octet-stream', ), 'passport' => array( 'name' => 'passport.txt', 'tmp_name' => '/private/var/tmp/php7f5zLt', 'error' => 0, 'size' => 458, 'type' => 'application/octet-stream', ), 'drivers_license' => array( 'name' => 'ugly pic.jpg', 'tmp_name' => '/private/var/tmp/phpMXpZgT', 'error' => 0, 'size' => 875, 'type' => 'application/octet-stream', ), ), 2 => array( 'birth_cert' => array( 'name' => 'aunt betty.txt', 'tmp_name' => '/private/var/tmp/php5kHZt0', 'error' => 0, 'size' => 876, 'type' => 'application/octet-stream', ), 'passport' => array( 'name' => 'betty-passport.txt', 'tmp_name' => '/private/var/tmp/phpnYkOuM', 'error' => 0, 'size' => 976, 'type' => 'application/octet-stream', ), 'drivers_license' => array( 'name' => 'betty-photo.jpg', 'tmp_name' => '/private/var/tmp/php9Rq0P3', 'error' => 0, 'size' => 9783, 'type' => 'application/octet-stream', ), ), ) ); $this->assertEquals($expected, $request->data); $_FILES = array( 'data' => array( 'name' => array('birth_cert' => 'born on.txt'), 'type' => array('birth_cert' => 'application/octet-stream'), 'tmp_name' => array('birth_cert' => '/private/var/tmp/phpbsUWfH'), 'error' => array('birth_cert' => 0), 'size' => array('birth_cert' => 123) ) ); $request = new CakeRequest('some/path'); $expected = array( 'birth_cert' => array( 'name' => 'born on.txt', 'type' => 'application/octet-stream', 'tmp_name' => '/private/var/tmp/phpbsUWfH', 'error' => 0, 'size' => 123 ) ); $this->assertEquals($expected, $request->data); $_FILES = array( 'something' => array( 'name' => 'something.txt', 'type' => 'text/plain', 'tmp_name' => '/some/file', 'error' => 0, 'size' => 123 ) ); $request = new CakeRequest('some/path'); $this->assertEquals($request->params['form'], $_FILES); } /** * Test that files in the 0th index work. * * @return void */ public function testFilesZeroithIndex() { $_FILES = array( 0 => array( 'name' => 'cake_sqlserver_patch.patch', 'type' => 'text/plain', 'tmp_name' => '/private/var/tmp/phpy05Ywj', 'error' => 0, 'size' => 6271, ), ); $request = new CakeRequest('some/path'); $this->assertEquals($_FILES, $request->params['form']); } /** * Test method overrides coming in from POST data. * * @return void */ public function testMethodOverrides() { $_POST = array('_method' => 'POST'); $request = new CakeRequest('some/path'); $this->assertEquals(env('REQUEST_METHOD'), 'POST'); $_POST = array('_method' => 'DELETE'); $request = new CakeRequest('some/path'); $this->assertEquals(env('REQUEST_METHOD'), 'DELETE'); $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; $request = new CakeRequest('some/path'); $this->assertEquals(env('REQUEST_METHOD'), 'PUT'); } /** * Test the clientIp method. * * @return void */ public function testclientIp() { $_SERVER['HTTP_X_FORWARDED_FOR'] = '192.168.1.5, 10.0.1.1, proxy.com'; $_SERVER['HTTP_CLIENT_IP'] = '192.168.1.2'; $_SERVER['REMOTE_ADDR'] = '192.168.1.3'; $request = new CakeRequest('some/path'); $this->assertEquals('192.168.1.5', $request->clientIp(false)); $this->assertEquals('192.168.1.2', $request->clientIp()); unset($_SERVER['HTTP_X_FORWARDED_FOR']); $this->assertEquals('192.168.1.2', $request->clientIp()); unset($_SERVER['HTTP_CLIENT_IP']); $this->assertEquals('192.168.1.3', $request->clientIp()); $_SERVER['HTTP_CLIENTADDRESS'] = '10.0.1.2, 10.0.1.1'; $this->assertEquals('10.0.1.2', $request->clientIp()); } /** * Test the referrer function. * * @return void */ public function testReferer() { $request = new CakeRequest('some/path'); $request->webroot = '/'; $_SERVER['HTTP_REFERER'] = 'http://cakephp.org'; $result = $request->referer(); $this->assertSame($result, 'http://cakephp.org'); $_SERVER['HTTP_REFERER'] = ''; $result = $request->referer(); $this->assertSame($result, '/'); $_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseUrl') . '/some/path'; $result = $request->referer(true); $this->assertSame($result, '/some/path'); $_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseUrl') . '/some/path'; $result = $request->referer(false); $this->assertSame($result, Configure::read('App.fullBaseUrl') . '/some/path'); $_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseUrl') . '/recipes/add'; $result = $request->referer(true); $this->assertSame($result, '/recipes/add'); } /** * Test referer() with a base path that duplicates the * first segment. * * @return void */ public function testRefererBasePath() { $request = new CakeRequest('some/path'); $request->url = 'users/login'; $request->webroot = '/waves/'; $request->base = '/waves'; $request->here = '/waves/users/login'; $_SERVER['HTTP_REFERER'] = FULL_BASE_URL . '/waves/waves/add'; $result = $request->referer(true); $this->assertSame($result, '/waves/add'); } /** * test the simple uses of is() * * @return void */ public function testIsHttpMethods() { $request = new CakeRequest('some/path'); $this->assertFalse($request->is('undefined-behavior')); $_SERVER['REQUEST_METHOD'] = 'GET'; $this->assertTrue($request->is('get')); $_SERVER['REQUEST_METHOD'] = 'POST'; $this->assertTrue($request->is('POST')); $_SERVER['REQUEST_METHOD'] = 'PUT'; $this->assertTrue($request->is('put')); $this->assertFalse($request->is('get')); $_SERVER['REQUEST_METHOD'] = 'DELETE'; $this->assertTrue($request->is('delete')); $this->assertTrue($request->isDelete()); $_SERVER['REQUEST_METHOD'] = 'delete'; $this->assertFalse($request->is('delete')); } /** * Test is() with json and xml. * * @return void */ public function testIsJsonAndXml() { $request = new CakeRequest('some/path'); $_SERVER['HTTP_ACCEPT'] = 'application/json, text/plain, */*'; $this->assertTrue($request->is(array('json'))); $_SERVER['HTTP_ACCEPT'] = 'application/xml, text/plain, */*'; $this->assertTrue($request->is(array('xml'))); $_SERVER['HTTP_ACCEPT'] = 'text/xml, */*'; $this->assertTrue($request->is(array('xml'))); } /** * Test is() with multiple types. * * @return void */ public function testIsMultiple() { $request = new CakeRequest('some/path'); $_SERVER['REQUEST_METHOD'] = 'GET'; $this->assertTrue($request->is(array('get', 'post'))); $_SERVER['REQUEST_METHOD'] = 'POST'; $this->assertTrue($request->is(array('get', 'post'))); $_SERVER['REQUEST_METHOD'] = 'PUT'; $this->assertFalse($request->is(array('get', 'post'))); } /** * Test isAll() * * @return void */ public function testIsAll() { $request = new CakeRequest('some/path'); $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; $_SERVER['REQUEST_METHOD'] = 'GET'; $this->assertTrue($request->isAll(array('ajax', 'get'))); $this->assertFalse($request->isAll(array('post', 'get'))); $this->assertFalse($request->isAll(array('ajax', 'post'))); } /** * Test the method() method. * * @return void */ public function testMethod() { $_SERVER['REQUEST_METHOD'] = 'delete'; $request = new CakeRequest('some/path'); $this->assertEquals('delete', $request->method()); } /** * Test host retrieval. * * @return void */ public function testHost() { $_SERVER['HTTP_HOST'] = 'localhost'; $_SERVER['HTTP_X_FORWARDED_HOST'] = 'cakephp.org'; $request = new CakeRequest('some/path'); $this->assertEquals('localhost', $request->host()); $this->assertEquals('cakephp.org', $request->host(true)); } /** * Test domain retrieval. * * @return void */ public function testDomain() { $_SERVER['HTTP_HOST'] = 'something.example.com'; $request = new CakeRequest('some/path'); $this->assertEquals('example.com', $request->domain()); $_SERVER['HTTP_HOST'] = 'something.example.co.uk'; $this->assertEquals('example.co.uk', $request->domain(2)); } /** * Test getting subdomains for a host. * * @return void */ public function testSubdomain() { $_SERVER['HTTP_HOST'] = 'something.example.com'; $request = new CakeRequest('some/path'); $this->assertEquals(array('something'), $request->subdomains()); $_SERVER['HTTP_HOST'] = 'www.something.example.com'; $this->assertEquals(array('www', 'something'), $request->subdomains()); $_SERVER['HTTP_HOST'] = 'www.something.example.co.uk'; $this->assertEquals(array('www', 'something'), $request->subdomains(2)); $_SERVER['HTTP_HOST'] = 'example.co.uk'; $this->assertEquals(array(), $request->subdomains(2)); } /** * Test ajax, flash and friends * * @return void */ public function testisAjaxFlashAndFriends() { $request = new CakeRequest('some/path'); $_SERVER['HTTP_USER_AGENT'] = 'Shockwave Flash'; $this->assertTrue($request->is('flash')); $_SERVER['HTTP_USER_AGENT'] = 'Adobe Flash'; $this->assertTrue($request->is('flash')); $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'; $this->assertTrue($request->is('ajax')); $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHTTPREQUEST'; $this->assertFalse($request->is('ajax')); $this->assertFalse($request->isAjax()); $_SERVER['HTTP_USER_AGENT'] = 'Android 2.0'; $this->assertTrue($request->is('mobile')); $this->assertTrue($request->isMobile()); $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Windows NT 5.1; rv:2.0b6pre) Gecko/20100902 Firefox/4.0b6pre Fennec/2.0b1pre'; $this->assertTrue($request->is('mobile')); $this->assertTrue($request->isMobile()); $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; SAMSUNG; OMNIA7)'; $this->assertTrue($request->is('mobile')); $this->assertTrue($request->isMobile()); } /** * Test __call exceptions * * @expectedException CakeException * @return void */ public function testMagicCallExceptionOnUnknownMethod() { $request = new CakeRequest('some/path'); $request->IamABanana(); } /** * Test is(ssl) * * @return void */ public function testIsSsl() { $request = new CakeRequest('some/path'); $_SERVER['HTTPS'] = 1; $this->assertTrue($request->is('ssl')); $_SERVER['HTTPS'] = 'on'; $this->assertTrue($request->is('ssl')); $_SERVER['HTTPS'] = '1'; $this->assertTrue($request->is('ssl')); $_SERVER['HTTPS'] = 'I am not empty'; $this->assertTrue($request->is('ssl')); $_SERVER['HTTPS'] = 1; $this->assertTrue($request->is('ssl')); $_SERVER['HTTPS'] = 'off'; $this->assertFalse($request->is('ssl')); $_SERVER['HTTPS'] = false; $this->assertFalse($request->is('ssl')); $_SERVER['HTTPS'] = ''; $this->assertFalse($request->is('ssl')); } /** * Test getting request params with object properties. * * @return void */ public function testMagicget() { $request = new CakeRequest('some/path'); $request->params = array('controller' => 'posts', 'action' => 'view', 'plugin' => 'blogs'); $this->assertEquals('posts', $request->controller); $this->assertEquals('view', $request->action); $this->assertEquals('blogs', $request->plugin); $this->assertNull($request->banana); } /** * Test isset()/empty() with overloaded properties. * * @return void */ public function testMagicisset() { $request = new CakeRequest('some/path'); $request->params = array( 'controller' => 'posts', 'action' => 'view', 'plugin' => 'blogs', 'named' => array() ); $this->assertTrue(isset($request->controller)); $this->assertFalse(isset($request->notthere)); $this->assertFalse(empty($request->controller)); $this->assertTrue(empty($request->named)); } /** * Test the array access implementation * * @return void */ public function testArrayAccess() { $request = new CakeRequest('some/path'); $request->params = array('controller' => 'posts', 'action' => 'view', 'plugin' => 'blogs'); $this->assertEquals('posts', $request['controller']); $request['slug'] = 'speedy-slug'; $this->assertEquals('speedy-slug', $request->slug); $this->assertEquals('speedy-slug', $request['slug']); $this->assertTrue(isset($request['action'])); $this->assertFalse(isset($request['wrong-param'])); $this->assertTrue(isset($request['plugin'])); unset($request['plugin']); $this->assertFalse(isset($request['plugin'])); $this->assertNull($request['plugin']); $this->assertNull($request->plugin); $request = new CakeRequest('some/path?one=something&two=else'); $this->assertTrue(isset($request['url']['one'])); $request->data = array('Post' => array('title' => 'something')); $this->assertEquals('something', $request['data']['Post']['title']); } /** * Test adding detectors and having them work. * * @return void */ public function testAddDetector() { $request = new CakeRequest('some/path'); $request->addDetector('compare', array('env' => 'TEST_VAR', 'value' => 'something')); $_SERVER['TEST_VAR'] = 'something'; $this->assertTrue($request->is('compare'), 'Value match failed.'); $_SERVER['TEST_VAR'] = 'wrong'; $this->assertFalse($request->is('compare'), 'Value mis-match failed.'); $request->addDetector('compareCamelCase', array('env' => 'TEST_VAR', 'value' => 'foo')); $_SERVER['TEST_VAR'] = 'foo'; $this->assertTrue($request->is('compareCamelCase'), 'Value match failed.'); $this->assertTrue($request->is('comparecamelcase'), 'detectors should be case insensitive'); $this->assertTrue($request->is('COMPARECAMELCASE'), 'detectors should be case insensitive'); $_SERVER['TEST_VAR'] = 'not foo'; $this->assertFalse($request->is('compareCamelCase'), 'Value match failed.'); $this->assertFalse($request->is('comparecamelcase'), 'detectors should be case insensitive'); $this->assertFalse($request->is('COMPARECAMELCASE'), 'detectors should be case insensitive'); $request->addDetector('banana', array('env' => 'TEST_VAR', 'pattern' => '/^ban.*$/')); $_SERVER['TEST_VAR'] = 'banana'; $this->assertTrue($request->isBanana()); $_SERVER['TEST_VAR'] = 'wrong value'; $this->assertFalse($request->isBanana()); $request->addDetector('mobile', array('options' => array('Imagination'))); $_SERVER['HTTP_USER_AGENT'] = 'Imagination land'; $this->assertTrue($request->isMobile()); $_SERVER['HTTP_USER_AGENT'] = 'iPhone 3.0'; $this->assertTrue($request->isMobile()); $request->addDetector('callme', array('env' => 'TEST_VAR', 'callback' => array($this, 'detectCallback'))); $request->addDetector('index', array('param' => 'action', 'value' => 'index')); $request->params['action'] = 'index'; $this->assertTrue($request->isIndex()); $request->params['action'] = 'add'; $this->assertFalse($request->isIndex()); $request->return = true; $this->assertTrue($request->isCallMe()); $request->return = false; $this->assertFalse($request->isCallMe()); $request->addDetector('extension', array('param' => 'ext', 'options' => array('pdf', 'png', 'txt'))); $request->params['ext'] = 'pdf'; $this->assertTrue($request->is('extension')); $request->params['ext'] = 'exe'; $this->assertFalse($request->isExtension()); } /** * Helper function for testing callbacks. * * @param $request * @return bool */ public function detectCallback($request) { return (bool)$request->return; } /** * Test getting headers * * @return void */ public function testHeader() { $_SERVER['HTTP_X_THING'] = ''; $_SERVER['HTTP_HOST'] = 'localhost'; $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-ca) AppleWebKit/534.8+ (KHTML, like Gecko) Version/5.0 Safari/533.16'; $request = new CakeRequest('/', false); $this->assertEquals($_SERVER['HTTP_HOST'], $request->header('host')); $this->assertEquals($_SERVER['HTTP_USER_AGENT'], $request->header('User-Agent')); $this->assertSame('', $request->header('X-thing')); } /** * Test accepts() with and without parameters * * @return void */ public function testAccepts() { $_SERVER['HTTP_ACCEPT'] = 'text/xml,application/xml;q=0.9,application/xhtml+xml,text/html,text/plain,image/png'; $request = new CakeRequest('/', false); $result = $request->accepts(); $expected = array( 'text/xml', 'application/xhtml+xml', 'text/html', 'text/plain', 'image/png', 'application/xml' ); $this->assertEquals($expected, $result, 'Content types differ.'); $result = $request->accepts('text/html'); $this->assertTrue($result); $result = $request->accepts('image/gif'); $this->assertFalse($result); } /** * Test that accept header types are trimmed for comparisons. * * @return void */ public function testAcceptWithWhitespace() { $_SERVER['HTTP_ACCEPT'] = 'text/xml , text/html , text/plain,image/png'; $request = new CakeRequest('/', false); $result = $request->accepts(); $expected = array( 'text/xml', 'text/html', 'text/plain', 'image/png' ); $this->assertEquals($expected, $result, 'Content types differ.'); $this->assertTrue($request->accepts('text/html')); } /** * Content types from accepts() should respect the client's q preference values. * * @return void */ public function testAcceptWithQvalueSorting() { $_SERVER['HTTP_ACCEPT'] = 'text/html;q=0.8,application/json;q=0.7,application/xml;q=1.0'; $request = new CakeRequest('/', false); $result = $request->accepts(); $expected = array('application/xml', 'text/html', 'application/json'); $this->assertEquals($expected, $result); } /** * Test the raw parsing of accept headers into the q value formatting. * * @return void */ public function testParseAcceptWithQValue() { $_SERVER['HTTP_ACCEPT'] = 'text/html;q=0.8,application/json;q=0.7,application/xml;q=1.0,image/png'; $request = new CakeRequest('/', false); $result = $request->parseAccept(); $expected = array( '1.0' => array('application/xml', 'image/png'), '0.8' => array('text/html'), '0.7' => array('application/json'), ); $this->assertEquals($expected, $result); } /** * Test parsing accept with a confusing accept value. * * @return void */ public function testParseAcceptNoQValues() { $_SERVER['HTTP_ACCEPT'] = 'application/json, text/plain, */*'; $request = new CakeRequest('/', false); $result = $request->parseAccept(); $expected = array( '1.0' => array('application/json', 'text/plain', '*/*'), ); $this->assertEquals($expected, $result); } /** * Test parsing accept ignores index param * * @return void */ public function testParseAcceptIgnoreAcceptExtensions() { $_SERVER['HTTP_ACCEPT'] = 'application/json;level=1, text/plain, */*'; $request = new CakeRequest('/', false); $result = $request->parseAccept(); $expected = array( '1.0' => array('application/json', 'text/plain', '*/*'), ); $this->assertEquals($expected, $result); } /** * Test that parsing accept headers with invalid syntax works. * * The header used is missing a q value for application/xml. * * @return void */ public function testParseAcceptInvalidSyntax() { $_SERVER['HTTP_ACCEPT'] = 'text/html,application/xhtml+xml,application/xml;image/png,image/jpeg,image/*;q=0.9,*/*;q=0.8'; $request = new CakeRequest('/', false); $result = $request->parseAccept(); $expected = array( '1.0' => array('text/html', 'application/xhtml+xml', 'application/xml', 'image/jpeg'), '0.9' => array('image/*'), '0.8' => array('*/*'), ); $this->assertEquals($expected, $result); } /** * Test baseUrl and webroot with ModRewrite * * @return void */ public function testBaseUrlAndWebrootWithModRewrite() { Configure::write('App.baseUrl', false); $_SERVER['DOCUMENT_ROOT'] = '/cake/repo/branches'; $_SERVER['PHP_SELF'] = '/urlencode me/app/webroot/index.php'; $_SERVER['PATH_INFO'] = '/posts/view/1'; $request = new CakeRequest(); $this->assertEquals('/urlencode%20me', $request->base); $this->assertEquals('/urlencode%20me/', $request->webroot); $this->assertEquals('posts/view/1', $request->url); $_SERVER['DOCUMENT_ROOT'] = '/cake/repo/branches'; $_SERVER['PHP_SELF'] = '/1.2.x.x/app/webroot/index.php'; $_SERVER['PATH_INFO'] = '/posts/view/1'; $request = new CakeRequest(); $this->assertEquals('/1.2.x.x', $request->base); $this->assertEquals('/1.2.x.x/', $request->webroot); $this->assertEquals('posts/view/1', $request->url); $_SERVER['DOCUMENT_ROOT'] = '/cake/repo/branches/1.2.x.x/app/webroot'; $_SERVER['PHP_SELF'] = '/index.php'; $_SERVER['PATH_INFO'] = '/posts/add'; $request = new CakeRequest(); $this->assertEquals('', $request->base); $this->assertEquals('/', $request->webroot); $this->assertEquals('posts/add', $request->url); $_SERVER['DOCUMENT_ROOT'] = '/cake/repo/branches/1.2.x.x/test/'; $_SERVER['PHP_SELF'] = '/webroot/index.php'; $request = new CakeRequest(); $this->assertEquals('', $request->base); $this->assertEquals('/', $request->webroot); $_SERVER['DOCUMENT_ROOT'] = '/some/apps/where'; $_SERVER['PHP_SELF'] = '/app/webroot/index.php'; $request = new CakeRequest(); $this->assertEquals('', $request->base); $this->assertEquals('/', $request->webroot); Configure::write('App.dir', 'auth'); $_SERVER['DOCUMENT_ROOT'] = '/cake/repo/branches'; $_SERVER['PHP_SELF'] = '/demos/auth/webroot/index.php'; $request = new CakeRequest(); $this->assertEquals('/demos/auth', $request->base); $this->assertEquals('/demos/auth/', $request->webroot); Configure::write('App.dir', 'code'); $_SERVER['DOCUMENT_ROOT'] = '/Library/WebServer/Documents'; $_SERVER['PHP_SELF'] = '/clients/PewterReport/code/webroot/index.php'; $request = new CakeRequest(); $this->assertEquals('/clients/PewterReport/code', $request->base); $this->assertEquals('/clients/PewterReport/code/', $request->webroot); } /** * Test baseUrl with ModRewrite alias * * @return void */ public function testBaseUrlwithModRewriteAlias() { $_SERVER['DOCUMENT_ROOT'] = '/home/aplusnur/public_html'; $_SERVER['PHP_SELF'] = '/control/index.php'; Configure::write('App.base', '/control'); $request = new CakeRequest(); $this->assertEquals('/control', $request->base); $this->assertEquals('/control/', $request->webroot); Configure::write('App.base', false); Configure::write('App.dir', 'affiliate'); Configure::write('App.webroot', 'newaffiliate'); $_SERVER['DOCUMENT_ROOT'] = '/var/www/abtravaff/html'; $_SERVER['PHP_SELF'] = '/newaffiliate/index.php'; $request = new CakeRequest(); $this->assertEquals('/newaffiliate', $request->base); $this->assertEquals('/newaffiliate/', $request->webroot); } /** * Test base, webroot, URL and here parsing when there is URL rewriting but * CakePHP gets called with index.php in URL nonetheless. * * Tests uri with * - index.php/ * - index.php/ * - index.php/apples/ * - index.php/bananas/eat/tasty_banana * * @link https://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/3318 * @return void */ public function testBaseUrlWithModRewriteAndIndexPhp() { $_SERVER['REQUEST_URI'] = '/cakephp/app/webroot/index.php'; $_SERVER['PHP_SELF'] = '/cakephp/app/webroot/index.php'; unset($_SERVER['PATH_INFO']); $request = new CakeRequest(); $this->assertEquals('/cakephp', $request->base); $this->assertEquals('/cakephp/', $request->webroot); $this->assertEquals('', $request->url); $this->assertEquals('/cakephp/', $request->here); $_SERVER['REQUEST_URI'] = '/cakephp/app/webroot/index.php/'; $_SERVER['PHP_SELF'] = '/cakephp/app/webroot/index.php/'; $_SERVER['PATH_INFO'] = '/'; $request = new CakeRequest(); $this->assertEquals('/cakephp', $request->base); $this->assertEquals('/cakephp/', $request->webroot); $this->assertEquals('', $request->url); $this->assertEquals('/cakephp/', $request->here); $_SERVER['REQUEST_URI'] = '/cakephp/app/webroot/index.php/apples'; $_SERVER['PHP_SELF'] = '/cakephp/app/webroot/index.php/apples'; $_SERVER['PATH_INFO'] = '/apples'; $request = new CakeRequest(); $this->assertEquals('/cakephp', $request->base); $this->assertEquals('/cakephp/', $request->webroot); $this->assertEquals('apples', $request->url); $this->assertEquals('/cakephp/apples', $request->here); $_SERVER['REQUEST_URI'] = '/cakephp/app/webroot/index.php/melons/share/'; $_SERVER['PHP_SELF'] = '/cakephp/app/webroot/index.php/melons/share/'; $_SERVER['PATH_INFO'] = '/melons/share/'; $request = new CakeRequest(); $this->assertEquals('/cakephp', $request->base); $this->assertEquals('/cakephp/', $request->webroot); $this->assertEquals('melons/share/', $request->url); $this->assertEquals('/cakephp/melons/share/', $request->here); $_SERVER['REQUEST_URI'] = '/cakephp/app/webroot/index.php/bananas/eat/tasty_banana'; $_SERVER['PHP_SELF'] = '/cakephp/app/webroot/index.php/bananas/eat/tasty_banana'; $_SERVER['PATH_INFO'] = '/bananas/eat/tasty_banana'; $request = new CakeRequest(); $this->assertEquals('/cakephp', $request->base); $this->assertEquals('/cakephp/', $request->webroot); $this->assertEquals('bananas/eat/tasty_banana', $request->url); $this->assertEquals('/cakephp/bananas/eat/tasty_banana', $request->here); } /** * Test that even if mod_rewrite is on, and the url contains index.php * and there are numerous //s that the base/webroot is calculated correctly. * * @return void */ public function testBaseUrlWithModRewriteAndExtraSlashes() { $_SERVER['REQUEST_URI'] = '/cakephp/webroot///index.php/bananas/eat'; $_SERVER['PHP_SELF'] = '/cakephp/webroot///index.php/bananas/eat'; $_SERVER['PATH_INFO'] = '/bananas/eat'; $request = new CakeRequest(); $this->assertEquals('/cakephp', $request->base); $this->assertEquals('/cakephp/', $request->webroot); $this->assertEquals('bananas/eat', $request->url); $this->assertEquals('/cakephp/bananas/eat', $request->here); } /** * Test base, webroot, and URL parsing when there is no URL rewriting * * @return void */ public function testBaseUrlWithNoModRewrite() { $_SERVER['DOCUMENT_ROOT'] = '/Users/markstory/Sites'; $_SERVER['SCRIPT_FILENAME'] = '/Users/markstory/Sites/cake/index.php'; $_SERVER['PHP_SELF'] = '/cake/index.php/posts/index'; $_SERVER['REQUEST_URI'] = '/cake/index.php/posts/index'; Configure::write('App', array( 'dir' => APP_DIR, 'webroot' => WEBROOT_DIR, 'base' => false, 'baseUrl' => '/cake/index.php' )); $request = new CakeRequest(); $this->assertEquals('/cake/index.php', $request->base); $this->assertEquals('/cake/app/webroot/', $request->webroot); $this->assertEquals('posts/index', $request->url); } /** * Test baseUrl and webroot with baseUrl * * @return void */ public function testBaseUrlAndWebrootWithBaseUrl() { Configure::write('App.dir', 'app'); Configure::write('App.baseUrl', '/app/webroot/index.php'); $request = new CakeRequest(); $this->assertEquals('/app/webroot/index.php', $request->base); $this->assertEquals('/app/webroot/', $request->webroot); Configure::write('App.baseUrl', '/app/webroot/test.php'); $request = new CakeRequest(); $this->assertEquals('/app/webroot/test.php', $request->base); $this->assertEquals('/app/webroot/', $request->webroot); Configure::write('App.baseUrl', '/app/index.php'); $request = new CakeRequest(); $this->assertEquals('/app/index.php', $request->base); $this->assertEquals('/app/webroot/', $request->webroot); Configure::write('App.baseUrl', '/CakeBB/app/webroot/index.php'); $request = new CakeRequest(); $this->assertEquals('/CakeBB/app/webroot/index.php', $request->base); $this->assertEquals('/CakeBB/app/webroot/', $request->webroot); Configure::write('App.baseUrl', '/CakeBB/app/index.php'); $request = new CakeRequest(); $this->assertEquals('/CakeBB/app/index.php', $request->base); $this->assertEquals('/CakeBB/app/webroot/', $request->webroot); Configure::write('App.baseUrl', '/CakeBB/index.php'); $request = new CakeRequest(); $this->assertEquals('/CakeBB/index.php', $request->base); $this->assertEquals('/CakeBB/app/webroot/', $request->webroot); Configure::write('App.baseUrl', '/dbhauser/index.php'); $_SERVER['DOCUMENT_ROOT'] = '/kunden/homepages/4/d181710652/htdocs/joomla'; $_SERVER['SCRIPT_FILENAME'] = '/kunden/homepages/4/d181710652/htdocs/joomla/dbhauser/index.php'; $request = new CakeRequest(); $this->assertEquals('/dbhauser/index.php', $request->base); $this->assertEquals('/dbhauser/app/webroot/', $request->webroot); } /** * Test baseUrl with no rewrite and using the top level index.php. * * @return void */ public function testBaseUrlNoRewriteTopLevelIndex() { Configure::write('App.baseUrl', '/index.php'); $_SERVER['DOCUMENT_ROOT'] = '/Users/markstory/Sites/cake_dev'; $_SERVER['SCRIPT_FILENAME'] = '/Users/markstory/Sites/cake_dev/index.php'; $request = new CakeRequest(); $this->assertEquals('/index.php', $request->base); $this->assertEquals('/app/webroot/', $request->webroot); } /** * Check that a sub-directory containing app|webroot doesn't get mishandled when re-writing is off. * * @return void */ public function testBaseUrlWithAppAndWebrootInDirname() { Configure::write('App.baseUrl', '/approval/index.php'); $_SERVER['DOCUMENT_ROOT'] = '/Users/markstory/Sites/'; $_SERVER['SCRIPT_FILENAME'] = '/Users/markstory/Sites/approval/index.php'; $request = new CakeRequest(); $this->assertEquals('/approval/index.php', $request->base); $this->assertEquals('/approval/app/webroot/', $request->webroot); Configure::write('App.baseUrl', '/webrootable/index.php'); $_SERVER['DOCUMENT_ROOT'] = '/Users/markstory/Sites/'; $_SERVER['SCRIPT_FILENAME'] = '/Users/markstory/Sites/webrootable/index.php'; $request = new CakeRequest(); $this->assertEquals('/webrootable/index.php', $request->base); $this->assertEquals('/webrootable/app/webroot/', $request->webroot); } /** * Test baseUrl with no rewrite, and using the app/webroot/index.php file as is normal with virtual hosts. * * @return void */ public function testBaseUrlNoRewriteWebrootIndex() { Configure::write('App.baseUrl', '/index.php'); $_SERVER['DOCUMENT_ROOT'] = '/Users/markstory/Sites/cake_dev/app/webroot'; $_SERVER['SCRIPT_FILENAME'] = '/Users/markstory/Sites/cake_dev/app/webroot/index.php'; $request = new CakeRequest(); $this->assertEquals('/index.php', $request->base); $this->assertEquals('/', $request->webroot); } /** * Test that a request with a . in the main GET parameter is filtered out. * PHP changes GET parameter keys containing dots to _. * * @return void */ public function testGetParamsWithDot() { $_GET = array(); $_GET['/posts/index/add_add'] = ''; $_SERVER['PHP_SELF'] = '/app/webroot/index.php'; $_SERVER['REQUEST_URI'] = '/posts/index/add.add'; $request = new CakeRequest(); $this->assertEquals('', $request->base); $this->assertEquals(array(), $request->query); $_GET = array(); $_GET['/cake_dev/posts/index/add_add'] = ''; $_SERVER['PHP_SELF'] = '/cake_dev/app/webroot/index.php'; $_SERVER['REQUEST_URI'] = '/cake_dev/posts/index/add.add'; $request = new CakeRequest(); $this->assertEquals('/cake_dev', $request->base); $this->assertEquals(array(), $request->query); } /** * Test that a request with urlencoded bits in the main GET parameter are filtered out. * * @return void */ public function testGetParamWithUrlencodedElement() { $_GET = array(); $_GET['/posts/add/โˆ‚โˆ‚'] = ''; $_SERVER['PHP_SELF'] = '/app/webroot/index.php'; $_SERVER['REQUEST_URI'] = '/posts/add/%E2%88%82%E2%88%82'; $request = new CakeRequest(); $this->assertEquals('', $request->base); $this->assertEquals(array(), $request->query); $_GET = array(); $_GET['/cake_dev/posts/add/โˆ‚โˆ‚'] = ''; $_SERVER['PHP_SELF'] = '/cake_dev/app/webroot/index.php'; $_SERVER['REQUEST_URI'] = '/cake_dev/posts/add/%E2%88%82%E2%88%82'; $request = new CakeRequest(); $this->assertEquals('/cake_dev', $request->base); $this->assertEquals(array(), $request->query); } /** * Generator for environment configurations * * @return array Environment array */ public static function environmentGenerator() { return array( array( 'IIS - No rewrite base path', array( 'App' => array( 'base' => false, 'baseUrl' => '/index.php', 'dir' => 'app', 'webroot' => 'webroot' ), 'SERVER' => array( 'SCRIPT_NAME' => '/index.php', 'PATH_TRANSLATED' => 'C:\\Inetpub\\wwwroot', 'QUERY_STRING' => '', 'REQUEST_URI' => '/index.php', 'URL' => '/index.php', 'SCRIPT_FILENAME' => 'C:\\Inetpub\\wwwroot\\index.php', 'ORIG_PATH_INFO' => '/index.php', 'PATH_INFO' => '', 'ORIG_PATH_TRANSLATED' => 'C:\\Inetpub\\wwwroot\\index.php', 'DOCUMENT_ROOT' => 'C:\\Inetpub\\wwwroot', 'PHP_SELF' => '/index.php', ), ), array( 'base' => '/index.php', 'webroot' => '/app/webroot/', 'url' => '' ), ), array( 'IIS - No rewrite with path, no PHP_SELF', array( 'App' => array( 'base' => false, 'baseUrl' => '/index.php?', 'dir' => 'app', 'webroot' => 'webroot' ), 'SERVER' => array( 'QUERY_STRING' => '/posts/add', 'REQUEST_URI' => '/index.php?/posts/add', 'PHP_SELF' => '', 'URL' => '/index.php?/posts/add', 'DOCUMENT_ROOT' => 'C:\\Inetpub\\wwwroot', 'argv' => array('/posts/add'), 'argc' => 1 ), ), array( 'url' => 'posts/add', 'base' => '/index.php?', 'webroot' => '/app/webroot/' ) ), array( 'IIS - No rewrite sub dir 2', array( 'App' => array( 'base' => false, 'baseUrl' => '/site/index.php', 'dir' => 'app', 'webroot' => 'webroot', ), 'SERVER' => array( 'SCRIPT_NAME' => '/site/index.php', 'PATH_TRANSLATED' => 'C:\\Inetpub\\wwwroot', 'QUERY_STRING' => '', 'REQUEST_URI' => '/site/index.php', 'URL' => '/site/index.php', 'SCRIPT_FILENAME' => 'C:\\Inetpub\\wwwroot\\site\\index.php', 'DOCUMENT_ROOT' => 'C:\\Inetpub\\wwwroot', 'PHP_SELF' => '/site/index.php', 'argv' => array(), 'argc' => 0 ), ), array( 'url' => '', 'base' => '/site/index.php', 'webroot' => '/site/app/webroot/' ), ), array( 'IIS - No rewrite sub dir 2 with path', array( 'App' => array( 'base' => false, 'baseUrl' => '/site/index.php', 'dir' => 'app', 'webroot' => 'webroot' ), 'GET' => array('/posts/add' => ''), 'SERVER' => array( 'SCRIPT_NAME' => '/site/index.php', 'PATH_TRANSLATED' => 'C:\\Inetpub\\wwwroot', 'QUERY_STRING' => '/posts/add', 'REQUEST_URI' => '/site/index.php/posts/add', 'URL' => '/site/index.php/posts/add', 'ORIG_PATH_TRANSLATED' => 'C:\\Inetpub\\wwwroot\\site\\index.php', 'DOCUMENT_ROOT' => 'C:\\Inetpub\\wwwroot', 'PHP_SELF' => '/site/index.php/posts/add', 'argv' => array('/posts/add'), 'argc' => 1 ), ), array( 'url' => 'posts/add', 'base' => '/site/index.php', 'webroot' => '/site/app/webroot/' ) ), array( 'Apache - No rewrite, document root set to webroot, requesting path', array( 'App' => array( 'base' => false, 'baseUrl' => '/index.php', 'dir' => 'app', 'webroot' => 'webroot' ), 'SERVER' => array( 'DOCUMENT_ROOT' => '/Library/WebServer/Documents/site/app/webroot', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/app/webroot/index.php', 'QUERY_STRING' => '', 'REQUEST_URI' => '/index.php/posts/index', 'SCRIPT_NAME' => '/index.php', 'PATH_INFO' => '/posts/index', 'PHP_SELF' => '/index.php/posts/index', ), ), array( 'url' => 'posts/index', 'base' => '/index.php', 'webroot' => '/' ), ), array( 'Apache - No rewrite, document root set to webroot, requesting root', array( 'App' => array( 'base' => false, 'baseUrl' => '/index.php', 'dir' => 'app', 'webroot' => 'webroot' ), 'SERVER' => array( 'DOCUMENT_ROOT' => '/Library/WebServer/Documents/site/app/webroot', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/app/webroot/index.php', 'QUERY_STRING' => '', 'REQUEST_URI' => '/index.php', 'SCRIPT_NAME' => '/index.php', 'PATH_INFO' => '', 'PHP_SELF' => '/index.php', ), ), array( 'url' => '', 'base' => '/index.php', 'webroot' => '/' ), ), array( 'Apache - No rewrite, document root set above top level cake dir, requesting path', array( 'App' => array( 'base' => false, 'baseUrl' => '/site/index.php', 'dir' => 'app', 'webroot' => 'webroot' ), 'SERVER' => array( 'SERVER_NAME' => 'localhost', 'DOCUMENT_ROOT' => '/Library/WebServer/Documents', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/index.php', 'REQUEST_URI' => '/site/index.php/posts/index', 'SCRIPT_NAME' => '/site/index.php', 'PATH_INFO' => '/posts/index', 'PHP_SELF' => '/site/index.php/posts/index', ), ), array( 'url' => 'posts/index', 'base' => '/site/index.php', 'webroot' => '/site/app/webroot/', ), ), array( 'Apache - No rewrite, document root set above top level cake dir, request root, no PATH_INFO', array( 'App' => array( 'base' => false, 'baseUrl' => '/site/index.php', 'dir' => 'app', 'webroot' => 'webroot' ), 'SERVER' => array( 'SERVER_NAME' => 'localhost', 'DOCUMENT_ROOT' => '/Library/WebServer/Documents', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/index.php', 'REQUEST_URI' => '/site/index.php/', 'SCRIPT_NAME' => '/site/index.php', 'PHP_SELF' => '/site/index.php/', ), ), array( 'url' => '', 'base' => '/site/index.php', 'webroot' => '/site/app/webroot/', ), ), array( 'Apache - No rewrite, document root set above top level cake dir, request path, with GET', array( 'App' => array( 'base' => false, 'baseUrl' => '/site/index.php', 'dir' => 'app', 'webroot' => 'webroot' ), 'GET' => array('a' => 'b', 'c' => 'd'), 'SERVER' => array( 'SERVER_NAME' => 'localhost', 'DOCUMENT_ROOT' => '/Library/WebServer/Documents', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/index.php', 'REQUEST_URI' => '/site/index.php/posts/index?a=b&c=d', 'SCRIPT_NAME' => '/site/index.php', 'PATH_INFO' => '/posts/index', 'PHP_SELF' => '/site/index.php/posts/index', 'QUERY_STRING' => 'a=b&c=d' ), ), array( 'urlParams' => array('a' => 'b', 'c' => 'd'), 'url' => 'posts/index', 'base' => '/site/index.php', 'webroot' => '/site/app/webroot/', ), ), array( 'Apache - w/rewrite, document root set above top level cake dir, request root, no PATH_INFO', array( 'App' => array( 'base' => false, 'baseUrl' => false, 'dir' => 'app', 'webroot' => 'webroot' ), 'SERVER' => array( 'SERVER_NAME' => 'localhost', 'DOCUMENT_ROOT' => '/Library/WebServer/Documents', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/index.php', 'REQUEST_URI' => '/site/', 'SCRIPT_NAME' => '/site/app/webroot/index.php', 'PHP_SELF' => '/site/app/webroot/index.php', ), ), array( 'url' => '', 'base' => '/site', 'webroot' => '/site/', ), ), array( 'Apache - w/rewrite, document root above top level cake dir, request root, no PATH_INFO/REQUEST_URI', array( 'App' => array( 'base' => false, 'baseUrl' => false, 'dir' => 'app', 'webroot' => 'webroot' ), 'SERVER' => array( 'SERVER_NAME' => 'localhost', 'DOCUMENT_ROOT' => '/Library/WebServer/Documents', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/index.php', 'SCRIPT_NAME' => '/site/app/webroot/index.php', 'PHP_SELF' => '/site/app/webroot/index.php', 'PATH_INFO' => null, 'REQUEST_URI' => null, ), ), array( 'url' => '', 'base' => '/site', 'webroot' => '/site/', ), ), array( 'Apache - w/rewrite, document root set to webroot, request root, no PATH_INFO/REQUEST_URI', array( 'App' => array( 'base' => false, 'baseUrl' => false, 'dir' => 'app', 'webroot' => 'webroot' ), 'SERVER' => array( 'SERVER_NAME' => 'localhost', 'DOCUMENT_ROOT' => '/Library/WebServer/Documents/site/app/webroot', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/app/webroot/index.php', 'SCRIPT_NAME' => '/index.php', 'PHP_SELF' => '/index.php', 'PATH_INFO' => null, 'REQUEST_URI' => null, ), ), array( 'url' => '', 'base' => '', 'webroot' => '/', ), ), array( 'Apache - w/rewrite, document root set above top level cake dir, request root, absolute REQUEST_URI', array( 'App' => array( 'base' => false, 'baseUrl' => false, 'dir' => 'app', 'webroot' => 'webroot' ), 'SERVER' => array( 'SERVER_NAME' => 'localhost', 'DOCUMENT_ROOT' => '/Library/WebServer/Documents', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/index.php', 'REQUEST_URI' => '/site/posts/index', 'SCRIPT_NAME' => '/site/app/webroot/index.php', 'PHP_SELF' => '/site/app/webroot/index.php', ), ), array( 'url' => 'posts/index', 'base' => '/site', 'webroot' => '/site/', ), ), array( 'Nginx - w/rewrite, document root set to webroot, request root, no PATH_INFO', array( 'App' => array( 'base' => false, 'baseUrl' => false, 'dir' => 'app', 'webroot' => 'webroot' ), 'GET' => array('/posts/add' => ''), 'SERVER' => array( 'SERVER_NAME' => 'localhost', 'DOCUMENT_ROOT' => '/Library/WebServer/Documents/site/app/webroot', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/app/webroot/index.php', 'SCRIPT_NAME' => '/index.php', 'QUERY_STRING' => '/posts/add&', 'PHP_SELF' => '/index.php', 'PATH_INFO' => null, 'REQUEST_URI' => '/posts/add', ), ), array( 'url' => 'posts/add', 'base' => '', 'webroot' => '/', 'urlParams' => array() ), ), array( 'Nginx - w/rewrite, document root set above top level cake dir, request root, no PATH_INFO, base parameter set', array( 'App' => array( 'base' => false, 'baseUrl' => false, 'dir' => 'app', 'webroot' => 'webroot' ), 'GET' => array('/site/posts/add' => ''), 'SERVER' => array( 'SERVER_NAME' => 'localhost', 'DOCUMENT_ROOT' => '/Library/WebServer/Documents', 'SCRIPT_FILENAME' => '/Library/WebServer/Documents/site/app/webroot/index.php', 'SCRIPT_NAME' => '/site/app/webroot/index.php', 'QUERY_STRING' => '/site/posts/add&', 'PHP_SELF' => '/site/app/webroot/index.php', 'PATH_INFO' => null, 'REQUEST_URI' => '/site/posts/add', ), ), array( 'url' => 'posts/add', 'base' => '/site', 'webroot' => '/site/', 'urlParams' => array() ), ), ); } /** * Test environment detection * * @dataProvider environmentGenerator * @param $name * @param $env * @param $expected * @return void */ public function testEnvironmentDetection($name, $env, $expected) { $_GET = array(); $this->_loadEnvironment($env); $request = new CakeRequest(); $this->assertEquals($expected['url'], $request->url, "url error"); $this->assertEquals($expected['base'], $request->base, "base error"); $this->assertEquals($expected['webroot'], $request->webroot, "webroot error"); if (isset($expected['urlParams'])) { $this->assertEquals($expected['urlParams'], $request->query, "GET param mismatch"); } } /** * Test the query() method * * @return void */ public function testQuery() { $_GET = array(); $_GET['foo'] = 'bar'; $request = new CakeRequest(); $result = $request->query('foo'); $this->assertEquals('bar', $result); $result = $request->query('imaginary'); $this->assertNull($result); } /** * Test the query() method with arrays passed via $_GET * * @return void */ public function testQueryWithArray() { $_GET = array(); $_GET['test'] = array('foo', 'bar'); $request = new CakeRequest(); $result = $request->query('test'); $this->assertEquals(array('foo', 'bar'), $result); $result = $request->query('test.1'); $this->assertEquals('bar', $result); $result = $request->query('test.2'); $this->assertNull($result); } /** * Test the data() method reading * * @return void */ public function testDataReading() { $_POST['data'] = array( 'Model' => array( 'field' => 'value' ) ); $request = new CakeRequest('posts/index'); $result = $request->data('Model'); $this->assertEquals($_POST['data']['Model'], $result); $result = $request->data('Model.imaginary'); $this->assertNull($result); } /** * Test writing with data() * * @return void */ public function testDataWriting() { $_POST['data'] = array( 'Model' => array( 'field' => 'value' ) ); $request = new CakeRequest('posts/index'); $result = $request->data('Model.new_value', 'new value'); $this->assertSame($result, $request, 'Return was not $this'); $this->assertEquals('new value', $request->data['Model']['new_value']); $request->data('Post.title', 'New post')->data('Comment.1.author', 'Mark'); $this->assertEquals('New post', $request->data['Post']['title']); $this->assertEquals('Mark', $request->data['Comment']['1']['author']); } /** * Test writing falsey values. * * @return void */ public function testDataWritingFalsey() { $request = new CakeRequest('posts/index'); $request->data('Post.null', null); $this->assertNull($request->data['Post']['null']); $request->data('Post.false', false); $this->assertFalse($request->data['Post']['false']); $request->data('Post.zero', 0); $this->assertSame(0, $request->data['Post']['zero']); $request->data('Post.empty', ''); $this->assertSame('', $request->data['Post']['empty']); } /** * Test reading params * * @dataProvider paramReadingDataProvider */ public function testParamReading($toRead, $expected) { $request = new CakeRequest('/'); $request->addParams(array( 'action' => 'index', 'foo' => 'bar', 'baz' => array( 'a' => array( 'b' => 'c', ), ), 'admin' => true, 'truthy' => 1, 'zero' => '0', )); $this->assertEquals($expected, $request->param($toRead)); } /** * Data provider for testing reading values with CakeRequest::param() * * @return array */ public function paramReadingDataProvider() { return array( array( 'action', 'index', ), array( 'baz', array( 'a' => array( 'b' => 'c', ), ), ), array( 'baz.a.b', 'c', ), array( 'does_not_exist', false, ), array( 'admin', true, ), array( 'truthy', 1, ), array( 'zero', '0', ), ); } /** * test writing request params with param() * * @return void */ public function testParamWriting() { $request = new CakeRequest('/'); $request->addParams(array( 'action' => 'index', )); $this->assertInstanceOf('CakeRequest', $request->param('some', 'thing'), 'Method has not returned $this'); $request->param('Post.null', null); $this->assertNull($request->params['Post']['null']); $request->param('Post.false', false); $this->assertFalse($request->params['Post']['false']); $request->param('Post.zero', 0); $this->assertSame(0, $request->params['Post']['zero']); $request->param('Post.empty', ''); $this->assertSame('', $request->params['Post']['empty']); $this->assertSame('index', $request->action); $request->param('action', 'edit'); $this->assertSame('edit', $request->action); } /** * Test accept language * * @return void */ public function testAcceptLanguage() { // Weird language $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'inexistent,en-ca'; $result = CakeRequest::acceptLanguage(); $this->assertEquals(array('inexistent', 'en-ca'), $result, 'Languages do not match'); // No qualifier $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'es_mx,en_ca'; $result = CakeRequest::acceptLanguage(); $this->assertEquals(array('es-mx', 'en-ca'), $result, 'Languages do not match'); // With qualifier $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'en-US,en;q=0.8,pt-BR;q=0.6,pt;q=0.4'; $result = CakeRequest::acceptLanguage(); $this->assertEquals(array('en-us', 'en', 'pt-br', 'pt'), $result, 'Languages do not match'); // With spaces $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'da, en-gb;q=0.8, en;q=0.7'; $result = CakeRequest::acceptLanguage(); $this->assertEquals(array('da', 'en-gb', 'en'), $result, 'Languages do not match'); // Checking if requested $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'es_mx,en_ca'; CakeRequest::acceptLanguage(); $result = CakeRequest::acceptLanguage('en-ca'); $this->assertTrue($result); $result = CakeRequest::acceptLanguage('en-CA'); $this->assertTrue($result); $result = CakeRequest::acceptLanguage('en-us'); $this->assertFalse($result); $result = CakeRequest::acceptLanguage('en-US'); $this->assertFalse($result); } /** * Test the here() method * * @return void */ public function testHere() { Configure::write('App.base', '/base_path'); $_GET = array('test' => 'value'); $request = new CakeRequest('/posts/add/1/name:value'); $result = $request->here(); $this->assertEquals('/base_path/posts/add/1/name:value?test=value', $result); $result = $request->here(false); $this->assertEquals('/posts/add/1/name:value?test=value', $result); $request = new CakeRequest('/posts/base_path/1/name:value'); $result = $request->here(); $this->assertEquals('/base_path/posts/base_path/1/name:value?test=value', $result); $result = $request->here(false); $this->assertEquals('/posts/base_path/1/name:value?test=value', $result); } /** * Test the here() with space in URL * * @return void */ public function testHereWithSpaceInUrl() { Configure::write('App.base', ''); $_GET = array('/admin/settings/settings/prefix/Access_Control' => ''); $request = new CakeRequest('/admin/settings/settings/prefix/Access%20Control'); $result = $request->here(); $this->assertEquals('/admin/settings/settings/prefix/Access%20Control', $result); } /** * Test the input() method. * * @return void */ public function testSetInput() { $request = new CakeRequest('/'); $request->setInput('I came from setInput'); $result = $request->input(); $this->assertEquals('I came from setInput', $result); $result = $request->input(); $this->assertEquals('I came from setInput', $result); } /** * Test the input() method. * * @return void */ public function testInput() { $request = $this->getMock('CakeRequest', array('_readInput')); $request->expects($this->once())->method('_readInput') ->will($this->returnValue('I came from stdin')); $result = $request->input(); $this->assertEquals('I came from stdin', $result); } /** * Test input() decoding. * * @return void */ public function testInputDecode() { $request = $this->getMock('CakeRequest', array('_readInput')); $request->expects($this->once())->method('_readInput') ->will($this->returnValue('{"name":"value"}')); $result = $request->input('json_decode'); $this->assertEquals(array('name' => 'value'), (array)$result); } /** * Test input() decoding with additional arguments. * * @return void */ public function testInputDecodeExtraParams() { $xml = << Test XML; $request = $this->getMock('CakeRequest', array('_readInput')); $request->expects($this->once())->method('_readInput') ->will($this->returnValue($xml)); $result = $request->input('Xml::build', array('return' => 'domdocument')); $this->assertInstanceOf('DOMDocument', $result); $this->assertEquals( 'Test', $result->getElementsByTagName('title')->item(0)->childNodes->item(0)->wholeText ); } /** * Test is('requested') and isRequested() * * @return void */ public function testIsRequested() { $request = new CakeRequest('/posts/index'); $request->addParams(array( 'controller' => 'posts', 'action' => 'index', 'plugin' => null, 'requested' => 1 )); $this->assertTrue($request->is('requested')); $this->assertTrue($request->isRequested()); $request = new CakeRequest('/posts/index'); $request->addParams(array( 'controller' => 'posts', 'action' => 'index', 'plugin' => null, )); $this->assertFalse($request->is('requested')); $this->assertFalse($request->isRequested()); } /** * Test allowMethod method * * @return void */ public function testAllowMethod() { $_SERVER['REQUEST_METHOD'] = 'PUT'; $request = new CakeRequest('/posts/edit/1'); $this->assertTrue($request->allowMethod(array('put'))); // BC check $this->assertTrue($request->onlyAllow(array('put'))); $_SERVER['REQUEST_METHOD'] = 'DELETE'; $this->assertTrue($request->allowMethod('post', 'delete')); // BC check $this->assertTrue($request->onlyAllow('post', 'delete')); } /** * Test allowMethod throwing exception * * @return void */ public function testAllowMethodException() { $_SERVER['REQUEST_METHOD'] = 'PUT'; $request = new CakeRequest('/posts/edit/1'); try { $request->allowMethod('POST', 'DELETE'); $this->fail('An expected exception has not been raised.'); } catch (MethodNotAllowedException $e) { $this->assertEquals(array('Allow' => 'POST, DELETE'), $e->responseHeader()); } $this->setExpectedException('MethodNotAllowedException'); $request->allowMethod('POST'); } /** * Tests that overriding the method to GET will clean all request * data, to better simulate a GET request. * * @return void */ public function testMethodOverrideEmptyData() { $_POST = array('_method' => 'GET', 'foo' => 'bar'); $_SERVER['REQUEST_METHOD'] = 'PUT'; $request = new CakeRequest('/posts/edit/1'); $this->assertEmpty($request->data); $_POST = array('foo' => 'bar'); $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'GET'; $request = new CakeRequest('/posts/edit/1'); $this->assertEmpty($request->data); } /** * loadEnvironment method * * @param array $env * @return void */ protected function _loadEnvironment($env) { if (isset($env['App'])) { Configure::write('App', $env['App']); } if (isset($env['GET'])) { foreach ($env['GET'] as $key => $val) { $_GET[$key] = $val; } } if (isset($env['POST'])) { foreach ($env['POST'] as $key => $val) { $_POST[$key] = $val; } } if (isset($env['SERVER'])) { foreach ($env['SERVER'] as $key => $val) { $_SERVER[$key] = $val; } } } } cakephp-2.8.0/lib/Cake/Test/Case/Network/CakeResponseTest.php000066400000000000000000001572331265552240500237440ustar00rootroot00000000000000assertNull($response->body()); $this->assertEquals('UTF-8', $response->charset()); $this->assertEquals('text/html', $response->type()); $this->assertEquals(200, $response->statusCode()); $options = array( 'body' => 'This is the body', 'charset' => 'my-custom-charset', 'type' => 'mp3', 'status' => '203' ); $response = new CakeResponse($options); $this->assertEquals('This is the body', $response->body()); $this->assertEquals('my-custom-charset', $response->charset()); $this->assertEquals('audio/mpeg', $response->type()); $this->assertEquals(203, $response->statusCode()); $options = array( 'body' => 'This is the body', 'charset' => 'my-custom-charset', 'type' => 'mp3', 'status' => '422', 'statusCodes' => array( 422 => 'Unprocessable Entity' ) ); $response = new CakeResponse($options); $this->assertEquals($options['body'], $response->body()); $this->assertEquals($options['charset'], $response->charset()); $this->assertEquals($response->getMimeType($options['type']), $response->type()); $this->assertEquals($options['status'], $response->statusCode()); } /** * Tests the body method * * @return void */ public function testBody() { $response = new CakeResponse(); $this->assertNull($response->body()); $response->body('Response body'); $this->assertEquals('Response body', $response->body()); $this->assertEquals('Changed Body', $response->body('Changed Body')); } /** * Tests the charset method * * @return void */ public function testCharset() { $response = new CakeResponse(); $this->assertEquals('UTF-8', $response->charset()); $response->charset('iso-8859-1'); $this->assertEquals('iso-8859-1', $response->charset()); $this->assertEquals('UTF-16', $response->charset('UTF-16')); } /** * Tests the statusCode method * * @expectedException CakeException * @return void */ public function testStatusCode() { $response = new CakeResponse(); $this->assertEquals(200, $response->statusCode()); $response->statusCode(404); $this->assertEquals(404, $response->statusCode()); $this->assertEquals(500, $response->statusCode(500)); //Throws exception $response->statusCode(1001); } /** * Tests the type method * * @return void */ public function testType() { $response = new CakeResponse(); $this->assertEquals('text/html', $response->type()); $response->type('pdf'); $this->assertEquals('application/pdf', $response->type()); $this->assertEquals('application/crazy-mime', $response->type('application/crazy-mime')); $this->assertEquals('application/json', $response->type('json')); $this->assertEquals('text/vnd.wap.wml', $response->type('wap')); $this->assertEquals('application/vnd.wap.xhtml+xml', $response->type('xhtml-mobile')); $this->assertEquals('text/csv', $response->type('csv')); $response->type(array('keynote' => 'application/keynote', 'bat' => 'application/bat')); $this->assertEquals('application/keynote', $response->type('keynote')); $this->assertEquals('application/bat', $response->type('bat')); $this->assertFalse($response->type('wackytype')); } /** * Tests the header method * * @return void */ public function testHeader() { $response = new CakeResponse(); $headers = array(); $this->assertEquals($headers, $response->header()); $response->header('Location', 'http://example.com'); $headers += array('Location' => 'http://example.com'); $this->assertEquals($headers, $response->header()); //Headers with the same name are overwritten $response->header('Location', 'http://example2.com'); $headers = array('Location' => 'http://example2.com'); $this->assertEquals($headers, $response->header()); $response->header(array('WWW-Authenticate' => 'Negotiate')); $headers += array('WWW-Authenticate' => 'Negotiate'); $this->assertEquals($headers, $response->header()); $response->header(array('WWW-Authenticate' => 'Not-Negotiate')); $headers['WWW-Authenticate'] = 'Not-Negotiate'; $this->assertEquals($headers, $response->header()); $response->header(array('Age' => 12, 'Allow' => 'GET, HEAD')); $headers += array('Age' => 12, 'Allow' => 'GET, HEAD'); $this->assertEquals($headers, $response->header()); // String headers are allowed $response->header('Content-Language: da'); $headers += array('Content-Language' => 'da'); $this->assertEquals($headers, $response->header()); $response->header('Content-Language: da'); $headers += array('Content-Language' => 'da'); $this->assertEquals($headers, $response->header()); $response->header(array('Content-Encoding: gzip', 'Vary: *', 'Pragma' => 'no-cache')); $headers += array('Content-Encoding' => 'gzip', 'Vary' => '*', 'Pragma' => 'no-cache'); $this->assertEquals($headers, $response->header()); $response->header('Access-Control-Allow-Origin', array('domain1', 'domain2')); $headers += array('Access-Control-Allow-Origin' => array('domain1', 'domain2')); $this->assertEquals($headers, $response->header()); } /** * Tests the send method * * @return void */ public function testSend() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies')); $response->header(array( 'Content-Language' => 'es', 'WWW-Authenticate' => 'Negotiate', 'Access-Control-Allow-Origin' => array('domain1', 'domain2'), )); $response->body('the response body'); $response->expects($this->once())->method('_sendContent')->with('the response body'); $response->expects($this->at(0))->method('_setCookies'); $response->expects($this->at(1)) ->method('_sendHeader')->with('HTTP/1.1 200 OK'); $response->expects($this->at(2)) ->method('_sendHeader')->with('Content-Language', 'es'); $response->expects($this->at(3)) ->method('_sendHeader')->with('WWW-Authenticate', 'Negotiate'); $response->expects($this->at(4)) ->method('_sendHeader')->with('Access-Control-Allow-Origin', 'domain1'); $response->expects($this->at(5)) ->method('_sendHeader')->with('Access-Control-Allow-Origin', 'domain2'); $response->expects($this->at(6)) ->method('_sendHeader')->with('Content-Length', 17); $response->expects($this->at(7)) ->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8'); $response->send(); } /** * Data provider for content type tests. * * @return array */ public static function charsetTypeProvider() { return array( array('mp3', 'audio/mpeg'), array('js', 'application/javascript; charset=UTF-8'), array('json', 'application/json; charset=UTF-8'), array('xml', 'application/xml; charset=UTF-8'), array('txt', 'text/plain; charset=UTF-8'), ); } /** * Tests the send method and changing the content type * * @dataProvider charsetTypeProvider * @return void */ public function testSendChangingContentType($original, $expected) { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies')); $response->type($original); $response->body('the response body'); $response->expects($this->once())->method('_sendContent')->with('the response body'); $response->expects($this->at(0))->method('_setCookies'); $response->expects($this->at(1)) ->method('_sendHeader')->with('HTTP/1.1 200 OK'); $response->expects($this->at(2)) ->method('_sendHeader')->with('Content-Length', 17); $response->expects($this->at(3)) ->method('_sendHeader')->with('Content-Type', $expected); $response->send(); } /** * Tests the send method and changing the content type to JS without adding the charset * * @return void */ public function testSendChangingContentTypeWithoutCharset() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies')); $response->type('js'); $response->charset(''); $response->body('var $foo = "bar";'); $response->expects($this->once())->method('_sendContent')->with('var $foo = "bar";'); $response->expects($this->at(0))->method('_setCookies'); $response->expects($this->at(1)) ->method('_sendHeader')->with('HTTP/1.1 200 OK'); $response->expects($this->at(2)) ->method('_sendHeader')->with('Content-Length', 17); $response->expects($this->at(3)) ->method('_sendHeader')->with('Content-Type', 'application/javascript'); $response->send(); } /** * Tests the send method and changing the content type * * @return void */ public function testSendWithLocation() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', '_setCookies')); $response->header('Location', 'http://www.example.com'); $response->expects($this->at(0))->method('_setCookies'); $response->expects($this->at(1)) ->method('_sendHeader')->with('HTTP/1.1 302 Found'); $response->expects($this->at(2)) ->method('_sendHeader')->with('Location', 'http://www.example.com'); $response->expects($this->at(3)) ->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8'); $response->send(); } /** * Tests the disableCache method * * @return void */ public function testDisableCache() { $response = new CakeResponse(); $expected = array( 'Expires' => 'Mon, 26 Jul 1997 05:00:00 GMT', 'Last-Modified' => gmdate("D, d M Y H:i:s") . " GMT", 'Cache-Control' => 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0' ); $response->disableCache(); $this->assertEquals($expected, $response->header()); } /** * Tests the cache method * * @return void */ public function testCache() { $response = new CakeResponse(); $since = time(); $time = new DateTime('+1 day', new DateTimeZone('UTC')); $response->expires('+1 day'); $expected = array( 'Date' => gmdate("D, j M Y G:i:s ", $since) . 'GMT', 'Last-Modified' => gmdate("D, j M Y H:i:s ", $since) . 'GMT', 'Expires' => $time->format('D, j M Y H:i:s') . ' GMT', 'Cache-Control' => 'public, max-age=' . ($time->format('U') - time()) ); $response->cache($since); $this->assertEquals($expected, $response->header()); $response = new CakeResponse(); $since = time(); $time = '+5 day'; $expected = array( 'Date' => gmdate("D, j M Y G:i:s ", $since) . 'GMT', 'Last-Modified' => gmdate("D, j M Y H:i:s ", $since) . 'GMT', 'Expires' => gmdate("D, j M Y H:i:s", strtotime($time)) . " GMT", 'Cache-Control' => 'public, max-age=' . (strtotime($time) - time()) ); $response->cache($since, $time); $this->assertEquals($expected, $response->header()); $response = new CakeResponse(); $since = time(); $time = time(); $expected = array( 'Date' => gmdate("D, j M Y G:i:s ", $since) . 'GMT', 'Last-Modified' => gmdate("D, j M Y H:i:s ", $since) . 'GMT', 'Expires' => gmdate("D, j M Y H:i:s", $time) . " GMT", 'Cache-Control' => 'public, max-age=0' ); $response->cache($since, $time); $this->assertEquals($expected, $response->header()); } /** * Tests the compress method * * @return void */ public function testCompress() { if (PHP_SAPI !== 'cli') { $this->markTestSkipped('The response compression can only be tested in cli.'); } $response = new CakeResponse(); if (ini_get("zlib.output_compression") === '1' || !extension_loaded("zlib")) { $this->assertFalse($response->compress()); $this->markTestSkipped('Is not possible to test output compression'); } $_SERVER['HTTP_ACCEPT_ENCODING'] = ''; $result = $response->compress(); $this->assertFalse($result); $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip'; $result = $response->compress(); $this->assertTrue($result); $this->assertTrue(in_array('ob_gzhandler', ob_list_handlers())); ob_get_clean(); } /** * Tests the httpCodes method * * @expectedException CakeException * @return void */ public function testHttpCodes() { $response = new CakeResponse(); $result = $response->httpCodes(); $this->assertEquals(41, count($result)); $result = $response->httpCodes(100); $expected = array(100 => 'Continue'); $this->assertEquals($expected, $result); $codes = array( 381 => 'Unicorn Moved', 555 => 'Unexpected Minotaur' ); $result = $response->httpCodes($codes); $this->assertTrue($result); $this->assertEquals(43, count($response->httpCodes())); $result = $response->httpCodes(381); $expected = array(381 => 'Unicorn Moved'); $this->assertEquals($expected, $result); $codes = array(404 => 'Sorry Bro'); $result = $response->httpCodes($codes); $this->assertTrue($result); $this->assertEquals(43, count($response->httpCodes())); $result = $response->httpCodes(404); $expected = array(404 => 'Sorry Bro'); $this->assertEquals($expected, $result); //Throws exception $response->httpCodes(array( 0 => 'Nothing Here', -1 => 'Reverse Infinity', 12345 => 'Universal Password', 'Hello' => 'World' )); } /** * Tests the download method * * @return void */ public function testDownload() { $response = new CakeResponse(); $expected = array( 'Content-Disposition' => 'attachment; filename="myfile.mp3"' ); $response->download('myfile.mp3'); $this->assertEquals($expected, $response->header()); } /** * Tests the mapType method * * @return void */ public function testMapType() { $response = new CakeResponse(); $this->assertEquals('wav', $response->mapType('audio/x-wav')); $this->assertEquals('pdf', $response->mapType('application/pdf')); $this->assertEquals('xml', $response->mapType('text/xml')); $this->assertEquals('html', $response->mapType('*/*')); $this->assertEquals('csv', $response->mapType('application/vnd.ms-excel')); $expected = array('json', 'xhtml', 'css'); $result = $response->mapType(array('application/json', 'application/xhtml+xml', 'text/css')); $this->assertEquals($expected, $result); } /** * Tests the outputCompressed method * * @return void */ public function testOutputCompressed() { $response = new CakeResponse(); $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip'; $result = $response->outputCompressed(); $this->assertFalse($result); $_SERVER['HTTP_ACCEPT_ENCODING'] = ''; $result = $response->outputCompressed(); $this->assertFalse($result); if (!extension_loaded("zlib")) { $this->markTestSkipped('Skipping further tests for outputCompressed as zlib extension is not loaded'); } if (PHP_SAPI !== 'cli') { $this->markTestSkipped('Testing outputCompressed method with compression enabled done only in cli'); } if (ini_get("zlib.output_compression") !== '1') { ob_start('ob_gzhandler'); } $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip'; $result = $response->outputCompressed(); $this->assertTrue($result); $_SERVER['HTTP_ACCEPT_ENCODING'] = ''; $result = $response->outputCompressed(); $this->assertFalse($result); if (ini_get("zlib.output_compression") !== '1') { ob_get_clean(); } } /** * Tests the send and setting of Content-Length * * @return void */ public function testSendContentLength() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->body('the response body'); $response->expects($this->once())->method('_sendContent')->with('the response body'); $response->expects($this->at(0)) ->method('_sendHeader')->with('HTTP/1.1 200 OK'); $response->expects($this->at(2)) ->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8'); $response->expects($this->at(1)) ->method('_sendHeader')->with('Content-Length', strlen('the response body')); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $body = '้•ทใ„้•ทใ„้•ทใ„Subjectใฎๅ ดๅˆใฏfoldingใ™ใ‚‹ใฎใŒๆญฃใ—ใ„ใ‚“ใ ใ‘ใฉใ„ใฃใŸใ„ใฉใ†ใชใ‚‹ใ‚“ใ ใ‚ใ†๏ผŸ'; $response->body($body); $response->expects($this->once())->method('_sendContent')->with($body); $response->expects($this->at(0)) ->method('_sendHeader')->with('HTTP/1.1 200 OK'); $response->expects($this->at(2)) ->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8'); $response->expects($this->at(1)) ->method('_sendHeader')->with('Content-Length', 116); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', 'outputCompressed')); $body = '้•ทใ„้•ทใ„้•ทใ„Subjectใฎๅ ดๅˆใฏfoldingใ™ใ‚‹ใฎใŒๆญฃใ—ใ„ใ‚“ใ ใ‘ใฉใ„ใฃใŸใ„ใฉใ†ใชใ‚‹ใ‚“ใ ใ‚ใ†๏ผŸ'; $response->body($body); $response->expects($this->once())->method('outputCompressed')->will($this->returnValue(true)); $response->expects($this->once())->method('_sendContent')->with($body); $response->expects($this->exactly(2))->method('_sendHeader'); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent', 'outputCompressed')); $body = 'hwy'; $response->body($body); $response->header('Content-Length', 1); $response->expects($this->never())->method('outputCompressed'); $response->expects($this->once())->method('_sendContent')->with($body); $response->expects($this->at(1)) ->method('_sendHeader')->with('Content-Length', 1); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $body = 'content'; $response->statusCode(301); $response->body($body); $response->expects($this->once())->method('_sendContent')->with($body); $response->expects($this->exactly(2))->method('_sendHeader'); $response->send(); ob_start(); $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $goofyOutput = 'I am goofily sending output in the controller'; echo $goofyOutput; $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $body = '้•ทใ„้•ทใ„้•ทใ„Subjectใฎๅ ดๅˆใฏfoldingใ™ใ‚‹ใฎใŒๆญฃใ—ใ„ใ‚“ใ ใ‘ใฉใ„ใฃใŸใ„ใฉใ†ใชใ‚‹ใ‚“ใ ใ‚ใ†๏ผŸ'; $response->body($body); $response->expects($this->once())->method('_sendContent')->with($body); $response->expects($this->at(0)) ->method('_sendHeader')->with('HTTP/1.1 200 OK'); $response->expects($this->at(1)) ->method('_sendHeader')->with('Content-Length', strlen($goofyOutput) + 116); $response->expects($this->at(2)) ->method('_sendHeader')->with('Content-Type', 'text/html; charset=UTF-8'); $response->send(); ob_end_clean(); } /** * Tests getting/setting the protocol * * @return void */ public function testProtocol() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->protocol('HTTP/1.0'); $this->assertEquals('HTTP/1.0', $response->protocol()); $response->expects($this->at(0)) ->method('_sendHeader')->with('HTTP/1.0 200 OK'); $response->send(); } /** * Tests getting/setting the Content-Length * * @return void */ public function testLength() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->length(100); $this->assertEquals(100, $response->length()); $response->expects($this->at(1)) ->method('_sendHeader')->with('Content-Length', 100); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->length(false); $this->assertFalse($response->length()); $response->expects($this->exactly(2)) ->method('_sendHeader'); $response->send(); } /** * Tests that the response body is unset if the status code is 304 or 204 * * @return void */ public function testUnmodifiedContent() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->body('This is a body'); $response->statusCode(204); $response->expects($this->once()) ->method('_sendContent')->with(''); $response->send(); $this->assertFalse(array_key_exists('Content-Type', $response->header())); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->body('This is a body'); $response->statusCode(304); $response->expects($this->once()) ->method('_sendContent')->with(''); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->body('This is a body'); $response->statusCode(200); $response->expects($this->once()) ->method('_sendContent')->with('This is a body'); $response->send(); } /** * Tests setting the expiration date * * @return void */ public function testExpires() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $now = new DateTime('now', new DateTimeZone('America/Los_Angeles')); $response->expires($now); $now->setTimeZone(new DateTimeZone('UTC')); $this->assertEquals($now->format('D, j M Y H:i:s') . ' GMT', $response->expires()); $response->expects($this->at(1)) ->method('_sendHeader')->with('Expires', $now->format('D, j M Y H:i:s') . ' GMT'); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $now = time(); $response->expires($now); $this->assertEquals(gmdate('D, j M Y H:i:s', $now) . ' GMT', $response->expires()); $response->expects($this->at(1)) ->method('_sendHeader')->with('Expires', gmdate('D, j M Y H:i:s', $now) . ' GMT'); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $time = new DateTime('+1 day', new DateTimeZone('UTC')); $response->expires('+1 day'); $this->assertEquals($time->format('D, j M Y H:i:s') . ' GMT', $response->expires()); $response->expects($this->at(1)) ->method('_sendHeader')->with('Expires', $time->format('D, j M Y H:i:s') . ' GMT'); $response->send(); } /** * Tests setting the modification date * * @return void */ public function testModified() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $now = new DateTime('now', new DateTimeZone('America/Los_Angeles')); $response->modified($now); $now->setTimeZone(new DateTimeZone('UTC')); $this->assertEquals($now->format('D, j M Y H:i:s') . ' GMT', $response->modified()); $response->expects($this->at(1)) ->method('_sendHeader')->with('Last-Modified', $now->format('D, j M Y H:i:s') . ' GMT'); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $now = time(); $response->modified($now); $this->assertEquals(gmdate('D, j M Y H:i:s', $now) . ' GMT', $response->modified()); $response->expects($this->at(1)) ->method('_sendHeader')->with('Last-Modified', gmdate('D, j M Y H:i:s', $now) . ' GMT'); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $time = new DateTime('+1 day', new DateTimeZone('UTC')); $response->modified('+1 day'); $this->assertEquals($time->format('D, j M Y H:i:s') . ' GMT', $response->modified()); $response->expects($this->at(1)) ->method('_sendHeader')->with('Last-Modified', $time->format('D, j M Y H:i:s') . ' GMT'); $response->send(); } /** * Tests setting of public/private Cache-Control directives * * @return void */ public function testSharable() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $this->assertNull($response->sharable()); $response->sharable(true); $headers = $response->header(); $this->assertEquals('public', $headers['Cache-Control']); $response->expects($this->at(1)) ->method('_sendHeader')->with('Cache-Control', 'public'); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->sharable(false); $headers = $response->header(); $this->assertEquals('private', $headers['Cache-Control']); $response->expects($this->at(1)) ->method('_sendHeader')->with('Cache-Control', 'private'); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->sharable(true); $headers = $response->header(); $this->assertEquals('public', $headers['Cache-Control']); $response->sharable(false); $headers = $response->header(); $this->assertEquals('private', $headers['Cache-Control']); $response->expects($this->at(1)) ->method('_sendHeader')->with('Cache-Control', 'private'); $response->send(); $this->assertFalse($response->sharable()); $response->sharable(true); $this->assertTrue($response->sharable()); $response = new CakeResponse; $response->sharable(true, 3600); $headers = $response->header(); $this->assertEquals('public, max-age=3600', $headers['Cache-Control']); $response = new CakeResponse; $response->sharable(false, 3600); $headers = $response->header(); $this->assertEquals('private, max-age=3600', $headers['Cache-Control']); $response->send(); } /** * Tests setting of max-age Cache-Control directive * * @return void */ public function testMaxAge() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $this->assertNull($response->maxAge()); $response->maxAge(3600); $this->assertEquals(3600, $response->maxAge()); $headers = $response->header(); $this->assertEquals('max-age=3600', $headers['Cache-Control']); $response->expects($this->at(1)) ->method('_sendHeader')->with('Cache-Control', 'max-age=3600'); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->maxAge(3600); $response->sharable(false); $headers = $response->header(); $this->assertEquals('max-age=3600, private', $headers['Cache-Control']); $response->expects($this->at(1)) ->method('_sendHeader')->with('Cache-Control', 'max-age=3600, private'); $response->send(); } /** * Tests setting of s-maxage Cache-Control directive * * @return void */ public function testSharedMaxAge() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $this->assertNull($response->maxAge()); $response->sharedMaxAge(3600); $this->assertEquals(3600, $response->sharedMaxAge()); $headers = $response->header(); $this->assertEquals('s-maxage=3600', $headers['Cache-Control']); $response->expects($this->at(1)) ->method('_sendHeader')->with('Cache-Control', 's-maxage=3600'); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->sharedMaxAge(3600); $response->sharable(true); $headers = $response->header(); $this->assertEquals('s-maxage=3600, public', $headers['Cache-Control']); $response->expects($this->at(1)) ->method('_sendHeader')->with('Cache-Control', 's-maxage=3600, public'); $response->send(); } /** * Tests setting of must-revalidate Cache-Control directive * * @return void */ public function testMustRevalidate() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $this->assertFalse($response->mustRevalidate()); $response->mustRevalidate(true); $this->assertTrue($response->mustRevalidate()); $headers = $response->header(); $this->assertEquals('must-revalidate', $headers['Cache-Control']); $response->expects($this->at(1)) ->method('_sendHeader')->with('Cache-Control', 'must-revalidate'); $response->send(); $response->mustRevalidate(false); $this->assertFalse($response->mustRevalidate()); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->sharedMaxAge(3600); $response->mustRevalidate(true); $headers = $response->header(); $this->assertEquals('s-maxage=3600, must-revalidate', $headers['Cache-Control']); $response->expects($this->at(1)) ->method('_sendHeader')->with('Cache-Control', 's-maxage=3600, must-revalidate'); $response->send(); } /** * Tests getting/setting the Vary header * * @return void */ public function testVary() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->vary('Accept-encoding'); $this->assertEquals(array('Accept-encoding'), $response->vary()); $response->expects($this->at(1)) ->method('_sendHeader')->with('Vary', 'Accept-encoding'); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->vary(array('Accept-language', 'Accept-encoding')); $response->expects($this->at(1)) ->method('_sendHeader')->with('Vary', 'Accept-language, Accept-encoding'); $response->send(); $this->assertEquals(array('Accept-language', 'Accept-encoding'), $response->vary()); } /** * Tests getting/setting the Etag header * * @return void */ public function testEtag() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->etag('something'); $this->assertEquals('"something"', $response->etag()); $response->expects($this->at(1)) ->method('_sendHeader')->with('Etag', '"something"'); $response->send(); $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->etag('something', true); $this->assertEquals('W/"something"', $response->etag()); $response->expects($this->at(1)) ->method('_sendHeader')->with('Etag', 'W/"something"'); $response->send(); } /** * Tests that the response is able to be marked as not modified * * @return void */ public function testNotModified() { $response = $this->getMock('CakeResponse', array('_sendHeader', '_sendContent')); $response->body('something'); $response->statusCode(200); $response->length(100); $response->modified('now'); $response->notModified(); $this->assertEmpty($response->header()); $this->assertEmpty($response->body()); $this->assertEquals(304, $response->statusCode()); } /** * Test checkNotModified method * * @return void */ public function testCheckNotModifiedByEtagStar() { $_SERVER['HTTP_IF_NONE_MATCH'] = '*'; $response = $this->getMock('CakeResponse', array('notModified')); $response->etag('something'); $response->expects($this->once())->method('notModified'); $response->checkNotModified(new CakeRequest); } /** * Test checkNotModified method * * @return void */ public function testCheckNotModifiedByEtagExact() { $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"'; $response = $this->getMock('CakeResponse', array('notModified')); $response->etag('something', true); $response->expects($this->once())->method('notModified'); $this->assertTrue($response->checkNotModified(new CakeRequest)); } /** * Test checkNotModified method * * @return void */ public function testCheckNotModifiedByEtagAndTime() { $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"'; $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00'; $response = $this->getMock('CakeResponse', array('notModified')); $response->etag('something', true); $response->modified('2012-01-01 00:00:00'); $response->expects($this->once())->method('notModified'); $this->assertTrue($response->checkNotModified(new CakeRequest)); } /** * Test checkNotModified method * * @return void */ public function testCheckNotModifiedByEtagAndTimeMismatch() { $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"'; $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00'; $response = $this->getMock('CakeResponse', array('notModified')); $response->etag('something', true); $response->modified('2012-01-01 00:00:01'); $response->expects($this->never())->method('notModified'); $this->assertFalse($response->checkNotModified(new CakeRequest)); } /** * Test checkNotModified method * * @return void */ public function testCheckNotModifiedByEtagMismatch() { $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something-else", "other"'; $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00'; $response = $this->getMock('CakeResponse', array('notModified')); $response->etag('something', true); $response->modified('2012-01-01 00:00:00'); $response->expects($this->never())->method('notModified'); $this->assertFalse($response->checkNotModified(new CakeRequest)); } /** * Test checkNotModified method * * @return void */ public function testCheckNotModifiedByTime() { $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00'; $response = $this->getMock('CakeResponse', array('notModified')); $response->modified('2012-01-01 00:00:00'); $response->expects($this->once())->method('notModified'); $this->assertTrue($response->checkNotModified(new CakeRequest)); } /** * Test checkNotModified method * * @return void */ public function testCheckNotModifiedNoHints() { $_SERVER['HTTP_IF_NONE_MATCH'] = 'W/"something", "other"'; $_SERVER['HTTP_IF_MODIFIED_SINCE'] = '2012-01-01 00:00:00'; $response = $this->getMock('CakeResponse', array('notModified')); $response->expects($this->never())->method('notModified'); $this->assertFalse($response->checkNotModified(new CakeRequest)); } /** * Test cookie setting * * @return void */ public function testCookieSettings() { $response = new CakeResponse(); $cookie = array( 'name' => 'CakeTestCookie[Testing]' ); $response->cookie($cookie); $expected = array( 'name' => 'CakeTestCookie[Testing]', 'value' => '', 'expire' => 0, 'path' => '/', 'domain' => '', 'secure' => false, 'httpOnly' => false); $result = $response->cookie('CakeTestCookie[Testing]'); $this->assertEquals($expected, $result); $cookie = array( 'name' => 'CakeTestCookie[Testing2]', 'value' => '[a,b,c]', 'expire' => 1000, 'path' => '/test', 'secure' => true ); $response->cookie($cookie); $expected = array( 'CakeTestCookie[Testing]' => array( 'name' => 'CakeTestCookie[Testing]', 'value' => '', 'expire' => 0, 'path' => '/', 'domain' => '', 'secure' => false, 'httpOnly' => false ), 'CakeTestCookie[Testing2]' => array( 'name' => 'CakeTestCookie[Testing2]', 'value' => '[a,b,c]', 'expire' => 1000, 'path' => '/test', 'domain' => '', 'secure' => true, 'httpOnly' => false ) ); $result = $response->cookie(); $this->assertEquals($expected, $result); $cookie = $expected['CakeTestCookie[Testing]']; $cookie['value'] = 'test'; $response->cookie($cookie); $expected = array( 'CakeTestCookie[Testing]' => array( 'name' => 'CakeTestCookie[Testing]', 'value' => 'test', 'expire' => 0, 'path' => '/', 'domain' => '', 'secure' => false, 'httpOnly' => false ), 'CakeTestCookie[Testing2]' => array( 'name' => 'CakeTestCookie[Testing2]', 'value' => '[a,b,c]', 'expire' => 1000, 'path' => '/test', 'domain' => '', 'secure' => true, 'httpOnly' => false ) ); $result = $response->cookie(); $this->assertEquals($expected, $result); } /** * Test CORS * * @dataProvider corsData * @param CakeRequest $request * @param string $origin * @param string|array $domains * @param string|array $methods * @param string|array $headers * @param string|bool $expectedOrigin * @param string|bool $expectedMethods * @param string|bool $expectedHeaders * @return void */ public function testCors($request, $origin, $domains, $methods, $headers, $expectedOrigin, $expectedMethods = false, $expectedHeaders = false) { $_SERVER['HTTP_ORIGIN'] = $origin; $response = $this->getMock('CakeResponse', array('header')); $method = $response->expects(!$expectedOrigin ? $this->never() : $this->at(0))->method('header'); $expectedOrigin && $method->with('Access-Control-Allow-Origin', $expectedOrigin ? $expectedOrigin : $this->anything()); $i = 1; if ($expectedMethods) { $response->expects($this->at($i++)) ->method('header') ->with('Access-Control-Allow-Methods', $expectedMethods ? $expectedMethods : $this->anything()); } if ($expectedHeaders) { $response->expects($this->at($i++)) ->method('header') ->with('Access-Control-Allow-Headers', $expectedHeaders ? $expectedHeaders : $this->anything()); } $response->cors($request, $domains, $methods, $headers); unset($_SERVER['HTTP_ORIGIN']); } /** * Feed for testCors * * @return array */ public function corsData() { $fooRequest = new CakeRequest(); $secureRequest = $this->getMock('CakeRequest', array('is')); $secureRequest->expects($this->any()) ->method('is') ->with('ssl') ->will($this->returnValue(true)); return array( array($fooRequest, null, '*', '', '', false, false), array($fooRequest, 'http://www.foo.com', '*', '', '', '*', false), array($fooRequest, 'http://www.foo.com', 'www.foo.com', '', '', 'http://www.foo.com', false), array($fooRequest, 'http://www.foo.com', '*.foo.com', '', '', 'http://www.foo.com', false), array($fooRequest, 'http://www.foo.com', 'http://*.foo.com', '', '', 'http://www.foo.com', false), array($fooRequest, 'http://www.foo.com', 'https://www.foo.com', '', '', false, false), array($fooRequest, 'http://www.foo.com', 'https://*.foo.com', '', '', false, false), array($fooRequest, 'http://www.foo.com', array('*.bar.com', '*.foo.com'), '', '', 'http://www.foo.com', false), array($secureRequest, 'https://www.bar.com', 'www.bar.com', '', '', 'https://www.bar.com', false), array($secureRequest, 'https://www.bar.com', 'http://www.bar.com', '', '', false, false), array($secureRequest, 'https://www.bar.com', '*.bar.com', '', '', 'https://www.bar.com', false), array($fooRequest, 'http://www.foo.com', '*', 'GET', '', '*', 'GET'), array($fooRequest, 'http://www.foo.com', '*.foo.com', 'GET', '', 'http://www.foo.com', 'GET'), array($fooRequest, 'http://www.foo.com', '*.foo.com', array('GET', 'POST'), '', 'http://www.foo.com', 'GET, POST'), array($fooRequest, 'http://www.foo.com', '*', '', 'X-CakePHP', '*', false, 'X-CakePHP'), array($fooRequest, 'http://www.foo.com', '*', '', array('X-CakePHP', 'X-MyApp'), '*', false, 'X-CakePHP, X-MyApp'), array($fooRequest, 'http://www.foo.com', '*', array('GET', 'OPTIONS'), array('X-CakePHP', 'X-MyApp'), '*', 'GET, OPTIONS', 'X-CakePHP, X-MyApp'), ); } /** * testFileNotFound * * @expectedException NotFoundException * @return void */ public function testFileNotFound() { $response = new CakeResponse(); $response->file('/some/missing/folder/file.jpg'); } /** * test file with ../ * * @expectedException NotFoundException * @expectedExceptionMessage The requested file contains `..` and will not be read. * @return void */ public function testFileWithForwardSlashPathTraversal() { $response = new CakeResponse(); $response->file('my/../cat.gif'); } /** * test file with ..\ * * @expectedException NotFoundException * @expectedExceptionMessage The requested file contains `..` and will not be read. * @return void */ public function testFileWithBackwardSlashPathTraversal() { $response = new CakeResponse(); $response->file('my\..\cat.gif'); } /** * Although unlikely, a file may contain dots in its filename. * This should be allowed, as long as the dots doesn't specify a path (../ or ..\) * * @expectedException NotFoundException * @execptedExceptionMessageRegExp #The requested file .+my/Some..cat.gif was not found or not readable# * @return void */ public function testFileWithDotsInFilename() { $response = new CakeResponse(); $response->file('my/Some..cat.gif'); } /** * testFile method * * @return void */ public function testFile() { $response = $this->getMock('CakeResponse', array( 'header', 'type', '_sendHeader', '_setContentType', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->exactly(1)) ->method('type') ->with('css') ->will($this->returnArgument(0)); $response->expects($this->at(1)) ->method('header') ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(2)) ->method('header') ->with('Content-Length', 38); $response->expects($this->once())->method('_clearBuffer'); $response->expects($this->once())->method('_flushBuffer'); $response->expects($this->exactly(1)) ->method('_isActive') ->will($this->returnValue(true)); $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css'); ob_start(); $result = $response->send(); $output = ob_get_clean(); $this->assertEquals("/* this is the test asset css file */\n", $output); $this->assertNotSame(false, $result); } /** * testFileWithUnknownFileTypeGeneric method * * @return void */ public function testFileWithUnknownFileTypeGeneric() { $currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null; $_SERVER['HTTP_USER_AGENT'] = 'Some generic browser'; $response = $this->getMock('CakeResponse', array( 'header', 'type', 'download', '_sendHeader', '_setContentType', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->exactly(1)) ->method('type') ->with('ini') ->will($this->returnValue(false)); $response->expects($this->once()) ->method('download') ->with('no_section.ini'); $response->expects($this->at(2)) ->method('header') ->with('Content-Transfer-Encoding', 'binary'); $response->expects($this->at(3)) ->method('header') ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(4)) ->method('header') ->with('Content-Length', 35); $response->expects($this->once())->method('_clearBuffer'); $response->expects($this->once())->method('_flushBuffer'); $response->expects($this->exactly(1)) ->method('_isActive') ->will($this->returnValue(true)); $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini'); ob_start(); $result = $response->send(); $output = ob_get_clean(); $this->assertEquals("some_key = some_value\nbool_key = 1\n", $output); $this->assertNotSame(false, $result); if ($currentUserAgent !== null) { $_SERVER['HTTP_USER_AGENT'] = $currentUserAgent; } } /** * testFileWithUnknownFileTypeOpera method * * @return void */ public function testFileWithUnknownFileTypeOpera() { $currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null; $_SERVER['HTTP_USER_AGENT'] = 'Opera/9.80 (Windows NT 6.0; U; en) Presto/2.8.99 Version/11.10'; $response = $this->getMock('CakeResponse', array( 'header', 'type', 'download', '_sendHeader', '_setContentType', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->at(0)) ->method('type') ->with('ini') ->will($this->returnValue(false)); $response->expects($this->at(1)) ->method('type') ->with('application/octet-stream') ->will($this->returnValue(false)); $response->expects($this->once()) ->method('download') ->with('no_section.ini'); $response->expects($this->at(3)) ->method('header') ->with('Content-Transfer-Encoding', 'binary'); $response->expects($this->at(4)) ->method('header') ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(5)) ->method('header') ->with('Content-Length', 35); $response->expects($this->once())->method('_clearBuffer'); $response->expects($this->once())->method('_flushBuffer'); $response->expects($this->exactly(1)) ->method('_isActive') ->will($this->returnValue(true)); $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini'); ob_start(); $result = $response->send(); $output = ob_get_clean(); $this->assertEquals("some_key = some_value\nbool_key = 1\n", $output); $this->assertNotSame(false, $result); if ($currentUserAgent !== null) { $_SERVER['HTTP_USER_AGENT'] = $currentUserAgent; } } /** * testFileWithUnknownFileTypeIE method * * @return void */ public function testFileWithUnknownFileTypeIE() { $currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null; $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; Media Center PC 4.0; SLCC1; .NET CLR 3.0.04320)'; $response = $this->getMock('CakeResponse', array( 'header', 'type', 'download', '_sendHeader', '_setContentType', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->at(0)) ->method('type') ->with('ini') ->will($this->returnValue(false)); $response->expects($this->at(1)) ->method('type') ->with('application/force-download') ->will($this->returnValue(false)); $response->expects($this->once()) ->method('download') ->with('config.ini'); $response->expects($this->at(3)) ->method('header') ->with('Content-Transfer-Encoding', 'binary'); $response->expects($this->at(4)) ->method('header') ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(5)) ->method('header') ->with('Content-Length', 35); $response->expects($this->once())->method('_clearBuffer'); $response->expects($this->once())->method('_flushBuffer'); $response->expects($this->exactly(1)) ->method('_isActive') ->will($this->returnValue(true)); $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini', array( 'name' => 'config.ini' )); ob_start(); $result = $response->send(); $output = ob_get_clean(); $this->assertEquals("some_key = some_value\nbool_key = 1\n", $output); $this->assertNotSame(false, $result); if ($currentUserAgent !== null) { $_SERVER['HTTP_USER_AGENT'] = $currentUserAgent; } } /** * testFileWithUnknownFileNoDownload method * * @return void */ public function testFileWithUnknownFileNoDownload() { $currentUserAgent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null; $_SERVER['HTTP_USER_AGENT'] = 'Some generic browser'; $response = $this->getMock('CakeResponse', array( 'header', 'type', 'download', '_sendHeader', '_setContentType', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->exactly(1)) ->method('type') ->with('ini') ->will($this->returnValue(false)); $response->expects($this->at(1)) ->method('header') ->with('Accept-Ranges', 'bytes'); $response->expects($this->never()) ->method('download'); $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'no_section.ini', array( 'download' => false )); if ($currentUserAgent !== null) { $_SERVER['HTTP_USER_AGENT'] = $currentUserAgent; } } /** * testConnectionAbortedOnBuffering method * * @return void */ public function testConnectionAbortedOnBuffering() { $response = $this->getMock('CakeResponse', array( 'header', 'type', 'download', '_sendHeader', '_setContentType', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->any()) ->method('type') ->with('css') ->will($this->returnArgument(0)); $response->expects($this->at(0)) ->method('_isActive') ->will($this->returnValue(false)); $response->expects($this->once())->method('_clearBuffer'); $response->expects($this->never())->method('_flushBuffer'); $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css'); $result = $response->send(); $this->assertNull($result); } /** * Test downloading files with UPPERCASE extensions. * * @return void */ public function testFileUpperExtension() { $response = $this->getMock('CakeResponse', array( 'header', 'type', 'download', '_sendHeader', '_setContentType', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->any()) ->method('type') ->with('jpg') ->will($this->returnArgument(0)); $response->expects($this->at(0)) ->method('_isActive') ->will($this->returnValue(true)); $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'img' . DS . 'test_2.JPG'); } /** * Test downloading files with extension not explicitly set. * * @return void */ public function testFileExtensionNotSet() { $response = $this->getMock('CakeResponse', array( 'header', 'type', 'download', '_sendHeader', '_setContentType', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->any()) ->method('type') ->with('jpg') ->will($this->returnArgument(0)); $response->expects($this->at(0)) ->method('_isActive') ->will($this->returnValue(true)); $response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'img' . DS . 'test_2.JPG'); } /** * A data provider for testing various ranges * * @return array */ public static function rangeProvider() { return array( // suffix-byte-range array( 'bytes=-25', 25, 'bytes 13-37/38' ), array( 'bytes=0-', 38, 'bytes 0-37/38' ), array( 'bytes=10-', 28, 'bytes 10-37/38' ), array( 'bytes=10-20', 11, 'bytes 10-20/38' ), ); } /** * Test the various range offset types. * * @dataProvider rangeProvider * @return void */ public function testFileRangeOffsets($range, $length, $offsetResponse) { $_SERVER['HTTP_RANGE'] = $range; $response = $this->getMock('CakeResponse', array( 'header', 'type', '_sendHeader', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->at(1)) ->method('header') ->with('Content-Disposition', 'attachment; filename="test_asset.css"'); $response->expects($this->at(2)) ->method('header') ->with('Content-Transfer-Encoding', 'binary'); $response->expects($this->at(3)) ->method('header') ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(4)) ->method('header') ->with(array( 'Content-Length' => $length, 'Content-Range' => $offsetResponse, )); $response->expects($this->any()) ->method('_isActive') ->will($this->returnValue(true)); $response->file( CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css', array('download' => true) ); ob_start(); $result = $response->send(); ob_get_clean(); } /** * Test fetching ranges from a file. * * @return void */ public function testFileRange() { $_SERVER['HTTP_RANGE'] = 'bytes=8-25'; $response = $this->getMock('CakeResponse', array( 'header', 'type', '_sendHeader', '_setContentType', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->exactly(1)) ->method('type') ->with('css') ->will($this->returnArgument(0)); $response->expects($this->at(1)) ->method('header') ->with('Content-Disposition', 'attachment; filename="test_asset.css"'); $response->expects($this->at(2)) ->method('header') ->with('Content-Transfer-Encoding', 'binary'); $response->expects($this->at(3)) ->method('header') ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(4)) ->method('header') ->with(array( 'Content-Length' => 18, 'Content-Range' => 'bytes 8-25/38', )); $response->expects($this->once())->method('_clearBuffer'); $response->expects($this->any()) ->method('_isActive') ->will($this->returnValue(true)); $response->file( CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css', array('download' => true) ); ob_start(); $result = $response->send(); $output = ob_get_clean(); $this->assertEquals(206, $response->statusCode()); $this->assertEquals("is the test asset ", $output); $this->assertNotSame(false, $result); } /** * Test invalid file ranges. * * @return void */ public function testFileRangeInvalid() { $_SERVER['HTTP_RANGE'] = 'bytes=30-2'; $response = $this->getMock('CakeResponse', array( 'header', 'type', '_sendHeader', '_setContentType', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->at(1)) ->method('header') ->with('Content-Disposition', 'attachment; filename="test_asset.css"'); $response->expects($this->at(2)) ->method('header') ->with('Content-Transfer-Encoding', 'binary'); $response->expects($this->at(3)) ->method('header') ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(4)) ->method('header') ->with(array( 'Content-Range' => 'bytes 0-37/38', )); $response->file( CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css', array('download' => true) ); $this->assertEquals(416, $response->statusCode()); $response->send(); } /** * testFileRangeOffsetsNoDownload method * * @dataProvider rangeProvider * @return void */ public function testFileRangeOffsetsNoDownload($range, $length, $offsetResponse) { $_SERVER['HTTP_RANGE'] = $range; $response = $this->getMock('CakeResponse', array( 'header', 'type', '_sendHeader', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->at(1)) ->method('header') ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(2)) ->method('header') ->with(array( 'Content-Length' => $length, 'Content-Range' => $offsetResponse, )); $response->expects($this->any()) ->method('_isActive') ->will($this->returnValue(true)); $response->file( CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css', array('download' => false) ); ob_start(); $response->send(); ob_get_clean(); } /** * testFileRangeNoDownload method * * @return void */ public function testFileRangeNoDownload() { $_SERVER['HTTP_RANGE'] = 'bytes=8-25'; $response = $this->getMock('CakeResponse', array( 'header', 'type', '_sendHeader', '_setContentType', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->exactly(1)) ->method('type') ->with('css') ->will($this->returnArgument(0)); $response->expects($this->at(1)) ->method('header') ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(2)) ->method('header') ->with(array( 'Content-Length' => 18, 'Content-Range' => 'bytes 8-25/38', )); $response->expects($this->once())->method('_clearBuffer'); $response->expects($this->any()) ->method('_isActive') ->will($this->returnValue(true)); $response->file( CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css', array('download' => false) ); ob_start(); $result = $response->send(); $output = ob_get_clean(); $this->assertEquals(206, $response->statusCode()); $this->assertEquals("is the test asset ", $output); $this->assertNotSame(false, $result); } /** * testFileRangeInvalidNoDownload method * * @return void */ public function testFileRangeInvalidNoDownload() { $_SERVER['HTTP_RANGE'] = 'bytes=30-2'; $response = $this->getMock('CakeResponse', array( 'header', 'type', '_sendHeader', '_setContentType', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->at(1)) ->method('header') ->with('Accept-Ranges', 'bytes'); $response->expects($this->at(2)) ->method('header') ->with(array( 'Content-Range' => 'bytes 0-37/38', )); $response->file( CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css', array('download' => false) ); $this->assertEquals(416, $response->statusCode()); $response->send(); } /** * Test the location method. * * @return void */ public function testLocation() { $response = new CakeResponse(); $this->assertNull($response->location(), 'No header should be set.'); $this->assertNull($response->location('http://example.org'), 'Setting a location should return null'); $this->assertEquals('http://example.org', $response->location(), 'Reading a location should return the value.'); } } cakephp-2.8.0/lib/Cake/Test/Case/Network/CakeSocketTest.php000066400000000000000000000266301265552240500233720ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Network * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('CakeSocket', 'Network'); /** * SocketTest class * * @package Cake.Test.Case.Network */ class CakeSocketTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->Socket = new CakeSocket(array('timeout' => 1)); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Socket); } /** * testConstruct method * * @return void */ public function testConstruct() { $this->Socket = new CakeSocket(); $config = $this->Socket->config; $this->assertSame($config, array( 'persistent' => false, 'host' => 'localhost', 'protocol' => 'tcp', 'port' => 80, 'timeout' => 30 )); $this->Socket->reset(); $this->Socket->__construct(array('host' => 'foo-bar')); $config['host'] = 'foo-bar'; $this->assertSame($this->Socket->config, $config); $this->Socket = new CakeSocket(array('host' => 'www.cakephp.org', 'port' => 23, 'protocol' => 'udp')); $config = $this->Socket->config; $config['host'] = 'www.cakephp.org'; $config['port'] = 23; $config['protocol'] = 'udp'; $this->assertSame($this->Socket->config, $config); } /** * testSocketConnection method * * @return void */ public function testSocketConnection() { $this->assertFalse($this->Socket->connected); $this->Socket->disconnect(); $this->assertFalse($this->Socket->connected); try { $this->Socket->connect(); $this->assertTrue($this->Socket->connected); $this->Socket->connect(); $this->assertTrue($this->Socket->connected); $this->Socket->disconnect(); $config = array('persistent' => true); $this->Socket = new CakeSocket($config); $this->Socket->connect(); $this->assertTrue($this->Socket->connected); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * data provider function for testInvalidConnection * * @return array */ public static function invalidConnections() { return array( array(array('host' => 'invalid.host', 'port' => 9999, 'timeout' => 1)), array(array('host' => '127.0.0.1', 'port' => '70000', 'timeout' => 1)) ); } /** * testInvalidConnection method * * @dataProvider invalidConnections * @expectedException SocketException * @return void */ public function testInvalidConnection($data) { $this->Socket->config = array_merge($this->Socket->config, $data); $this->Socket->connect(); } /** * testSocketHost method * * @return void */ public function testSocketHost() { try { $this->Socket = new CakeSocket(); $this->Socket->connect(); $this->assertEquals('127.0.0.1', $this->Socket->address()); $this->assertEquals(gethostbyaddr('127.0.0.1'), $this->Socket->host()); $this->assertEquals(null, $this->Socket->lastError()); $this->assertTrue(in_array('127.0.0.1', $this->Socket->addresses())); $this->Socket = new CakeSocket(array('host' => '127.0.0.1')); $this->Socket->connect(); $this->assertEquals('127.0.0.1', $this->Socket->address()); $this->assertEquals(gethostbyaddr('127.0.0.1'), $this->Socket->host()); $this->assertEquals(null, $this->Socket->lastError()); $this->assertTrue(in_array('127.0.0.1', $this->Socket->addresses())); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * testSocketWriting method * * @return void */ public function testSocketWriting() { try { $request = "GET / HTTP/1.1\r\nConnection: close\r\n\r\n"; $this->assertTrue((bool)$this->Socket->write($request)); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * testSocketReading method * * @return void */ public function testSocketReading() { $this->Socket = new CakeSocket(array('timeout' => 5)); try { $this->Socket->connect(); $this->assertEquals(null, $this->Socket->read(26)); $config = array('host' => 'google.com', 'port' => 80, 'timeout' => 1); $this->Socket = new CakeSocket($config); $this->assertTrue($this->Socket->connect()); $this->assertEquals(null, $this->Socket->read(26)); $this->assertEquals('2: ' . __d('cake_dev', 'Connection timed out'), $this->Socket->lastError()); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * testTimeOutConnection method * * @return void */ public function testTimeOutConnection() { $config = array('host' => '127.0.0.1', 'timeout' => 0.5); $this->Socket = new CakeSocket($config); try { $this->assertTrue($this->Socket->connect()); $config = array('host' => '127.0.0.1', 'timeout' => 0.00001); $this->Socket = new CakeSocket($config); $this->assertFalse($this->Socket->read(1024 * 1024)); $this->assertEquals('2: ' . __d('cake_dev', 'Connection timed out'), $this->Socket->lastError()); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * testLastError method * * @return void */ public function testLastError() { $this->Socket = new CakeSocket(); $this->Socket->setLastError(4, 'some error here'); $this->assertEquals('4: some error here', $this->Socket->lastError()); } /** * testReset method * * @return void */ public function testReset() { $config = array( 'persistent' => true, 'host' => '127.0.0.1', 'protocol' => 'udp', 'port' => 80, 'timeout' => 20 ); $anotherSocket = new CakeSocket($config); $anotherSocket->reset(); $this->assertEquals(array(), $anotherSocket->config); } /** * testEncrypt * * @expectedException SocketException * @return void */ public function testEnableCryptoSocketExceptionNoSsl() { $this->skipIf(!extension_loaded('openssl'), 'OpenSSL is not enabled cannot test SSL.'); $configNoSslOrTls = array('host' => 'localhost', 'port' => 80, 'timeout' => 0.1); // testing exception on no ssl socket server for ssl and tls methods $this->Socket = new CakeSocket($configNoSslOrTls); $this->Socket->connect(); $this->Socket->enableCrypto('sslv3', 'client'); } /** * testEnableCryptoSocketExceptionNoTls * * @expectedException SocketException * @return void */ public function testEnableCryptoSocketExceptionNoTls() { $configNoSslOrTls = array('host' => 'localhost', 'port' => 80, 'timeout' => 0.1); // testing exception on no ssl socket server for ssl and tls methods $this->Socket = new CakeSocket($configNoSslOrTls); $this->Socket->connect(); $this->Socket->enableCrypto('tls', 'client'); } /** * Test that protocol in the host doesn't cause cert errors. * * @return void */ public function testConnectProtocolInHost() { $this->skipIf(!extension_loaded('openssl'), 'OpenSSL is not enabled cannot test SSL.'); $configSslTls = array('host' => 'ssl://smtp.gmail.com', 'port' => 465, 'timeout' => 5); $socket = new CakeSocket($configSslTls); try { $socket->connect(); $this->assertEquals('smtp.gmail.com', $socket->config['host']); $this->assertEquals('ssl', $socket->config['protocol']); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * _connectSocketToSslTls * * @return void */ protected function _connectSocketToSslTls() { $this->skipIf(!extension_loaded('openssl'), 'OpenSSL is not enabled cannot test SSL.'); $configSslTls = array('host' => 'smtp.gmail.com', 'port' => 465, 'timeout' => 5); $this->Socket = new CakeSocket($configSslTls); try { $this->Socket->connect(); } catch (SocketException $e) { $this->markTestSkipped('Cannot test network, skipping.'); } } /** * testEnableCryptoBadMode * * @expectedException InvalidArgumentException * @return void */ public function testEnableCryptoBadMode() { // testing wrong encryption mode $this->_connectSocketToSslTls(); $this->Socket->enableCrypto('doesntExistMode', 'server'); $this->Socket->disconnect(); } /** * testEnableCrypto * * @return void */ public function testEnableCrypto() { // testing on ssl server $this->_connectSocketToSslTls(); $this->assertTrue($this->Socket->enableCrypto('sslv3', 'client')); $this->Socket->disconnect(); // testing on tls server $this->_connectSocketToSslTls(); $this->assertTrue($this->Socket->enableCrypto('tls', 'client')); $this->Socket->disconnect(); } /** * testEnableCryptoExceptionEnableTwice * * @expectedException SocketException * @return void */ public function testEnableCryptoExceptionEnableTwice() { // testing on tls server $this->_connectSocketToSslTls(); $this->Socket->enableCrypto('tls', 'client'); $this->Socket->enableCrypto('tls', 'client'); } /** * testEnableCryptoExceptionDisableTwice * * @expectedException SocketException * @return void */ public function testEnableCryptoExceptionDisableTwice() { // testing on tls server $this->_connectSocketToSslTls(); $this->Socket->enableCrypto('tls', 'client', false); } /** * testEnableCryptoEnableStatus * * @return void */ public function testEnableCryptoEnableStatus() { // testing on tls server $this->_connectSocketToSslTls(); $this->assertFalse($this->Socket->encrypted); $this->Socket->enableCrypto('tls', 'client', true); $this->assertTrue($this->Socket->encrypted); } /** * test getting the context for a socket. * * @return void */ public function testGetContext() { $this->skipIf(!extension_loaded('openssl'), 'OpenSSL is not enabled cannot test SSL.'); $config = array( 'host' => 'smtp.gmail.com', 'port' => 465, 'timeout' => 5, 'context' => array( 'ssl' => array('capture_peer' => true) ) ); $this->Socket = new CakeSocket($config); $this->Socket->connect(); $result = $this->Socket->context(); $this->assertSame($config['context']['ssl']['capture_peer'], $result['ssl']['capture_peer']); } /** * test configuring the context from the flat keys. * * @return void */ public function testConfigContext() { $this->skipIf(!extension_loaded('openssl'), 'OpenSSL is not enabled cannot test SSL.'); $config = array( 'host' => 'smtp.gmail.com', 'port' => 465, 'timeout' => 5, 'ssl_verify_peer' => true, 'ssl_allow_self_signed' => false, 'ssl_verify_depth' => 5, 'ssl_verify_host' => true, ); $this->Socket = new CakeSocket($config); $this->Socket->connect(); $result = $this->Socket->context(); $this->assertTrue($result['ssl']['verify_peer']); $this->assertFalse($result['ssl']['allow_self_signed']); $this->assertEquals(5, $result['ssl']['verify_depth']); $this->assertEquals('smtp.gmail.com', $result['ssl']['CN_match']); $this->assertArrayNotHasKey('ssl_verify_peer', $this->Socket->config); $this->assertArrayNotHasKey('ssl_allow_self_signed', $this->Socket->config); $this->assertArrayNotHasKey('ssl_verify_host', $this->Socket->config); $this->assertArrayNotHasKey('ssl_verify_depth', $this->Socket->config); } } cakephp-2.8.0/lib/Cake/Test/Case/Network/Email/000077500000000000000000000000001265552240500210255ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Network/Email/CakeEmailTest.php000066400000000000000000002413571265552240500242250ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Network.Email * @since CakePHP(tm) v 2.0.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('CakeEmail', 'Network/Email'); App::uses('File', 'Utility'); /** * Help to test CakeEmail */ class TestCakeEmail extends CakeEmail { /** * Config class name. * * Use a the testing config class in this file. * * @var string */ protected $_configClass = 'TestEmailConfig'; /** * Config */ protected $_config = array(); /** * Wrap to protected method * * @return array */ public function formatAddress($address) { return parent::_formatAddress($address); } /** * Wrap to protected method * * @return array */ public function wrap($text, $length = CakeEmail::LINE_LENGTH_MUST) { return parent::_wrap($text, $length); } /** * Get the boundary attribute * * @return string */ public function getBoundary() { return $this->_boundary; } /** * Encode to protected method * * @return string */ public function encode($text) { return $this->_encode($text); } /** * Render to protected method * * @return array */ public function render($content) { return $this->_render($content); } } /** * EmailConfig class */ class TestEmailConfig { /** * default config * * @var array */ public $default = array( 'subject' => 'Default Subject', ); /** * test config * * @var array */ public $test = array( 'from' => array('some@example.com' => 'My website'), 'to' => array('test@example.com' => 'Testname'), 'subject' => 'Test mail subject', 'transport' => 'Debug', 'theme' => 'TestTheme', 'helpers' => array('Html', 'Form'), ); /** * test config 2 * * @var array */ public $test2 = array( 'from' => array('some@example.com' => 'My website'), 'to' => array('test@example.com' => 'Testname'), 'subject' => 'Test mail subject', 'transport' => 'Smtp', 'host' => 'cakephp.org', 'timeout' => 60 ); } /** * ExtendTransport class * test class to ensure the class has send() method */ class ExtendTransport { } /** * CakeEmailTest class * * @package Cake.Test.Case.Network.Email */ class CakeEmailTest extends CakeTestCase { /** * setUp * * @return void */ public function setUp() { parent::setUp(); $this->_configFileExists = true; $emailConfig = new File(APP . 'Config' . DS . 'email.php'); if (!$emailConfig->exists()) { $this->_configFileExists = false; $emailConfig->create(); } $this->CakeEmail = new TestCakeEmail(); App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); App::build(); if (!$this->_configFileExists) { unlink(APP . 'Config' . DS . 'email.php'); } } /** * Test if the EmailConfig::$default configuration is read when present * * @return void */ public function testDefaultConfig() { $this->assertEquals('Default Subject', $this->CakeEmail->subject()); } /** * testFrom method * * @return void */ public function testFrom() { $this->assertSame(array(), $this->CakeEmail->from()); $this->CakeEmail->from('cake@cakephp.org'); $expected = array('cake@cakephp.org' => 'cake@cakephp.org'); $this->assertSame($expected, $this->CakeEmail->from()); $this->CakeEmail->from(array('cake@cakephp.org')); $this->assertSame($expected, $this->CakeEmail->from()); $this->CakeEmail->from('cake@cakephp.org', 'CakePHP'); $expected = array('cake@cakephp.org' => 'CakePHP'); $this->assertSame($expected, $this->CakeEmail->from()); $result = $this->CakeEmail->from(array('cake@cakephp.org' => 'CakePHP')); $this->assertSame($expected, $this->CakeEmail->from()); $this->assertSame($this->CakeEmail, $result); $this->setExpectedException('SocketException'); $this->CakeEmail->from(array('cake@cakephp.org' => 'CakePHP', 'fail@cakephp.org' => 'From can only be one address')); } /** * Test that from addresses using colons work. * * @return void */ public function testFromWithColonsAndQuotes() { $address = array( 'info@example.com' => '70:20:00 " Forum' ); $this->CakeEmail->from($address); $this->assertEquals($address, $this->CakeEmail->from()); $this->CakeEmail->to('info@example.com') ->subject('Test email') ->transport('Debug'); $result = $this->CakeEmail->send(); $this->assertContains('From: "70:20:00 \" Forum" ', $result['headers']); } /** * testSender method * * @return void */ public function testSender() { $this->CakeEmail->reset(); $this->assertSame(array(), $this->CakeEmail->sender()); $this->CakeEmail->sender('cake@cakephp.org', 'Name'); $expected = array('cake@cakephp.org' => 'Name'); $this->assertSame($expected, $this->CakeEmail->sender()); $headers = $this->CakeEmail->getHeaders(array('from' => true, 'sender' => true)); $this->assertFalse($headers['From']); $this->assertSame('Name ', $headers['Sender']); $this->CakeEmail->from('cake@cakephp.org', 'CakePHP'); $headers = $this->CakeEmail->getHeaders(array('from' => true, 'sender' => true)); $this->assertSame('CakePHP ', $headers['From']); $this->assertSame('', $headers['Sender']); } /** * testTo method * * @return void */ public function testTo() { $this->assertSame(array(), $this->CakeEmail->to()); $result = $this->CakeEmail->to('cake@cakephp.org'); $expected = array('cake@cakephp.org' => 'cake@cakephp.org'); $this->assertSame($expected, $this->CakeEmail->to()); $this->assertSame($this->CakeEmail, $result); $this->CakeEmail->to('cake@cakephp.org', 'CakePHP'); $expected = array('cake@cakephp.org' => 'CakePHP'); $this->assertSame($expected, $this->CakeEmail->to()); $list = array( 'root@localhost' => 'root', 'bjรธrn@hammerรถath.com' => 'Bjorn', 'cake.php@cakephp.org' => 'Cake PHP', 'cake-php@googlegroups.com' => 'Cake Groups', 'root@cakephp.org' ); $this->CakeEmail->to($list); $expected = array( 'root@localhost' => 'root', 'bjรธrn@hammerรถath.com' => 'Bjorn', 'cake.php@cakephp.org' => 'Cake PHP', 'cake-php@googlegroups.com' => 'Cake Groups', 'root@cakephp.org' => 'root@cakephp.org' ); $this->assertSame($expected, $this->CakeEmail->to()); $this->CakeEmail->addTo('jrbasso@cakephp.org'); $this->CakeEmail->addTo('mark_story@cakephp.org', 'Mark Story'); $this->CakeEmail->addTo('foobar@รฆtdcadsl.dk'); $result = $this->CakeEmail->addTo(array('phpnut@cakephp.org' => 'PhpNut', 'jose_zap@cakephp.org')); $expected = array( 'root@localhost' => 'root', 'bjรธrn@hammerรถath.com' => 'Bjorn', 'cake.php@cakephp.org' => 'Cake PHP', 'cake-php@googlegroups.com' => 'Cake Groups', 'root@cakephp.org' => 'root@cakephp.org', 'jrbasso@cakephp.org' => 'jrbasso@cakephp.org', 'mark_story@cakephp.org' => 'Mark Story', 'foobar@รฆtdcadsl.dk' => 'foobar@รฆtdcadsl.dk', 'phpnut@cakephp.org' => 'PhpNut', 'jose_zap@cakephp.org' => 'jose_zap@cakephp.org' ); $this->assertSame($expected, $this->CakeEmail->to()); $this->assertSame($this->CakeEmail, $result); } /** * Data provider function for testBuildInvalidData * * @return array */ public static function invalidEmails() { return array( array(1.0), array(''), array('string'), array(''), array(array('ok@cakephp.org', 1.0, '', 'string')) ); } /** * testBuildInvalidData * * @dataProvider invalidEmails * @expectedException SocketException * @return void */ public function testInvalidEmail($value) { $this->CakeEmail->to($value); } /** * testBuildInvalidData * * @dataProvider invalidEmails * @expectedException SocketException * @return void */ public function testInvalidEmailAdd($value) { $this->CakeEmail->addTo($value); } /** * test emailPattern method * * @return void */ public function testEmailPattern() { $regex = '/.+@.+\..+/i'; $this->assertSame($regex, $this->CakeEmail->emailPattern($regex)->emailPattern()); } /** * Tests that it is possible to set email regex configuration to a CakeEmail object * * @return void */ public function testConfigEmailPattern() { $regex = '/.+@.+\..+/i'; $email = new CakeEmail(array('emailPattern' => $regex)); $this->assertSame($regex, $email->emailPattern()); } /** * Tests that it is possible set custom email validation * * @return void */ public function testCustomEmailValidation() { $regex = '/^[\.a-z0-9!#$%&\'*+\/=?^_`{|}~-]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]{2,6}$/i'; $this->CakeEmail->emailPattern($regex)->to('pass.@example.com'); $this->assertSame(array( 'pass.@example.com' => 'pass.@example.com', ), $this->CakeEmail->to()); $this->CakeEmail->addTo('pass..old.docomo@example.com'); $this->assertSame(array( 'pass.@example.com' => 'pass.@example.com', 'pass..old.docomo@example.com' => 'pass..old.docomo@example.com', ), $this->CakeEmail->to()); $this->CakeEmail->reset(); $emails = array( 'pass.@example.com', 'pass..old.docomo@example.com' ); $additionalEmails = array( '.extend.@example.com', '.docomo@example.com' ); $this->CakeEmail->emailPattern($regex)->to($emails); $this->assertSame(array( 'pass.@example.com' => 'pass.@example.com', 'pass..old.docomo@example.com' => 'pass..old.docomo@example.com', ), $this->CakeEmail->to()); $this->CakeEmail->addTo($additionalEmails); $this->assertSame(array( 'pass.@example.com' => 'pass.@example.com', 'pass..old.docomo@example.com' => 'pass..old.docomo@example.com', '.extend.@example.com' => '.extend.@example.com', '.docomo@example.com' => '.docomo@example.com', ), $this->CakeEmail->to()); } /** * Tests that it is possible to unset the email pattern and make use of filter_var() instead. * * @return void * * @expectedException SocketException * @expectedExceptionMessage Invalid email: "fail.@example.com" */ public function testUnsetEmailPattern() { $email = new CakeEmail(); $this->assertSame(CakeEmail::EMAIL_PATTERN, $email->emailPattern()); $email->emailPattern(null); $this->assertNull($email->emailPattern()); $email->to('pass@example.com'); $email->to('fail.@example.com'); } /** * testFormatAddress method * * @return void */ public function testFormatAddress() { $result = $this->CakeEmail->formatAddress(array('cake@cakephp.org' => 'cake@cakephp.org')); $expected = array('cake@cakephp.org'); $this->assertSame($expected, $result); $result = $this->CakeEmail->formatAddress(array('cake@cakephp.org' => 'cake@cakephp.org', 'php@cakephp.org' => 'php@cakephp.org')); $expected = array('cake@cakephp.org', 'php@cakephp.org'); $this->assertSame($expected, $result); $result = $this->CakeEmail->formatAddress(array('cake@cakephp.org' => 'CakePHP', 'php@cakephp.org' => 'Cake')); $expected = array('CakePHP ', 'Cake '); $this->assertSame($expected, $result); $result = $this->CakeEmail->formatAddress(array('me@example.com' => 'Last, First')); $expected = array('"Last, First" '); $this->assertSame($expected, $result); $result = $this->CakeEmail->formatAddress(array('me@example.com' => '"Last" First')); $expected = array('"\"Last\" First" '); $this->assertSame($expected, $result); $result = $this->CakeEmail->formatAddress(array('me@example.com' => 'Last First')); $expected = array('Last First '); $this->assertSame($expected, $result); $result = $this->CakeEmail->formatAddress(array('cake@cakephp.org' => 'ร„ร–รœTest')); $expected = array('=?UTF-8?B?w4TDlsOcVGVzdA==?= '); $this->assertSame($expected, $result); $result = $this->CakeEmail->formatAddress(array('cake@cakephp.org' => 'ๆ—ฅๆœฌ่ชžTest')); $expected = array('=?UTF-8?B?5pel5pys6KqeVGVzdA==?= '); $this->assertSame($expected, $result); } /** * testFormatAddressJapanese * * @return void */ public function testFormatAddressJapanese() { $this->skipIf(!function_exists('mb_convert_encoding')); $this->CakeEmail->headerCharset = 'ISO-2022-JP'; $result = $this->CakeEmail->formatAddress(array('cake@cakephp.org' => 'ๆ—ฅๆœฌ่ชžTest')); $expected = array('=?ISO-2022-JP?B?GyRCRnxLXDhsGyhCVGVzdA==?= '); $this->assertSame($expected, $result); $result = $this->CakeEmail->formatAddress(array('cake@cakephp.org' => 'ๅฏฟ้™็„กๅฏฟ้™็„กไบ”ๅŠซใฎๆ“ฆใ‚Šๅˆ‡ใ‚Œๆตท็ ‚ๅˆฉๆฐด้ญšใฎๆฐด่กŒๆœซ้›ฒๆฅๆœซ้ขจๆฅๆœซ้ฃŸใ†ๅฏใ‚‹ๅ‡ฆใซไฝใ‚€ๅ‡ฆใ‚„ใถใ‚‰ๅฐ่ทฏใฎ่—ชๆŸ‘ๅญใƒ‘ใ‚คใƒใƒ‘ใ‚คใƒใƒ‘ใ‚คใƒใฎใ‚ทใƒฅใƒผใƒชใƒณใ‚ฌใƒณใ‚ทใƒฅใƒผใƒชใƒณใ‚ฌใƒณใฎใ‚ฐใƒผใƒชใƒณใƒ€ใ‚คใ‚ฐใƒผใƒชใƒณใƒ€ใ‚คใฎใƒใƒณใƒใ‚ณใƒ”ใƒผใฎใƒใƒณใƒใ‚ณใƒŠใƒผใฎ้•ทไน…ๅ‘ฝใฎ้•ทๅŠฉ')); $expected = array("=?ISO-2022-JP?B?GyRCPHc4Qkw1PHc4Qkw1OF45ZSROOyQkakBaJGwzJDo9TXg/ZTV7GyhC?=\r\n" . " =?ISO-2022-JP?B?GyRCJE4/ZTlUS3YxQE1oS3ZJd01oS3Y/KSQmPzIkaz1oJEs9OyRgGyhC?=\r\n" . " =?ISO-2022-JP?B?GyRCPWgkZCRWJGk+Lk8pJE5pLjQ7O1IlUSUkJV0lUSUkJV0lUSUkGyhC?=\r\n" . " =?ISO-2022-JP?B?GyRCJV0kTiU3JWUhPCVqJXMlLCVzJTclZSE8JWolcyUsJXMkTiUwGyhC?=\r\n" . " =?ISO-2022-JP?B?GyRCITwlaiVzJUAlJCUwITwlaiVzJUAlJCROJV0lcyVdJTMlVCE8GyhC?=\r\n" . " =?ISO-2022-JP?B?GyRCJE4lXSVzJV0lMyVKITwkTkQ5NVdMPyRORDk9dRsoQg==?= "); $this->assertSame($expected, $result); } /** * testAddresses method * * @return void */ public function testAddresses() { $this->CakeEmail->reset(); $this->CakeEmail->from('cake@cakephp.org', 'CakePHP'); $this->CakeEmail->replyTo('replyto@cakephp.org', 'ReplyTo CakePHP'); $this->CakeEmail->readReceipt('readreceipt@cakephp.org', 'ReadReceipt CakePHP'); $this->CakeEmail->returnPath('returnpath@cakephp.org', 'ReturnPath CakePHP'); $this->CakeEmail->to('to@cakephp.org', 'To, CakePHP'); $this->CakeEmail->cc('cc@cakephp.org', 'Cc CakePHP'); $this->CakeEmail->bcc('bcc@cakephp.org', 'Bcc CakePHP'); $this->CakeEmail->addTo('to2@cakephp.org', 'To2 CakePHP'); $this->CakeEmail->addCc('cc2@cakephp.org', 'Cc2 CakePHP'); $this->CakeEmail->addBcc('bcc2@cakephp.org', 'Bcc2 CakePHP'); $this->assertSame($this->CakeEmail->from(), array('cake@cakephp.org' => 'CakePHP')); $this->assertSame($this->CakeEmail->replyTo(), array('replyto@cakephp.org' => 'ReplyTo CakePHP')); $this->assertSame($this->CakeEmail->readReceipt(), array('readreceipt@cakephp.org' => 'ReadReceipt CakePHP')); $this->assertSame($this->CakeEmail->returnPath(), array('returnpath@cakephp.org' => 'ReturnPath CakePHP')); $this->assertSame($this->CakeEmail->to(), array('to@cakephp.org' => 'To, CakePHP', 'to2@cakephp.org' => 'To2 CakePHP')); $this->assertSame($this->CakeEmail->cc(), array('cc@cakephp.org' => 'Cc CakePHP', 'cc2@cakephp.org' => 'Cc2 CakePHP')); $this->assertSame($this->CakeEmail->bcc(), array('bcc@cakephp.org' => 'Bcc CakePHP', 'bcc2@cakephp.org' => 'Bcc2 CakePHP')); $headers = $this->CakeEmail->getHeaders(array_fill_keys(array('from', 'replyTo', 'readReceipt', 'returnPath', 'to', 'cc', 'bcc'), true)); $this->assertSame($headers['From'], 'CakePHP '); $this->assertSame($headers['Reply-To'], 'ReplyTo CakePHP '); $this->assertSame($headers['Disposition-Notification-To'], 'ReadReceipt CakePHP '); $this->assertSame($headers['Return-Path'], 'ReturnPath CakePHP '); $this->assertSame($headers['To'], '"To, CakePHP" , To2 CakePHP '); $this->assertSame($headers['Cc'], 'Cc CakePHP , Cc2 CakePHP '); $this->assertSame($headers['Bcc'], 'Bcc CakePHP , Bcc2 CakePHP '); } /** * testMessageId method * * @return void */ public function testMessageId() { $this->CakeEmail->messageId(true); $result = $this->CakeEmail->getHeaders(); $this->assertTrue(isset($result['Message-ID'])); $this->CakeEmail->messageId(false); $result = $this->CakeEmail->getHeaders(); $this->assertFalse(isset($result['Message-ID'])); $result = $this->CakeEmail->messageId(''); $this->assertSame($this->CakeEmail, $result); $result = $this->CakeEmail->getHeaders(); $this->assertSame('', $result['Message-ID']); $result = $this->CakeEmail->messageId(); $this->assertSame('', $result); } /** * testMessageIdInvalid method * * @return void * @expectedException SocketException */ public function testMessageIdInvalid() { $this->CakeEmail->messageId('my-email@localhost'); } /** * testDomain method * * @return void */ public function testDomain() { $result = $this->CakeEmail->domain(); $expected = env('HTTP_HOST') ? env('HTTP_HOST') : php_uname('n'); $this->assertSame($expected, $result); $this->CakeEmail->domain('example.org'); $result = $this->CakeEmail->domain(); $expected = 'example.org'; $this->assertSame($expected, $result); } /** * testMessageIdWithDomain method * * @return void */ public function testMessageIdWithDomain() { $this->CakeEmail->domain('example.org'); $result = $this->CakeEmail->getHeaders(); $expected = '@example.org>'; $this->assertTextContains($expected, $result['Message-ID']); $_SERVER['HTTP_HOST'] = 'example.org'; $result = $this->CakeEmail->getHeaders(); $this->assertTextContains('example.org', $result['Message-ID']); $_SERVER['HTTP_HOST'] = 'example.org:81'; $result = $this->CakeEmail->getHeaders(); $this->assertTextNotContains(':81', $result['Message-ID']); } /** * testSubject method * * @return void */ public function testSubject() { $this->CakeEmail->subject('You have a new message.'); $this->assertSame('You have a new message.', $this->CakeEmail->subject()); $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('1', $this->CakeEmail->subject()); $this->CakeEmail->subject('ู‡ุฐู‡ ุฑุณุงู„ุฉ ุจุนู†ูˆุงู† ุทูˆูŠู„ ู…ุฑุณู„ ู„ู„ู…ุณุชู„ู…'); $expected = '=?UTF-8?B?2YfYsNmHINix2LPYp9mE2Kkg2KjYudmG2YjYp9mGINi32YjZitmEINmF2LE=?=' . "\r\n" . ' =?UTF-8?B?2LPZhCDZhNmE2YXYs9iq2YTZhQ==?='; $this->assertSame($expected, $this->CakeEmail->subject()); } /** * testSubjectJapanese * * @return void */ public function testSubjectJapanese() { $this->skipIf(!function_exists('mb_convert_encoding')); mb_internal_encoding('UTF-8'); $this->CakeEmail->headerCharset = 'ISO-2022-JP'; $this->CakeEmail->subject('ๆ—ฅๆœฌ่ชžใฎSubjectใซใ‚‚ๅฏพๅฟœใ™ใ‚‹ใ‚ˆ'); $expected = '=?ISO-2022-JP?B?GyRCRnxLXDhsJE4bKEJTdWJqZWN0GyRCJEskYkJQMX4kOSRrJGgbKEI=?='; $this->assertSame($expected, $this->CakeEmail->subject()); $this->CakeEmail->subject('้•ทใ„้•ทใ„้•ทใ„Subjectใฎๅ ดๅˆใฏfoldingใ™ใ‚‹ใฎใŒๆญฃใ—ใ„ใ‚“ใ ใ‘ใฉใ„ใฃใŸใ„ใฉใ†ใชใ‚‹ใ‚“ใ ใ‚ใ†๏ผŸ'); $expected = "=?ISO-2022-JP?B?GyRCRDkkJEQ5JCREOSQkGyhCU3ViamVjdBskQiROPmw5ZyRPGyhCZm9s?=\r\n" . " =?ISO-2022-JP?B?ZGluZxskQiQ5JGskTiQsQDUkNyQkJHMkQCQxJEkkJCRDJD8kJCRJGyhC?=\r\n" . " =?ISO-2022-JP?B?GyRCJCYkSiRrJHMkQCRtJCYhKRsoQg==?="; $this->assertSame($expected, $this->CakeEmail->subject()); } /** * testHeaders method * * @return void */ public function testHeaders() { $this->CakeEmail->messageId(false); $this->CakeEmail->setHeaders(array('X-Something' => 'nice')); $expected = array( 'X-Something' => 'nice', 'X-Mailer' => 'CakePHP Email', 'Date' => date(DATE_RFC2822), 'MIME-Version' => '1.0', 'Content-Type' => 'text/plain; charset=UTF-8', 'Content-Transfer-Encoding' => '8bit' ); $this->assertSame($expected, $this->CakeEmail->getHeaders()); $this->CakeEmail->addHeaders(array('X-Something' => 'very nice', 'X-Other' => 'cool')); $expected = array( 'X-Something' => 'very nice', 'X-Other' => 'cool', 'X-Mailer' => 'CakePHP Email', 'Date' => date(DATE_RFC2822), 'MIME-Version' => '1.0', 'Content-Type' => 'text/plain; charset=UTF-8', 'Content-Transfer-Encoding' => '8bit' ); $this->assertSame($expected, $this->CakeEmail->getHeaders()); $this->CakeEmail->from('cake@cakephp.org'); $this->assertSame($expected, $this->CakeEmail->getHeaders()); $expected = array( 'From' => 'cake@cakephp.org', 'X-Something' => 'very nice', 'X-Other' => 'cool', 'X-Mailer' => 'CakePHP Email', 'Date' => date(DATE_RFC2822), 'MIME-Version' => '1.0', 'Content-Type' => 'text/plain; charset=UTF-8', 'Content-Transfer-Encoding' => '8bit' ); $this->assertSame($expected, $this->CakeEmail->getHeaders(array('from' => true))); $this->CakeEmail->from('cake@cakephp.org', 'CakePHP'); $expected['From'] = 'CakePHP '; $this->assertSame($expected, $this->CakeEmail->getHeaders(array('from' => true))); $this->CakeEmail->to(array('cake@cakephp.org', 'php@cakephp.org' => 'CakePHP')); $expected = array( 'From' => 'CakePHP ', 'To' => 'cake@cakephp.org, CakePHP ', 'X-Something' => 'very nice', 'X-Other' => 'cool', 'X-Mailer' => 'CakePHP Email', 'Date' => date(DATE_RFC2822), 'MIME-Version' => '1.0', 'Content-Type' => 'text/plain; charset=UTF-8', 'Content-Transfer-Encoding' => '8bit' ); $this->assertSame($expected, $this->CakeEmail->getHeaders(array('from' => true, 'to' => true))); $this->CakeEmail->charset = 'ISO-2022-JP'; $expected = array( 'From' => 'CakePHP ', 'To' => 'cake@cakephp.org, CakePHP ', 'X-Something' => 'very nice', 'X-Other' => 'cool', 'X-Mailer' => 'CakePHP Email', 'Date' => date(DATE_RFC2822), 'MIME-Version' => '1.0', 'Content-Type' => 'text/plain; charset=ISO-2022-JP', 'Content-Transfer-Encoding' => '7bit' ); $this->assertSame($expected, $this->CakeEmail->getHeaders(array('from' => true, 'to' => true))); $result = $this->CakeEmail->setHeaders(array()); $this->assertInstanceOf('CakeEmail', $result); } /** * Data provider function for testInvalidHeaders * * @return array */ public static function invalidHeaders() { return array( array(10), array(''), array('string'), array(false), array(null) ); } /** * testInvalidHeaders * * @dataProvider invalidHeaders * @expectedException SocketException * @return void */ public function testInvalidHeaders($value) { $this->CakeEmail->setHeaders($value); } /** * testInvalidAddHeaders * * @dataProvider invalidHeaders * @expectedException SocketException * @return void */ public function testInvalidAddHeaders($value) { $this->CakeEmail->addHeaders($value); } /** * testTemplate method * * @return void */ public function testTemplate() { $this->CakeEmail->template('template', 'layout'); $expected = array('template' => 'template', 'layout' => 'layout'); $this->assertSame($expected, $this->CakeEmail->template()); $this->CakeEmail->template('new_template'); $expected = array('template' => 'new_template', 'layout' => 'layout'); $this->assertSame($expected, $this->CakeEmail->template()); $this->CakeEmail->template('template', null); $expected = array('template' => 'template', 'layout' => null); $this->assertSame($expected, $this->CakeEmail->template()); $this->CakeEmail->template(null, null); $expected = array('template' => null, 'layout' => null); $this->assertSame($expected, $this->CakeEmail->template()); } /** * testTheme method * * @return void */ public function testTheme() { $this->assertNull($this->CakeEmail->theme()); $this->CakeEmail->theme('default'); $expected = 'default'; $this->assertSame($expected, $this->CakeEmail->theme()); } /** * testViewVars method * * @return void */ public function testViewVars() { $this->assertSame(array(), $this->CakeEmail->viewVars()); $this->CakeEmail->viewVars(array('value' => 12345)); $this->assertSame(array('value' => 12345), $this->CakeEmail->viewVars()); $this->CakeEmail->viewVars(array('name' => 'CakePHP')); $this->assertSame(array('value' => 12345, 'name' => 'CakePHP'), $this->CakeEmail->viewVars()); $this->CakeEmail->viewVars(array('value' => 4567)); $this->assertSame(array('value' => 4567, 'name' => 'CakePHP'), $this->CakeEmail->viewVars()); } /** * testAttachments method * * @return void */ public function testAttachments() { $this->CakeEmail->attachments(CAKE . 'basics.php'); $expected = array( 'basics.php' => array( 'file' => CAKE . 'basics.php', 'mimetype' => 'application/octet-stream' ) ); $this->assertSame($expected, $this->CakeEmail->attachments()); $this->CakeEmail->attachments(array()); $this->assertSame(array(), $this->CakeEmail->attachments()); $this->CakeEmail->attachments(array( array('file' => CAKE . 'basics.php', 'mimetype' => 'text/plain') )); $this->CakeEmail->addAttachments(CAKE . 'bootstrap.php'); $this->CakeEmail->addAttachments(array(CAKE . 'bootstrap.php')); $this->CakeEmail->addAttachments(array('other.txt' => CAKE . 'bootstrap.php', 'license' => CAKE . 'LICENSE.txt')); $expected = array( 'basics.php' => array('file' => CAKE . 'basics.php', 'mimetype' => 'text/plain'), 'bootstrap.php' => array('file' => CAKE . 'bootstrap.php', 'mimetype' => 'application/octet-stream'), 'other.txt' => array('file' => CAKE . 'bootstrap.php', 'mimetype' => 'application/octet-stream'), 'license' => array('file' => CAKE . 'LICENSE.txt', 'mimetype' => 'application/octet-stream') ); $this->assertSame($expected, $this->CakeEmail->attachments()); $this->setExpectedException('SocketException'); $this->CakeEmail->attachments(array(array('nofile' => CAKE . 'basics.php', 'mimetype' => 'text/plain'))); } /** * testTransport method * * @return void */ public function testTransport() { $result = $this->CakeEmail->transport('Debug'); $this->assertSame($this->CakeEmail, $result); $this->assertSame('Debug', $this->CakeEmail->transport()); $result = $this->CakeEmail->transportClass(); $this->assertInstanceOf('DebugTransport', $result); $this->setExpectedException('SocketException'); $this->CakeEmail->transport('Invalid'); $this->CakeEmail->transportClass(); } /** * testExtendTransport method * * @return void */ public function testExtendTransport() { $this->setExpectedException('SocketException'); $this->CakeEmail->transport('Extend'); $this->CakeEmail->transportClass(); } /** * testConfig method * * @return void */ public function testConfig() { $transportClass = $this->CakeEmail->transport('debug')->transportClass(); $config = array('test' => 'ok', 'test2' => true); $this->CakeEmail->config($config); $this->assertSame($config, $transportClass->config()); $expected = $config + array('subject' => 'Default Subject'); $this->assertSame($expected, $this->CakeEmail->config()); $this->CakeEmail->config(array()); $this->assertSame($config, $transportClass->config()); $config = array('test' => 'test@example.com', 'subject' => 'my test subject'); $this->CakeEmail->config($config); $expected = array('test' => 'test@example.com', 'subject' => 'my test subject', 'test2' => true); $this->assertSame($expected, $this->CakeEmail->config()); $this->assertSame(array('test' => 'test@example.com', 'test2' => true), $transportClass->config()); } /** * testConfigString method * * @return void */ public function testConfigString() { $configs = new TestEmailConfig(); $this->CakeEmail->config('test'); $result = $this->CakeEmail->to(); $this->assertEquals($configs->test['to'], $result); $result = $this->CakeEmail->from(); $this->assertEquals($configs->test['from'], $result); $result = $this->CakeEmail->subject(); $this->assertEquals($configs->test['subject'], $result); $result = $this->CakeEmail->theme(); $this->assertEquals($configs->test['theme'], $result); $result = $this->CakeEmail->transport(); $this->assertEquals($configs->test['transport'], $result); $result = $this->CakeEmail->transportClass(); $this->assertInstanceOf('DebugTransport', $result); $result = $this->CakeEmail->helpers(); $this->assertEquals($configs->test['helpers'], $result); } /** * Test updating config doesn't reset transport's config. * * @return void */ public function testConfigMerge() { $this->CakeEmail->config('test2'); $expected = array( 'host' => 'cakephp.org', 'port' => 25, 'timeout' => 60, 'username' => null, 'password' => null, 'client' => null, 'tls' => false, 'ssl_allow_self_signed' => false ); $this->assertEquals($expected, $this->CakeEmail->transportClass()->config()); $this->CakeEmail->config(array('log' => true)); $this->CakeEmail->transportClass()->config(); $expected += array('log' => true); $this->assertEquals($expected, $this->CakeEmail->transportClass()->config()); $this->CakeEmail->config(array('timeout' => 45)); $result = $this->CakeEmail->transportClass()->config(); $this->assertEquals(45, $result['timeout']); } /** * Calling send() with no parameters should not overwrite the view variables. * * @return void */ public function testSendWithNoContentDoesNotOverwriteViewVar() { $this->CakeEmail->reset(); $this->CakeEmail->transport('Debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to('you@cakephp.org'); $this->CakeEmail->subject('My title'); $this->CakeEmail->emailFormat('text'); $this->CakeEmail->template('default'); $this->CakeEmail->viewVars(array( 'content' => 'A message to you', )); $result = $this->CakeEmail->send(); $this->assertContains('A message to you', $result['message']); } /** * testSendWithContent method * * @return void */ public function testSendWithContent() { $this->CakeEmail->reset(); $this->CakeEmail->transport('Debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $result = $this->CakeEmail->send("Here is my body, with multi lines.\nThis is the second line.\r\n\r\nAnd the last."); $expected = array('headers', 'message'); $this->assertEquals($expected, array_keys($result)); $expected = "Here is my body, with multi lines.\r\nThis is the second line.\r\n\r\nAnd the last.\r\n\r\n"; $this->assertEquals($expected, $result['message']); $this->assertTrue((bool)strpos($result['headers'], 'Date: ')); $this->assertTrue((bool)strpos($result['headers'], 'Message-ID: ')); $this->assertTrue((bool)strpos($result['headers'], 'To: ')); $result = $this->CakeEmail->send("Other body"); $expected = "Other body\r\n\r\n"; $this->assertSame($expected, $result['message']); $this->assertTrue((bool)strpos($result['headers'], 'Message-ID: ')); $this->assertTrue((bool)strpos($result['headers'], 'To: ')); $this->CakeEmail->reset(); $this->CakeEmail->transport('Debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $result = $this->CakeEmail->send(array('Sending content', 'As array')); $expected = "Sending content\r\nAs array\r\n\r\n\r\n"; $this->assertSame($expected, $result['message']); } /** * testSendWithoutFrom method * * @return void */ public function testSendWithoutFrom() { $this->CakeEmail->transport('Debug'); $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $this->setExpectedException('SocketException'); $this->CakeEmail->send("Forgot to set From"); } /** * testSendWithoutTo method * * @return void */ public function testSendWithoutTo() { $this->CakeEmail->transport('Debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $this->setExpectedException('SocketException'); $this->CakeEmail->send("Forgot to set To"); } /** * Test send() with no template. * * @return void */ public function testSendNoTemplateWithAttachments() { $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->subject('My title'); $this->CakeEmail->emailFormat('text'); $this->CakeEmail->attachments(array(CAKE . 'basics.php')); $result = $this->CakeEmail->send('Hello'); $boundary = $this->CakeEmail->getBoundary(); $this->assertContains('Content-Type: multipart/mixed; boundary="' . $boundary . '"', $result['headers']); $expected = "--$boundary\r\n" . "Content-Type: text/plain; charset=UTF-8\r\n" . "Content-Transfer-Encoding: 8bit\r\n" . "\r\n" . "Hello" . "\r\n" . "\r\n" . "\r\n" . "--$boundary\r\n" . "Content-Type: application/octet-stream\r\n" . "Content-Transfer-Encoding: base64\r\n" . "Content-Disposition: attachment; filename=\"basics.php\"\r\n\r\n"; $this->assertContains($expected, $result['message']); } /** * Test send() with no template and data string attachment * * @return void */ public function testSendNoTemplateWithDataStringAttachment() { $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->subject('My title'); $this->CakeEmail->emailFormat('text'); $data = file_get_contents(CAKE . 'Console/Templates/skel/webroot/img/cake.icon.png'); $this->CakeEmail->attachments(array('cake.icon.png' => array( 'data' => $data, 'mimetype' => 'image/png' ))); $result = $this->CakeEmail->send('Hello'); $boundary = $this->CakeEmail->getBoundary(); $this->assertContains('Content-Type: multipart/mixed; boundary="' . $boundary . '"', $result['headers']); $expected = "--$boundary\r\n" . "Content-Type: text/plain; charset=UTF-8\r\n" . "Content-Transfer-Encoding: 8bit\r\n" . "\r\n" . "Hello" . "\r\n" . "\r\n" . "\r\n" . "--$boundary\r\n" . "Content-Type: image/png\r\n" . "Content-Transfer-Encoding: base64\r\n" . "Content-Disposition: attachment; filename=\"cake.icon.png\"\r\n\r\n"; $expected .= chunk_split(base64_encode($data), 76, "\r\n"); $this->assertContains($expected, $result['message']); } /** * Test send() with no template as both * * @return void */ public function testSendNoTemplateWithAttachmentsAsBoth() { $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->subject('My title'); $this->CakeEmail->emailFormat('both'); $this->CakeEmail->attachments(array(CAKE . 'VERSION.txt')); $result = $this->CakeEmail->send('Hello'); $boundary = $this->CakeEmail->getBoundary(); $this->assertContains('Content-Type: multipart/mixed; boundary="' . $boundary . '"', $result['headers']); $expected = "--$boundary\r\n" . "Content-Type: multipart/alternative; boundary=\"alt-$boundary\"\r\n" . "\r\n" . "--alt-$boundary\r\n" . "Content-Type: text/plain; charset=UTF-8\r\n" . "Content-Transfer-Encoding: 8bit\r\n" . "\r\n" . "Hello" . "\r\n" . "\r\n" . "\r\n" . "--alt-$boundary\r\n" . "Content-Type: text/html; charset=UTF-8\r\n" . "Content-Transfer-Encoding: 8bit\r\n" . "\r\n" . "Hello" . "\r\n" . "\r\n" . "\r\n" . "--alt-{$boundary}--\r\n" . "\r\n" . "--$boundary\r\n" . "Content-Type: application/octet-stream\r\n" . "Content-Transfer-Encoding: base64\r\n" . "Content-Disposition: attachment; filename=\"VERSION.txt\"\r\n\r\n"; $this->assertContains($expected, $result['message']); } /** * Test setting inline attachments and messages. * * @return void */ public function testSendWithInlineAttachments() { $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->subject('My title'); $this->CakeEmail->emailFormat('both'); $this->CakeEmail->attachments(array( 'cake.png' => array( 'file' => CAKE . 'VERSION.txt', 'contentId' => 'abc123' ) )); $result = $this->CakeEmail->send('Hello'); $boundary = $this->CakeEmail->getBoundary(); $this->assertContains('Content-Type: multipart/mixed; boundary="' . $boundary . '"', $result['headers']); $expected = "--$boundary\r\n" . "Content-Type: multipart/related; boundary=\"rel-$boundary\"\r\n" . "\r\n" . "--rel-$boundary\r\n" . "Content-Type: multipart/alternative; boundary=\"alt-$boundary\"\r\n" . "\r\n" . "--alt-$boundary\r\n" . "Content-Type: text/plain; charset=UTF-8\r\n" . "Content-Transfer-Encoding: 8bit\r\n" . "\r\n" . "Hello" . "\r\n" . "\r\n" . "\r\n" . "--alt-$boundary\r\n" . "Content-Type: text/html; charset=UTF-8\r\n" . "Content-Transfer-Encoding: 8bit\r\n" . "\r\n" . "Hello" . "\r\n" . "\r\n" . "\r\n" . "--alt-{$boundary}--\r\n" . "\r\n" . "--rel-$boundary\r\n" . "Content-Type: application/octet-stream\r\n" . "Content-Transfer-Encoding: base64\r\n" . "Content-ID: \r\n" . "Content-Disposition: inline; filename=\"cake.png\"\r\n\r\n"; $this->assertContains($expected, $result['message']); $this->assertContains('--rel-' . $boundary . '--', $result['message']); $this->assertContains('--' . $boundary . '--', $result['message']); } /** * Test setting inline attachments and HTML only messages. * * @return void */ public function testSendWithInlineAttachmentsHtmlOnly() { $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->subject('My title'); $this->CakeEmail->emailFormat('html'); $this->CakeEmail->attachments(array( 'cake.png' => array( 'file' => CAKE . 'VERSION.txt', 'contentId' => 'abc123' ) )); $result = $this->CakeEmail->send('Hello'); $boundary = $this->CakeEmail->getBoundary(); $this->assertContains('Content-Type: multipart/mixed; boundary="' . $boundary . '"', $result['headers']); $expected = "--$boundary\r\n" . "Content-Type: multipart/related; boundary=\"rel-$boundary\"\r\n" . "\r\n" . "--rel-$boundary\r\n" . "Content-Type: text/html; charset=UTF-8\r\n" . "Content-Transfer-Encoding: 8bit\r\n" . "\r\n" . "Hello" . "\r\n" . "\r\n" . "\r\n" . "--rel-$boundary\r\n" . "Content-Type: application/octet-stream\r\n" . "Content-Transfer-Encoding: base64\r\n" . "Content-ID: \r\n" . "Content-Disposition: inline; filename=\"cake.png\"\r\n\r\n"; $this->assertContains($expected, $result['message']); $this->assertContains('--rel-' . $boundary . '--', $result['message']); $this->assertContains('--' . $boundary . '--', $result['message']); } /** * Test disabling content-disposition. * * @return void */ public function testSendWithNoContentDispositionAttachments() { $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->subject('My title'); $this->CakeEmail->emailFormat('text'); $this->CakeEmail->attachments(array( 'cake.png' => array( 'file' => CAKE . 'VERSION.txt', 'contentDisposition' => false ) )); $result = $this->CakeEmail->send('Hello'); $boundary = $this->CakeEmail->getBoundary(); $this->assertContains('Content-Type: multipart/mixed; boundary="' . $boundary . '"', $result['headers']); $expected = "--$boundary\r\n" . "Content-Type: text/plain; charset=UTF-8\r\n" . "Content-Transfer-Encoding: 8bit\r\n" . "\r\n" . "Hello" . "\r\n" . "\r\n" . "\r\n" . "--{$boundary}\r\n" . "Content-Type: application/octet-stream\r\n" . "Content-Transfer-Encoding: base64\r\n" . "\r\n"; $this->assertContains($expected, $result['message']); $this->assertContains('--' . $boundary . '--', $result['message']); } /** * testSendWithLog method * * @return void */ public function testSendWithLog() { CakeLog::config('email', array( 'engine' => 'File', 'path' => TMP )); CakeLog::drop('default'); $this->CakeEmail->transport('Debug'); $this->CakeEmail->to('me@cakephp.org'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('log' => 'cake_test_emails')); $result = $this->CakeEmail->send("Logging This"); App::uses('File', 'Utility'); $File = new File(TMP . 'cake_test_emails.log'); $log = $File->read(); $this->assertTrue(strpos($log, $result['headers']) !== false); $this->assertTrue(strpos($log, $result['message']) !== false); $File->delete(); CakeLog::drop('email'); } /** * testSendWithLogAndScope method * * @return void */ public function testSendWithLogAndScope() { CakeLog::config('email', array( 'engine' => 'File', 'path' => TMP, 'types' => array('cake_test_emails'), 'scopes' => array('email') )); CakeLog::drop('default'); $this->CakeEmail->transport('Debug'); $this->CakeEmail->to('me@cakephp.org'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('log' => array('level' => 'cake_test_emails', 'scope' => 'email'))); $result = $this->CakeEmail->send("Logging This"); App::uses('File', 'Utility'); $File = new File(TMP . 'cake_test_emails.log'); $log = $File->read(); $this->assertTrue(strpos($log, $result['headers']) !== false); $this->assertTrue(strpos($log, $result['message']) !== false); $File->delete(); CakeLog::drop('email'); } /** * testSendRender method * * @return void */ public function testSendRender() { $this->CakeEmail->reset(); $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $this->CakeEmail->template('default', 'default'); $result = $this->CakeEmail->send(); $this->assertContains('This email was sent using the CakePHP Framework', $result['message']); $this->assertContains('Message-ID: ', $result['headers']); $this->assertContains('To: ', $result['headers']); } /** * test sending and rendering with no layout * * @return void */ public function testSendRenderNoLayout() { $this->CakeEmail->reset(); $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $this->CakeEmail->template('default', null); $result = $this->CakeEmail->send('message body.'); $this->assertContains('message body.', $result['message']); $this->assertNotContains('This email was sent using the CakePHP Framework', $result['message']); } /** * testSendRender both method * * @return void */ public function testSendRenderBoth() { $this->CakeEmail->reset(); $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $this->CakeEmail->template('default', 'default'); $this->CakeEmail->emailFormat('both'); $result = $this->CakeEmail->send(); $this->assertContains('Message-ID: ', $result['headers']); $this->assertContains('To: ', $result['headers']); $boundary = $this->CakeEmail->getBoundary(); $this->assertContains('Content-Type: multipart/alternative; boundary="' . $boundary . '"', $result['headers']); $expected = "--$boundary\r\n" . "Content-Type: text/plain; charset=UTF-8\r\n" . "Content-Transfer-Encoding: 8bit\r\n" . "\r\n" . "\r\n" . "\r\n" . "This email was sent using the CakePHP Framework, http://cakephp.org." . "\r\n" . "\r\n" . "--$boundary\r\n" . "Content-Type: text/html; charset=UTF-8\r\n" . "Content-Transfer-Encoding: 8bit\r\n" . "\r\n" . "assertStringStartsWith($expected, $result['message']); $expected = "\r\n" . "\r\n" . "\r\n" . "--$boundary--\r\n"; $this->assertStringEndsWith($expected, $result['message']); } /** * testSendRender method for ISO-2022-JP * * @return void */ public function testSendRenderJapanese() { $this->skipIf(!function_exists('mb_convert_encoding')); $this->CakeEmail->reset(); $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $this->CakeEmail->template('default', 'japanese'); $this->CakeEmail->charset = 'ISO-2022-JP'; $result = $this->CakeEmail->send(); $expected = mb_convert_encoding('CakePHP Framework ใ‚’ไฝฟใฃใฆ้€ไฟกใ—ใŸใƒกใƒผใƒซใงใ™ใ€‚ http://cakephp.org.', 'ISO-2022-JP'); $this->assertContains($expected, $result['message']); $this->assertContains('Message-ID: ', $result['headers']); $this->assertContains('To: ', $result['headers']); } /** * testSendRenderThemed method * * @return void */ public function testSendRenderThemed() { $this->CakeEmail->reset(); $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $this->CakeEmail->theme('TestTheme'); $this->CakeEmail->template('themed', 'default'); $result = $this->CakeEmail->send(); $this->assertContains('In TestTheme', $result['message']); $this->assertContains('Message-ID: ', $result['headers']); $this->assertContains('To: ', $result['headers']); $this->assertContains('/theme/TestTheme/img/test.jpg', $result['message']); } /** * testSendRenderWithHTML method and assert line length is kept below the required limit * * @return void */ public function testSendRenderWithHTML() { $this->CakeEmail->reset(); $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $this->CakeEmail->emailFormat('html'); $this->CakeEmail->template('html', 'default'); $result = $this->CakeEmail->send(); $this->assertTextContains('

HTML Ipsum Presents

', $result['message']); $this->assertLineLengths($result['message']); } /** * testSendRenderWithVars method * * @return void */ public function testSendRenderWithVars() { $this->CakeEmail->reset(); $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $this->CakeEmail->template('custom', 'default'); $this->CakeEmail->viewVars(array('value' => 12345)); $result = $this->CakeEmail->send(); $this->assertContains('Here is your value: 12345', $result['message']); } /** * testSendRenderWithVars method for ISO-2022-JP * * @return void */ public function testSendRenderWithVarsJapanese() { $this->skipIf(!function_exists('mb_convert_encoding')); $this->CakeEmail->reset(); $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $this->CakeEmail->template('japanese', 'default'); $this->CakeEmail->viewVars(array('value' => 'ๆ—ฅๆœฌ่ชžใฎๅทฎใ—่พผใฟ123')); $this->CakeEmail->charset = 'ISO-2022-JP'; $result = $this->CakeEmail->send(); $expected = mb_convert_encoding('ใ“ใ“ใซใ‚ใชใŸใฎ่จญๅฎšใ—ใŸๅ€คใŒๅ…ฅใ‚Šใพใ™: ๆ—ฅๆœฌ่ชžใฎๅทฎใ—่พผใฟ123', 'ISO-2022-JP'); $this->assertTrue((bool)strpos($result['message'], $expected)); } /** * testSendRenderWithHelpers method * * @return void */ public function testSendRenderWithHelpers() { $this->CakeEmail->reset(); $this->CakeEmail->transport('debug'); $timestamp = time(); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $this->CakeEmail->template('custom_helper', 'default'); $this->CakeEmail->viewVars(array('time' => $timestamp)); $result = $this->CakeEmail->helpers(array('Time')); $this->assertInstanceOf('CakeEmail', $result); $result = $this->CakeEmail->send(); $this->assertTrue((bool)strpos($result['message'], 'Right now: ' . date('Y-m-d\TH:i:s\Z', $timestamp))); $result = $this->CakeEmail->helpers(); $this->assertEquals(array('Time'), $result); } /** * testSendRenderWithImage method * * @return void */ public function testSendRenderWithImage() { $this->CakeEmail->reset(); $this->CakeEmail->transport('Debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $this->CakeEmail->template('image'); $this->CakeEmail->emailFormat('html'); $server = env('SERVER_NAME') ? env('SERVER_NAME') : 'localhost'; if (env('SERVER_PORT') && env('SERVER_PORT') != 80) { $server .= ':' . env('SERVER_PORT'); } $expected = 'cool image'; $result = $this->CakeEmail->send(); $this->assertContains($expected, $result['message']); } /** * testSendRenderPlugin method * * @return void */ public function testSendRenderPlugin() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); $this->CakeEmail->reset(); $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $result = $this->CakeEmail->template('TestPlugin.test_plugin_tpl', 'default')->send(); $this->assertContains('Into TestPlugin.', $result['message']); $this->assertContains('This email was sent using the CakePHP Framework', $result['message']); $result = $this->CakeEmail->template('TestPlugin.test_plugin_tpl', 'TestPlugin.plug_default')->send(); $this->assertContains('Into TestPlugin.', $result['message']); $this->assertContains('This email was sent using the TestPlugin.', $result['message']); $result = $this->CakeEmail->template('TestPlugin.test_plugin_tpl', 'plug_default')->send(); $this->assertContains('Into TestPlugin.', $result['message']); $this->assertContains('This email was sent using the TestPlugin.', $result['message']); $this->CakeEmail->template( 'TestPlugin.test_plugin_tpl', 'TestPluginTwo.default' ); $result = $this->CakeEmail->send(); $this->assertContains('Into TestPlugin.', $result['message']); $this->assertContains('This email was sent using TestPluginTwo.', $result['message']); // test plugin template overridden by theme $this->CakeEmail->theme('TestTheme'); $result = $this->CakeEmail->send(); $this->assertContains('Into TestPlugin. (themed)', $result['message']); $this->CakeEmail->viewVars(array('value' => 12345)); $result = $this->CakeEmail->template('custom', 'TestPlugin.plug_default')->send(); $this->assertContains('Here is your value: 12345', $result['message']); $this->assertContains('This email was sent using the TestPlugin.', $result['message']); $this->setExpectedException('MissingViewException'); $this->CakeEmail->template('test_plugin_tpl', 'plug_default')->send(); } /** * testSendMultipleMIME method * * @return void */ public function testSendMultipleMIME() { $this->CakeEmail->reset(); $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->template('custom', 'default'); $this->CakeEmail->config(array()); $this->CakeEmail->viewVars(array('value' => 12345)); $this->CakeEmail->emailFormat('both'); $this->CakeEmail->send(); $message = $this->CakeEmail->message(); $boundary = $this->CakeEmail->getBoundary(); $this->assertFalse(empty($boundary)); $this->assertContains('--' . $boundary, $message); $this->assertContains('--' . $boundary . '--', $message); $this->CakeEmail->attachments(array('fake.php' => __FILE__)); $this->CakeEmail->send(); $message = $this->CakeEmail->message(); $boundary = $this->CakeEmail->getBoundary(); $this->assertFalse(empty($boundary)); $this->assertContains('--' . $boundary, $message); $this->assertContains('--' . $boundary . '--', $message); $this->assertContains('--alt-' . $boundary, $message); $this->assertContains('--alt-' . $boundary . '--', $message); } /** * testSendAttachment method * * @return void */ public function testSendAttachment() { $this->CakeEmail->reset(); $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array()); $this->CakeEmail->attachments(array(CAKE . 'basics.php')); $result = $this->CakeEmail->send('body'); $this->assertContains("Content-Type: application/octet-stream\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\"basics.php\"", $result['message']); $this->CakeEmail->attachments(array('my.file.txt' => CAKE . 'basics.php')); $result = $this->CakeEmail->send('body'); $this->assertContains("Content-Type: application/octet-stream\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\"my.file.txt\"", $result['message']); $this->CakeEmail->attachments(array('file.txt' => array('file' => CAKE . 'basics.php', 'mimetype' => 'text/plain'))); $result = $this->CakeEmail->send('body'); $this->assertContains("Content-Type: text/plain\r\nContent-Transfer-Encoding: base64\r\nContent-Disposition: attachment; filename=\"file.txt\"", $result['message']); $this->CakeEmail->attachments(array('file2.txt' => array('file' => CAKE . 'basics.php', 'mimetype' => 'text/plain', 'contentId' => 'a1b1c1'))); $result = $this->CakeEmail->send('body'); $this->assertContains("Content-Type: text/plain\r\nContent-Transfer-Encoding: base64\r\nContent-ID: \r\nContent-Disposition: inline; filename=\"file2.txt\"", $result['message']); } /** * testDeliver method * * @return void */ public function testDeliver() { $instance = CakeEmail::deliver('all@cakephp.org', 'About', 'Everything ok', array('from' => 'root@cakephp.org'), false); $this->assertInstanceOf('CakeEmail', $instance); $this->assertSame($instance->to(), array('all@cakephp.org' => 'all@cakephp.org')); $this->assertSame($instance->subject(), 'About'); $this->assertSame($instance->from(), array('root@cakephp.org' => 'root@cakephp.org')); $config = array( 'from' => 'cake@cakephp.org', 'to' => 'debug@cakephp.org', 'subject' => 'Update ok', 'template' => 'custom', 'layout' => 'custom_layout', 'viewVars' => array('value' => 123), 'cc' => array('cake@cakephp.org' => 'Myself') ); $instance = CakeEmail::deliver(null, null, array('name' => 'CakePHP'), $config, false); $this->assertSame($instance->from(), array('cake@cakephp.org' => 'cake@cakephp.org')); $this->assertSame($instance->to(), array('debug@cakephp.org' => 'debug@cakephp.org')); $this->assertSame($instance->subject(), 'Update ok'); $this->assertSame($instance->template(), array('template' => 'custom', 'layout' => 'custom_layout')); $this->assertSame($instance->viewVars(), array('value' => 123, 'name' => 'CakePHP')); $this->assertSame($instance->cc(), array('cake@cakephp.org' => 'Myself')); $configs = array('from' => 'root@cakephp.org', 'message' => 'Message from configs', 'transport' => 'Debug'); $instance = CakeEmail::deliver('all@cakephp.org', 'About', null, $configs, true); $message = $instance->message(); $this->assertEquals($configs['message'], $message[0]); } /** * testMessage method * * @return void */ public function testMessage() { $this->CakeEmail->reset(); $this->CakeEmail->transport('debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to(array('you@cakephp.org' => 'You')); $this->CakeEmail->subject('My title'); $this->CakeEmail->config(array('empty')); $this->CakeEmail->template('default', 'default'); $this->CakeEmail->emailFormat('both'); $this->CakeEmail->send(); $expected = '

This email was sent using the CakePHP Framework

'; $this->assertContains($expected, $this->CakeEmail->message(CakeEmail::MESSAGE_HTML)); $expected = 'This email was sent using the CakePHP Framework, http://cakephp.org.'; $this->assertContains($expected, $this->CakeEmail->message(CakeEmail::MESSAGE_TEXT)); $message = $this->CakeEmail->message(); $this->assertContains('Content-Type: text/plain; charset=UTF-8', $message); $this->assertContains('Content-Type: text/html; charset=UTF-8', $message); // UTF-8 is 8bit $this->assertTrue($this->_checkContentTransferEncoding($message, '8bit')); $this->CakeEmail->charset = 'ISO-2022-JP'; $this->CakeEmail->send(); $message = $this->CakeEmail->message(); $this->assertContains('Content-Type: text/plain; charset=ISO-2022-JP', $message); $this->assertContains('Content-Type: text/html; charset=ISO-2022-JP', $message); // ISO-2022-JP is 7bit $this->assertTrue($this->_checkContentTransferEncoding($message, '7bit')); } /** * testReset method * * @return void */ public function testReset() { $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->theme('TestTheme'); $this->CakeEmail->emailPattern('/.+@.+\..+/i'); $this->assertSame(array('cake@cakephp.org' => 'cake@cakephp.org'), $this->CakeEmail->to()); $this->CakeEmail->reset(); $this->assertSame(array(), $this->CakeEmail->to()); $this->assertNull($this->CakeEmail->theme()); $this->assertSame(CakeEmail::EMAIL_PATTERN, $this->CakeEmail->emailPattern()); } /** * testReset with charset * * @return void */ public function testResetWithCharset() { $this->CakeEmail->charset = 'ISO-2022-JP'; $this->CakeEmail->reset(); $this->assertSame('utf-8', $this->CakeEmail->charset, $this->CakeEmail->charset); $this->assertNull($this->CakeEmail->headerCharset, $this->CakeEmail->headerCharset); } /** * testWrap method * * @return void */ public function testWrap() { $text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ac turpis orci, non commodo odio. Morbi nibh nisi, vehicula pellentesque accumsan amet.'; $result = $this->CakeEmail->wrap($text, CakeEmail::LINE_LENGTH_SHOULD); $expected = array( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ac turpis orci,', 'non commodo odio. Morbi nibh nisi, vehicula pellentesque accumsan amet.', '' ); $this->assertSame($expected, $result); $text = 'Lorem ipsum dolor sit amet, consectetur < adipiscing elit. Donec ac turpis orci, non commodo odio. Morbi nibh nisi, vehicula > pellentesque accumsan amet.'; $result = $this->CakeEmail->wrap($text, CakeEmail::LINE_LENGTH_SHOULD); $expected = array( 'Lorem ipsum dolor sit amet, consectetur < adipiscing elit. Donec ac turpis', 'orci, non commodo odio. Morbi nibh nisi, vehicula > pellentesque accumsan', 'amet.', '' ); $this->assertSame($expected, $result); $text = '

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


'; $result = $this->CakeEmail->wrap($text, CakeEmail::LINE_LENGTH_SHOULD); $expected = array( '

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


', '' ); $this->assertSame($expected, $result); $text = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ac turpis orci, non commodo odio. Morbi nibh nisi, vehicula pellentesque accumsan amet.'; $result = $this->CakeEmail->wrap($text, CakeEmail::LINE_LENGTH_SHOULD); $expected = array( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ac', 'turpis orci, non commodo odio. Morbi nibh', 'nisi, vehicula pellentesque accumsan amet.', '' ); $this->assertSame($expected, $result); $text = 'Lorem ipsum ok'; $result = $this->CakeEmail->wrap($text, CakeEmail::LINE_LENGTH_SHOULD); $expected = array( 'Lorem ipsum', '', 'ok', '' ); $this->assertSame($expected, $result); $text = 'Lorem ipsum withonewordverybigMorethanthelineshouldsizeofrfcspecificationbyieeeavailableonieeesite ok.'; $result = $this->CakeEmail->wrap($text, CakeEmail::LINE_LENGTH_SHOULD); $expected = array( 'Lorem ipsum', 'withonewordverybigMorethanthelineshouldsizeofrfcspecificationbyieeeavailableonieeesite', 'ok.', '' ); $this->assertSame($expected, $result); } /** * testRender method * * @return void */ public function testRenderWithLayoutAndAttachment() { $this->CakeEmail->emailFormat('html'); $this->CakeEmail->template('html', 'default'); $this->CakeEmail->attachments(array(CAKE . 'basics.php')); $result = $this->CakeEmail->render(array()); $this->assertNotEmpty($result); $result = $this->CakeEmail->getBoundary(); $this->assertNotEmpty($result); } /** * testConstructWithConfigArray method * * @return void */ public function testConstructWithConfigArray() { $configs = array( 'from' => array('some@example.com' => 'My website'), 'to' => 'test@example.com', 'subject' => 'Test mail subject', 'transport' => 'Debug', ); $this->CakeEmail = new CakeEmail($configs); $result = $this->CakeEmail->to(); $this->assertEquals(array($configs['to'] => $configs['to']), $result); $result = $this->CakeEmail->from(); $this->assertEquals($configs['from'], $result); $result = $this->CakeEmail->subject(); $this->assertEquals($configs['subject'], $result); $result = $this->CakeEmail->transport(); $this->assertEquals($configs['transport'], $result); $result = $this->CakeEmail->transportClass(); $this->assertTrue($result instanceof DebugTransport); $result = $this->CakeEmail->send('This is the message'); $this->assertTrue((bool)strpos($result['headers'], 'Message-ID: ')); $this->assertTrue((bool)strpos($result['headers'], 'To: ')); } /** * testConfigArrayWithLayoutWithoutTemplate method * * @return void */ public function testConfigArrayWithLayoutWithoutTemplate() { $configs = array( 'from' => array('some@example.com' => 'My website'), 'to' => 'test@example.com', 'subject' => 'Test mail subject', 'transport' => 'Debug', 'layout' => 'custom' ); $this->CakeEmail = new CakeEmail($configs); $result = $this->CakeEmail->template(); $this->assertEquals('', $result['template']); $this->assertEquals($configs['layout'], $result['layout']); } /** * testConstructWithConfigString method * * @return void */ public function testConstructWithConfigString() { $configs = new TestEmailConfig(); $this->CakeEmail = new TestCakeEmail('test'); $result = $this->CakeEmail->to(); $this->assertEquals($configs->test['to'], $result); $result = $this->CakeEmail->from(); $this->assertEquals($configs->test['from'], $result); $result = $this->CakeEmail->subject(); $this->assertEquals($configs->test['subject'], $result); $result = $this->CakeEmail->transport(); $this->assertEquals($configs->test['transport'], $result); $result = $this->CakeEmail->transportClass(); $this->assertTrue($result instanceof DebugTransport); $result = $this->CakeEmail->send('This is the message'); $this->assertTrue((bool)strpos($result['headers'], 'Message-ID: ')); $this->assertTrue((bool)strpos($result['headers'], 'To: ')); } /** * testViewRender method * * @return void */ public function testViewRender() { $result = $this->CakeEmail->viewRender(); $this->assertEquals('View', $result); $result = $this->CakeEmail->viewRender('Theme'); $this->assertInstanceOf('CakeEmail', $result); $result = $this->CakeEmail->viewRender(); $this->assertEquals('Theme', $result); } /** * testEmailFormat method * * @return void */ public function testEmailFormat() { $result = $this->CakeEmail->emailFormat(); $this->assertEquals('text', $result); $result = $this->CakeEmail->emailFormat('html'); $this->assertInstanceOf('CakeEmail', $result); $result = $this->CakeEmail->emailFormat(); $this->assertEquals('html', $result); $this->setExpectedException('SocketException'); $this->CakeEmail->emailFormat('invalid'); } /** * Tests that it is possible to add charset configuration to a CakeEmail object * * @return void */ public function testConfigCharset() { $email = new CakeEmail(); $this->assertEquals(Configure::read('App.encoding'), $email->charset); $this->assertEquals(Configure::read('App.encoding'), $email->headerCharset); $email = new CakeEmail(array('charset' => 'iso-2022-jp', 'headerCharset' => 'iso-2022-jp-ms')); $this->assertEquals('iso-2022-jp', $email->charset); $this->assertEquals('iso-2022-jp-ms', $email->headerCharset); $email = new CakeEmail(array('charset' => 'iso-2022-jp')); $this->assertEquals('iso-2022-jp', $email->charset); $this->assertEquals('iso-2022-jp', $email->headerCharset); $email = new CakeEmail(array('headerCharset' => 'iso-2022-jp-ms')); $this->assertEquals(Configure::read('App.encoding'), $email->charset); $this->assertEquals('iso-2022-jp-ms', $email->headerCharset); } /** * Tests that the header is encoded using the configured headerCharset * * @return void */ public function testHeaderEncoding() { $this->skipIf(!function_exists('mb_convert_encoding')); $email = new CakeEmail(array('headerCharset' => 'iso-2022-jp-ms', 'transport' => 'Debug')); $email->subject('ใ‚ใ‚Œ๏ผŸใ‚‚ใ—ใ‹ใ—ใฆใฎๅ‰ใจ'); $headers = $email->getHeaders(array('subject')); $expected = "?ISO-2022-JP?B?GyRCJCIkbCEpJGIkNyQrJDckRiROQTAkSBsoQg==?="; $this->assertContains($expected, $headers['Subject']); $email->to('someone@example.com')->from('someone@example.com'); $result = $email->send('ใฃใฆใƒ†ใƒผใƒ–ใƒซใ‚’ไฝœใฃใฆใ‚„ใฃใฆใŸใ‚‰ใ†'); $this->assertContains('ใฃใฆใƒ†ใƒผใƒ–ใƒซใ‚’ไฝœใฃใฆใ‚„ใฃใฆใŸใ‚‰ใ†', $result['message']); } /** * Tests that the body is encoded using the configured charset * * @return void */ public function testBodyEncoding() { $this->skipIf(!function_exists('mb_convert_encoding')); $email = new CakeEmail(array( 'charset' => 'iso-2022-jp', 'headerCharset' => 'iso-2022-jp-ms', 'transport' => 'Debug' )); $email->subject('ใ‚ใ‚Œ๏ผŸใ‚‚ใ—ใ‹ใ—ใฆใฎๅ‰ใจ'); $headers = $email->getHeaders(array('subject')); $expected = "?ISO-2022-JP?B?GyRCJCIkbCEpJGIkNyQrJDckRiROQTAkSBsoQg==?="; $this->assertContains($expected, $headers['Subject']); $email->to('someone@example.com')->from('someone@example.com'); $result = $email->send('ใฃใฆใƒ†ใƒผใƒ–ใƒซใ‚’ไฝœใฃใฆใ‚„ใฃใฆใŸใ‚‰ใ†'); $this->assertContains('Content-Type: text/plain; charset=ISO-2022-JP', $result['headers']); $this->assertContains(mb_convert_encoding('ใฃใฆใƒ†ใƒผใƒ–ใƒซใ‚’ไฝœใฃใฆใ‚„ใฃใฆใŸใ‚‰ใ†', 'ISO-2022-JP'), $result['message']); } /** * Tests that the body is encoded using the configured charset (Japanese standard encoding) * * @return void */ public function testBodyEncodingIso2022Jp() { $this->skipIf(!function_exists('mb_convert_encoding')); $email = new CakeEmail(array( 'charset' => 'iso-2022-jp', 'headerCharset' => 'iso-2022-jp', 'transport' => 'Debug' )); $email->subject('ใ‚ใ‚Œ๏ผŸใ‚‚ใ—ใ‹ใ—ใฆใฎๅ‰ใจ'); $headers = $email->getHeaders(array('subject')); $expected = "?ISO-2022-JP?B?GyRCJCIkbCEpJGIkNyQrJDckRiROQTAkSBsoQg==?="; $this->assertContains($expected, $headers['Subject']); $email->to('someone@example.com')->from('someone@example.com'); $result = $email->send('โ‘ ใˆฑ'); $this->assertTextContains("Content-Type: text/plain; charset=ISO-2022-JP", $result['headers']); $this->assertTextNotContains("Content-Type: text/plain; charset=ISO-2022-JP-MS", $result['headers']); // not charset=iso-2022-jp-ms $this->assertTextNotContains(mb_convert_encoding('โ‘ ใˆฑ', 'ISO-2022-JP-MS'), $result['message']); } /** * Tests that the body is encoded using the configured charset (Japanese irregular encoding, but sometime use this) * * @return void */ public function testBodyEncodingIso2022JpMs() { $this->skipIf(!function_exists('mb_convert_encoding')); $email = new CakeEmail(array( 'charset' => 'iso-2022-jp-ms', 'headerCharset' => 'iso-2022-jp-ms', 'transport' => 'Debug' )); $email->subject('ใ‚ใ‚Œ๏ผŸใ‚‚ใ—ใ‹ใ—ใฆใฎๅ‰ใจ'); $headers = $email->getHeaders(array('subject')); $expected = "?ISO-2022-JP?B?GyRCJCIkbCEpJGIkNyQrJDckRiROQTAkSBsoQg==?="; $this->assertContains($expected, $headers['Subject']); $email->to('someone@example.com')->from('someone@example.com'); $result = $email->send('โ‘ ใˆฑ'); $this->assertTextContains("Content-Type: text/plain; charset=ISO-2022-JP", $result['headers']); $this->assertTextNotContains("Content-Type: text/plain; charset=iso-2022-jp-ms", $result['headers']); // not charset=iso-2022-jp-ms $this->assertContains(mb_convert_encoding('โ‘ ใˆฑ', 'ISO-2022-JP-MS'), $result['message']); } protected function _checkContentTransferEncoding($message, $charset) { $boundary = '--' . $this->CakeEmail->getBoundary(); $result['text'] = false; $result['html'] = false; $length = count($message); for ($i = 0; $i < $length; ++$i) { if ($message[$i] === $boundary) { $flag = false; $type = ''; while (!preg_match('/^$/', $message[$i])) { if (preg_match('/^Content-Type: text\/plain/', $message[$i])) { $type = 'text'; } if (preg_match('/^Content-Type: text\/html/', $message[$i])) { $type = 'html'; } if ($message[$i] === 'Content-Transfer-Encoding: ' . $charset) { $flag = true; } ++$i; } $result[$type] = $flag; } } return $result['text'] && $result['html']; } /** * Test CakeEmail::_encode function * * @return void */ public function testEncode() { $this->skipIf(!function_exists('mb_convert_encoding')); $this->CakeEmail->headerCharset = 'ISO-2022-JP'; $result = $this->CakeEmail->encode('ๆ—ฅๆœฌ่ชž'); $expected = '=?ISO-2022-JP?B?GyRCRnxLXDhsGyhC?='; $this->assertSame($expected, $result); $this->CakeEmail->headerCharset = 'ISO-2022-JP'; $result = $this->CakeEmail->encode('้•ทใ„้•ทใ„้•ทใ„Subjectใฎๅ ดๅˆใฏfoldingใ™ใ‚‹ใฎใŒๆญฃใ—ใ„ใ‚“ใ ใ‘ใฉใ„ใฃใŸใ„ใฉใ†ใชใ‚‹ใ‚“ใ ใ‚ใ†๏ผŸ'); $expected = "=?ISO-2022-JP?B?GyRCRDkkJEQ5JCREOSQkGyhCU3ViamVjdBskQiROPmw5ZyRPGyhCZm9s?=\r\n" . " =?ISO-2022-JP?B?ZGluZxskQiQ5JGskTiQsQDUkNyQkJHMkQCQxJEkkJCRDJD8kJCRJGyhC?=\r\n" . " =?ISO-2022-JP?B?GyRCJCYkSiRrJHMkQCRtJCYhKRsoQg==?="; $this->assertSame($expected, $result); } /** * Tests charset setter/getter * * @return void */ public function testCharset() { $this->CakeEmail->charset('UTF-8'); $this->assertSame($this->CakeEmail->charset(), 'UTF-8'); $this->CakeEmail->charset('ISO-2022-JP'); $this->assertSame($this->CakeEmail->charset(), 'ISO-2022-JP'); $charset = $this->CakeEmail->charset('Shift_JIS'); $this->assertSame($charset, 'Shift_JIS'); } /** * Tests headerCharset setter/getter * * @return void */ public function testHeaderCharset() { $this->CakeEmail->headerCharset('UTF-8'); $this->assertSame($this->CakeEmail->headerCharset(), 'UTF-8'); $this->CakeEmail->headerCharset('ISO-2022-JP'); $this->assertSame($this->CakeEmail->headerCharset(), 'ISO-2022-JP'); $charset = $this->CakeEmail->headerCharset('Shift_JIS'); $this->assertSame($charset, 'Shift_JIS'); } /** * Tests for compatible check. * charset property and charset() method. * headerCharset property and headerCharset() method. * * @return void */ public function testCharsetsCompatible() { $this->skipIf(!function_exists('mb_convert_encoding')); $checkHeaders = array( 'from' => true, 'to' => true, 'cc' => true, 'subject' => true, ); // Header Charset : null (used by default UTF-8) // Body Charset : ISO-2022-JP $oldStyleEmail = $this->_getEmailByOldStyleCharset('iso-2022-jp', null); $oldStyleHeaders = $oldStyleEmail->getHeaders($checkHeaders); $newStyleEmail = $this->_getEmailByNewStyleCharset('iso-2022-jp', null); $newStyleHeaders = $newStyleEmail->getHeaders($checkHeaders); $this->assertSame($oldStyleHeaders['From'], $newStyleHeaders['From']); $this->assertSame($oldStyleHeaders['To'], $newStyleHeaders['To']); $this->assertSame($oldStyleHeaders['Cc'], $newStyleHeaders['Cc']); $this->assertSame($oldStyleHeaders['Subject'], $newStyleHeaders['Subject']); // Header Charset : UTF-8 // Boby Charset : ISO-2022-JP $oldStyleEmail = $this->_getEmailByOldStyleCharset('iso-2022-jp', 'utf-8'); $oldStyleHeaders = $oldStyleEmail->getHeaders($checkHeaders); $newStyleEmail = $this->_getEmailByNewStyleCharset('iso-2022-jp', 'utf-8'); $newStyleHeaders = $newStyleEmail->getHeaders($checkHeaders); $this->assertSame($oldStyleHeaders['From'], $newStyleHeaders['From']); $this->assertSame($oldStyleHeaders['To'], $newStyleHeaders['To']); $this->assertSame($oldStyleHeaders['Cc'], $newStyleHeaders['Cc']); $this->assertSame($oldStyleHeaders['Subject'], $newStyleHeaders['Subject']); // Header Charset : ISO-2022-JP // Boby Charset : UTF-8 $oldStyleEmail = $this->_getEmailByOldStyleCharset('utf-8', 'iso-2022-jp'); $oldStyleHeaders = $oldStyleEmail->getHeaders($checkHeaders); $newStyleEmail = $this->_getEmailByNewStyleCharset('utf-8', 'iso-2022-jp'); $newStyleHeaders = $newStyleEmail->getHeaders($checkHeaders); $this->assertSame($oldStyleHeaders['From'], $newStyleHeaders['From']); $this->assertSame($oldStyleHeaders['To'], $newStyleHeaders['To']); $this->assertSame($oldStyleHeaders['Cc'], $newStyleHeaders['Cc']); $this->assertSame($oldStyleHeaders['Subject'], $newStyleHeaders['Subject']); } /** * @param mixed $charset * @param mixed $headerCharset * @return CakeEmail */ protected function _getEmailByOldStyleCharset($charset, $headerCharset) { $email = new CakeEmail(array('transport' => 'Debug')); if (!empty($charset)) { $email->charset = $charset; } if (!empty($headerCharset)) { $email->headerCharset = $headerCharset; } $email->from('someone@example.com', 'ใฉใ“ใ‹ใฎ่ชฐใ‹'); $email->to('someperson@example.jp', 'ใฉใ“ใ‹ใฎใฉใชใŸใ‹'); $email->cc('miku@example.net', 'ใƒŸใ‚ฏ'); $email->subject('ใƒ†ใ‚นใƒˆใƒกใƒผใƒซ'); $email->send('ใƒ†ใ‚นใƒˆใƒกใƒผใƒซใฎๆœฌๆ–‡'); return $email; } /** * @param mixed $charset * @param mixed $headerCharset * @return CakeEmail */ protected function _getEmailByNewStyleCharset($charset, $headerCharset) { $email = new CakeEmail(array('transport' => 'Debug')); if (!empty($charset)) { $email->charset($charset); } if (!empty($headerCharset)) { $email->headerCharset($headerCharset); } $email->from('someone@example.com', 'ใฉใ“ใ‹ใฎ่ชฐใ‹'); $email->to('someperson@example.jp', 'ใฉใ“ใ‹ใฎใฉใชใŸใ‹'); $email->cc('miku@example.net', 'ใƒŸใ‚ฏ'); $email->subject('ใƒ†ใ‚นใƒˆใƒกใƒผใƒซ'); $email->send('ใƒ†ใ‚นใƒˆใƒกใƒผใƒซใฎๆœฌๆ–‡'); return $email; } /** * testWrapLongLine() * * @return void */ public function testWrapLongLine() { $message = '' . str_repeat('x', CakeEmail::LINE_LENGTH_MUST) . ""; $this->CakeEmail->reset(); $this->CakeEmail->transport('Debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->subject('Wordwrap Test'); $this->CakeEmail->config(array('empty')); $result = $this->CakeEmail->send($message); $expected = "' . str_repeat('x', CakeEmail::LINE_LENGTH_MUST - 26) . "\r\n" . str_repeat('x', 26) . "\r\n\r\n\r\n"; $this->assertEquals($expected, $result['message']); $this->assertLineLengths($result['message']); $str1 = "a "; $str2 = " b"; $length = strlen($str1) + strlen($str2); $message = $str1 . str_repeat('x', CakeEmail::LINE_LENGTH_MUST - $length - 1) . $str2; $result = $this->CakeEmail->send($message); $expected = "{$message}\r\n\r\n"; $this->assertEquals($expected, $result['message']); $this->assertLineLengths($result['message']); $message = $str1 . str_repeat('x', CakeEmail::LINE_LENGTH_MUST - $length) . $str2; $result = $this->CakeEmail->send($message); $expected = "{$message}\r\n\r\n"; $this->assertEquals($expected, $result['message']); $this->assertLineLengths($result['message']); $message = $str1 . str_repeat('x', CakeEmail::LINE_LENGTH_MUST - $length + 1) . $str2; $result = $this->CakeEmail->send($message); $expected = $str1 . str_repeat('x', CakeEmail::LINE_LENGTH_MUST - $length + 1) . sprintf("\r\n%s\r\n\r\n", trim($str2)); $this->assertEquals($expected, $result['message']); $this->assertLineLengths($result['message']); } /** * testWrapWithTagsAcrossLines() * * @return void */ public function testWrapWithTagsAcrossLines() { $str = << The tag is across multiple lines HTML; $message = $str . str_repeat('x', CakeEmail::LINE_LENGTH_MUST + 1); $this->CakeEmail->reset(); $this->CakeEmail->transport('Debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->subject('Wordwrap Test'); $this->CakeEmail->config(array('empty')); $result = $this->CakeEmail->send($message); $message = str_replace("\r\n", "\n", substr($message, 0, -9)); $message = str_replace("\n", "\r\n", $message); $expected = "{$message}\r\nxxxxxxxxx\r\n\r\n"; $this->assertEquals($expected, $result['message']); $this->assertLineLengths($result['message']); } /** * CakeEmailTest::testWrapIncludeLessThanSign() * * @return void */ public function testWrapIncludeLessThanSign() { $str = 'fooCakeEmail->reset(); $this->CakeEmail->transport('Debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->subject('Wordwrap Test'); $this->CakeEmail->config(array('empty')); $result = $this->CakeEmail->send($message); $message = substr($message, 0, -1); $expected = "{$message}\r\nx\r\n\r\n"; $this->assertEquals($expected, $result['message']); $this->assertLineLengths($result['message']); } /** * CakeEmailTest::testWrapForJapaneseEncoding() * * @return void */ public function testWrapForJapaneseEncoding() { $this->skipIf(!function_exists('mb_convert_encoding')); $message = mb_convert_encoding('ๅ—ใ‘ไป˜ใ‘ใพใ—ใŸ', 'iso-2022-jp', 'UTF-8'); $this->CakeEmail->reset(); $this->CakeEmail->transport('Debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->subject('Wordwrap Test'); $this->CakeEmail->config(array('empty')); $this->CakeEmail->charset('iso-2022-jp'); $this->CakeEmail->headerCharset('iso-2022-jp'); $result = $this->CakeEmail->send($message); $expected = "{$message}\r\n\r\n"; $this->assertEquals($expected, $result['message']); } /** * testZeroOnlyLinesNotBeingEmptied() * * @return void */ public function testZeroOnlyLinesNotBeingEmptied() { $message = "Lorem\r\n0\r\n0\r\nipsum"; $this->CakeEmail->reset(); $this->CakeEmail->transport('Debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->subject('Wordwrap Test'); $this->CakeEmail->config(array('empty')); $result = $this->CakeEmail->send($message); $expected = "{$message}\r\n\r\n"; $this->assertEquals($expected, $result['message']); } /** * Test that really long lines don't cause errors. * * @return void */ public function testReallyLongLine() { $this->CakeEmail->reset(); $this->CakeEmail->config(array('empty')); $this->CakeEmail->transport('Debug'); $this->CakeEmail->from('cake@cakephp.org'); $this->CakeEmail->to('cake@cakephp.org'); $this->CakeEmail->subject('Wordwrap Test'); $this->CakeEmail->emailFormat('html'); $this->CakeEmail->template('long_line', null); $result = $this->CakeEmail->send(); $this->assertContains('', $result['message'], 'First bits are included'); $this->assertContains('x', $result['message'], 'Last byte are included'); } /** * CakeEmailTest::assertLineLengths() * * @param string $message * @return void */ public function assertLineLengths($message) { $lines = explode("\r\n", $message); foreach ($lines as $line) { $this->assertTrue(strlen($line) <= CakeEmail::LINE_LENGTH_MUST, 'Line length exceeds the max. limit of CakeEmail::LINE_LENGTH_MUST'); } } } cakephp-2.8.0/lib/Cake/Test/Case/Network/Email/DebugTransportTest.php000066400000000000000000000052121265552240500253410ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Network.Email * @since CakePHP(tm) v 2.0.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('CakeEmail', 'Network/Email'); App::uses('AbstractTransport', 'Network/Email'); App::uses('DebugTransport', 'Network/Email'); /** * Test case */ class DebugTransportTest extends CakeTestCase { /** * Setup * * @return void */ public function setUp() { parent::setUp(); $this->DebugTransport = new DebugTransport(); } /** * testSend method * * @return void */ public function testSend() { $email = $this->getMock('CakeEmail', array('message'), array(), 'DebugCakeEmail'); $email->from('noreply@cakephp.org', 'CakePHP Test'); $email->to('cake@cakephp.org', 'CakePHP'); $email->cc(array('mark@cakephp.org' => 'Mark Story', 'juan@cakephp.org' => 'Juan Basso')); $email->bcc('phpnut@cakephp.org'); $email->messageID('<4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>'); $email->subject('Testing Message'); $date = date(DATE_RFC2822); $email->setHeaders(array('X-Mailer' => DebugCakeEmail::EMAIL_CLIENT, 'Date' => $date)); $email->expects($this->once())->method('message')->will($this->returnValue(array('First Line', 'Second Line', '.Third Line', ''))); $headers = "From: CakePHP Test \r\n"; $headers .= "To: CakePHP \r\n"; $headers .= "Cc: Mark Story , Juan Basso \r\n"; $headers .= "X-Mailer: CakePHP Email\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"; $headers .= "Content-Type: text/plain; charset=UTF-8\r\n"; $headers .= "Content-Transfer-Encoding: 8bit"; $data = "First Line\r\n"; $data .= "Second Line\r\n"; $data .= ".Third Line\r\n"; // Not use 'RFC5321 4.5.2.Transparency' in DebugTransport. $result = $this->DebugTransport->send($email); $this->assertEquals($headers, $result['headers']); $this->assertEquals($data, $result['message']); } } cakephp-2.8.0/lib/Cake/Test/Case/Network/Email/MailTransportTest.php000066400000000000000000000061501265552240500251770ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Network.Email * @since CakePHP(tm) v 2.0.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('CakeEmail', 'Network/Email'); App::uses('AbstractTransport', 'Network/Email'); App::uses('MailTransport', 'Network/Email'); /** * Test case */ class MailTransportTest extends CakeTestCase { /** * Setup * * @return void */ public function setUp() { parent::setUp(); $this->MailTransport = $this->getMock('MailTransport', array('_mail')); $this->MailTransport->config(array('additionalParameters' => '-f')); } /** * testSend method * * @return void */ public function testSendData() { $email = $this->getMock('CakeEmail', array('message'), array()); $email->from('noreply@cakephp.org', 'CakePHP Test'); $email->returnPath('pleasereply@cakephp.org', 'CakePHP Return'); $email->to('cake@cakephp.org', 'CakePHP'); $email->cc(array('mark@cakephp.org' => 'Mark Story', 'juan@cakephp.org' => 'Juan Basso')); $email->bcc('phpnut@cakephp.org'); $email->messageID('<4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>'); $longNonAscii = 'Foรธ Bรฅr Bรฉz Foรธ Bรฅr Bรฉz Foรธ Bรฅr Bรฉz Foรธ Bรฅr Bรฉz'; $email->subject($longNonAscii); $date = date(DATE_RFC2822); $email->setHeaders(array( 'X-Mailer' => 'CakePHP Email', 'Date' => $date, 'X-add' => mb_encode_mimeheader($longNonAscii, 'utf8', 'B'), )); $email->expects($this->any())->method('message') ->will($this->returnValue(array('First Line', 'Second Line', '.Third Line', ''))); $encoded = '=?UTF-8?B?Rm/DuCBCw6VyIELDqXogRm/DuCBCw6VyIELDqXogRm/DuCBCw6VyIELDqXog?='; $encoded .= ' =?UTF-8?B?Rm/DuCBCw6VyIELDqXo=?='; $data = "From: CakePHP Test " . PHP_EOL; $data .= "Return-Path: CakePHP Return " . PHP_EOL; $data .= "Cc: Mark Story , Juan Basso " . PHP_EOL; $data .= "Bcc: phpnut@cakephp.org" . PHP_EOL; $data .= "X-Mailer: CakePHP Email" . PHP_EOL; $data .= "Date: " . $date . PHP_EOL; $data .= "X-add: " . $encoded . PHP_EOL; $data .= "Message-ID: <4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>" . PHP_EOL; $data .= "MIME-Version: 1.0" . PHP_EOL; $data .= "Content-Type: text/plain; charset=UTF-8" . PHP_EOL; $data .= "Content-Transfer-Encoding: 8bit"; $this->MailTransport->expects($this->once())->method('_mail') ->with( 'CakePHP ', $encoded, implode(PHP_EOL, array('First Line', 'Second Line', '.Third Line', '')), $data, '-f' ); $this->MailTransport->send($email); } } cakephp-2.8.0/lib/Cake/Test/Case/Network/Email/SmtpTransportTest.php000066400000000000000000000562221265552240500252450ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Network.Email * @since CakePHP(tm) v 2.0.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('CakeEmail', 'Network/Email'); App::uses('AbstractTransport', 'Network/Email'); App::uses('SmtpTransport', 'Network/Email'); /** * Help to test SmtpTransport */ class SmtpTestTransport extends SmtpTransport { /** * Helper to change the socket * * @param CakeSocket $socket A socket. * @return void */ public function setSocket(CakeSocket $socket) { $this->_socket = $socket; } /** * Helper to change the CakeEmail * * @param object $cakeEmail An email object. * @return void */ public function setCakeEmail($cakeEmail) { $this->_cakeEmail = $cakeEmail; } /** * Disabled the socket change * * @return void */ protected function _generateSocket() { } /** * Magic function to call protected methods * * @param string $method The method to call. * @param string $args The arguments. * @return mixed */ public function __call($method, $args) { $method = '_' . $method; return call_user_func_array(array($this, $method), $args); } } /** * Test case */ class SmtpTransportTest extends CakeTestCase { /** * Setup * * @return void */ public function setUp() { parent::setUp(); $this->socket = $this->getMock('CakeSocket', array('read', 'write', 'connect', 'enableCrypto')); $this->SmtpTransport = new SmtpTestTransport(); $this->SmtpTransport->setSocket($this->socket); $this->SmtpTransport->config(array('client' => 'localhost')); } /** * testConnectEhlo method * * @return void */ public function testConnectEhlo() { $this->socket->expects($this->any())->method('connect')->will($this->returnValue(true)); $this->socket->expects($this->at(0))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue("220 Welcome message\r\n")); $this->socket->expects($this->at(2))->method('write')->with("EHLO localhost\r\n"); $this->socket->expects($this->at(3))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue("250 Accepted\r\n")); $this->SmtpTransport->connect(); } /** * testConnectEhloTls method * * @return void */ public function testConnectEhloTls() { $this->SmtpTransport->config(array('tls' => true)); $this->socket->expects($this->any())->method('connect')->will($this->returnValue(true)); $this->socket->expects($this->at(0))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue("220 Welcome message\r\n")); $this->socket->expects($this->at(2))->method('write')->with("EHLO localhost\r\n"); $this->socket->expects($this->at(3))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue("250 Accepted\r\n")); $this->socket->expects($this->at(5))->method('write')->with("STARTTLS\r\n"); $this->socket->expects($this->at(6))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(7))->method('read')->will($this->returnValue("220 Server ready\r\n")); $this->socket->expects($this->at(8))->method('enableCrypto')->with('tls')->will($this->returnValue(true)); $this->socket->expects($this->at(9))->method('write')->with("EHLO localhost\r\n"); $this->socket->expects($this->at(10))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(11))->method('read')->will($this->returnValue("250 Accepted\r\n")); $this->SmtpTransport->connect(); } /** * testConnectEhloTlsOnNonTlsServer method * * @expectedException SocketException * @expectedExceptionMessage SMTP server did not accept the connection or trying to connect to non TLS SMTP server using TLS. * @return void */ public function testConnectEhloTlsOnNonTlsServer() { $this->SmtpTransport->config(array('tls' => true)); $this->socket->expects($this->any())->method('connect')->will($this->returnValue(true)); $this->socket->expects($this->at(0))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue("220 Welcome message\r\n")); $this->socket->expects($this->at(2))->method('write')->with("EHLO localhost\r\n"); $this->socket->expects($this->at(3))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue("250 Accepted\r\n")); $this->socket->expects($this->at(5))->method('write')->with("STARTTLS\r\n"); $this->socket->expects($this->at(6))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(7))->method('read')->will($this->returnValue("500 5.3.3 Unrecognized command\r\n")); $this->SmtpTransport->connect(); } /** * testConnectEhloNoTlsOnRequiredTlsServer method * * @expectedException SocketException * @expectedExceptionMessage SMTP authentication method not allowed, check if SMTP server requires TLS. * @return void */ public function testConnectEhloNoTlsOnRequiredTlsServer() { $this->SmtpTransport->config(array('tls' => false, 'username' => 'user', 'password' => 'pass')); $this->socket->expects($this->any())->method('connect')->will($this->returnValue(true)); $this->socket->expects($this->at(0))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue("220 Welcome message\r\n")); $this->socket->expects($this->at(2))->method('write')->with("EHLO localhost\r\n"); $this->socket->expects($this->at(3))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue("250 Accepted\r\n")); $this->socket->expects($this->at(5))->method('write')->with("AUTH LOGIN\r\n"); $this->socket->expects($this->at(6))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(7))->method('read')->will($this->returnValue("504 5.7.4 Unrecognized authentication type\r\n")); $this->SmtpTransport->connect(); $this->SmtpTransport->auth(); } /** * testConnectHelo method * * @return void */ public function testConnectHelo() { $this->socket->expects($this->any())->method('connect')->will($this->returnValue(true)); $this->socket->expects($this->at(0))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue("220 Welcome message\r\n")); $this->socket->expects($this->at(2))->method('write')->with("EHLO localhost\r\n"); $this->socket->expects($this->at(3))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue("200 Not Accepted\r\n")); $this->socket->expects($this->at(5))->method('write')->with("HELO localhost\r\n"); $this->socket->expects($this->at(6))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(7))->method('read')->will($this->returnValue("250 Accepted\r\n")); $this->SmtpTransport->connect(); } /** * testConnectFail method * * @expectedException SocketException * @expectedExceptionMessage SMTP server did not accept the connection. * @return void */ public function testConnectFail() { $this->socket->expects($this->any())->method('connect')->will($this->returnValue(true)); $this->socket->expects($this->at(0))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue("220 Welcome message\r\n")); $this->socket->expects($this->at(2))->method('write')->with("EHLO localhost\r\n"); $this->socket->expects($this->at(3))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue("200 Not Accepted\r\n")); $this->socket->expects($this->at(5))->method('write')->with("HELO localhost\r\n"); $this->socket->expects($this->at(6))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(7))->method('read')->will($this->returnValue("200 Not Accepted\r\n")); $this->SmtpTransport->connect(); } /** * testAuth method * * @return void */ public function testAuth() { $this->socket->expects($this->at(0))->method('write')->with("AUTH LOGIN\r\n"); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(2))->method('read')->will($this->returnValue("334 Login\r\n")); $this->socket->expects($this->at(3))->method('write')->with("bWFyaw==\r\n"); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(5))->method('read')->will($this->returnValue("334 Pass\r\n")); $this->socket->expects($this->at(6))->method('write')->with("c3Rvcnk=\r\n"); $this->socket->expects($this->at(7))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(8))->method('read')->will($this->returnValue("235 OK\r\n")); $this->SmtpTransport->config(array('username' => 'mark', 'password' => 'story')); $this->SmtpTransport->auth(); } /** * testAuthNotRecognized method * * @expectedException SocketException * @expectedExceptionMessage AUTH command not recognized or not implemented, SMTP server may not require authentication. * @return void */ public function testAuthNotRecognized() { $this->socket->expects($this->at(0))->method('write')->with("AUTH LOGIN\r\n"); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(2))->method('read')->will($this->returnValue("500 5.3.3 Unrecognized command\r\n")); $this->SmtpTransport->config(array('username' => 'mark', 'password' => 'story')); $this->SmtpTransport->auth(); } /** * testAuthNotImplemented method * * @expectedException SocketException * @expectedExceptionMessage AUTH command not recognized or not implemented, SMTP server may not require authentication. * @return void */ public function testAuthNotImplemented() { $this->socket->expects($this->at(0))->method('write')->with("AUTH LOGIN\r\n"); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(2))->method('read')->will($this->returnValue("502 5.3.3 Command not implemented\r\n")); $this->SmtpTransport->config(array('username' => 'mark', 'password' => 'story')); $this->SmtpTransport->auth(); } /** * testAuthBadSequence method * * @expectedException SocketException * @expectedExceptionMessage SMTP Error: 503 5.5.1 Already authenticated * @return void */ public function testAuthBadSequence() { $this->socket->expects($this->at(0))->method('write')->with("AUTH LOGIN\r\n"); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(2))->method('read')->will($this->returnValue("503 5.5.1 Already authenticated\r\n")); $this->SmtpTransport->config(array('username' => 'mark', 'password' => 'story')); $this->SmtpTransport->auth(); } /** * testAuthBadUsername method * * @expectedException SocketException * @expectedExceptionMessage SMTP server did not accept the username. * @return void */ public function testAuthBadUsername() { $this->socket->expects($this->at(0))->method('write')->with("AUTH LOGIN\r\n"); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(2))->method('read')->will($this->returnValue("334 Login\r\n")); $this->socket->expects($this->at(3))->method('write')->with("bWFyaw==\r\n"); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(5))->method('read')->will($this->returnValue("535 5.7.8 Authentication failed\r\n")); $this->SmtpTransport->config(array('username' => 'mark', 'password' => 'story')); $this->SmtpTransport->auth(); } /** * testAuthBadPassword method * * @expectedException SocketException * @expectedExceptionMessage SMTP server did not accept the password. * @return void */ public function testAuthBadPassword() { $this->socket->expects($this->at(0))->method('write')->with("AUTH LOGIN\r\n"); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(2))->method('read')->will($this->returnValue("334 Login\r\n")); $this->socket->expects($this->at(3))->method('write')->with("bWFyaw==\r\n"); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(5))->method('read')->will($this->returnValue("334 Pass\r\n")); $this->socket->expects($this->at(6))->method('write')->with("c3Rvcnk=\r\n"); $this->socket->expects($this->at(7))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(8))->method('read')->will($this->returnValue("535 5.7.8 Authentication failed\r\n")); $this->SmtpTransport->config(array('username' => 'mark', 'password' => 'story')); $this->SmtpTransport->auth(); } /** * testAuthNoAuth method * * @return void */ public function testAuthNoAuth() { $this->socket->expects($this->any())->method('write')->with($this->logicalNot($this->stringContains('AUTH LOGIN'))); $this->SmtpTransport->config(array('username' => null, 'password' => null)); $this->SmtpTransport->auth(); } /** * testRcpt method * * @return void */ public function testRcpt() { $email = new CakeEmail(); $email->from('noreply@cakephp.org', 'CakePHP Test'); $email->to('cake@cakephp.org', 'CakePHP'); $email->bcc('phpnut@cakephp.org'); $email->cc(array('mark@cakephp.org' => 'Mark Story', 'juan@cakephp.org' => 'Juan Basso')); $this->socket->expects($this->at(0))->method('write')->with("MAIL FROM:\r\n"); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(2))->method('read')->will($this->returnValue("250 OK\r\n")); $this->socket->expects($this->at(3))->method('write')->with("RCPT TO:\r\n"); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(5))->method('read')->will($this->returnValue("250 OK\r\n")); $this->socket->expects($this->at(6))->method('write')->with("RCPT TO:\r\n"); $this->socket->expects($this->at(7))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(8))->method('read')->will($this->returnValue("250 OK\r\n")); $this->socket->expects($this->at(9))->method('write')->with("RCPT TO:\r\n"); $this->socket->expects($this->at(10))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(11))->method('read')->will($this->returnValue("250 OK\r\n")); $this->socket->expects($this->at(12))->method('write')->with("RCPT TO:\r\n"); $this->socket->expects($this->at(13))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(14))->method('read')->will($this->returnValue("250 OK\r\n")); $this->SmtpTransport->setCakeEmail($email); $this->SmtpTransport->sendRcpt(); } /** * testRcptWithReturnPath method * * @return void */ public function testRcptWithReturnPath() { $email = new CakeEmail(); $email->from('noreply@cakephp.org', 'CakePHP Test'); $email->to('cake@cakephp.org', 'CakePHP'); $email->returnPath('pleasereply@cakephp.org', 'CakePHP Return'); $this->socket->expects($this->at(0))->method('write')->with("MAIL FROM:\r\n"); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(2))->method('read')->will($this->returnValue("250 OK\r\n")); $this->socket->expects($this->at(3))->method('write')->with("RCPT TO:\r\n"); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(5))->method('read')->will($this->returnValue("250 OK\r\n")); $this->SmtpTransport->setCakeEmail($email); $this->SmtpTransport->sendRcpt(); } /** * testSendData method * * @return void */ public function testSendData() { $email = $this->getMock('CakeEmail', array('message'), array(), 'SmtpCakeEmail'); $email->from('noreply@cakephp.org', 'CakePHP Test'); $email->returnPath('pleasereply@cakephp.org', 'CakePHP Return'); $email->to('cake@cakephp.org', 'CakePHP'); $email->cc(array('mark@cakephp.org' => 'Mark Story', 'juan@cakephp.org' => 'Juan Basso')); $email->bcc('phpnut@cakephp.org'); $email->messageID('<4d9946cf-0a44-4907-88fe-1d0ccbdd56cb@localhost>'); $email->subject('Testing SMTP'); $date = date(DATE_RFC2822); $email->setHeaders(array('X-Mailer' => SmtpCakeEmail::EMAIL_CLIENT, 'Date' => $date)); $email->expects($this->once())->method('message')->will($this->returnValue(array('First Line', 'Second Line', '.Third Line', ''))); $data = "From: CakePHP Test \r\n"; $data .= "To: CakePHP \r\n"; $data .= "Cc: Mark Story , Juan Basso \r\n"; $data .= "X-Mailer: CakePHP Email\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"; $data .= "Content-Type: text/plain; charset=UTF-8\r\n"; $data .= "Content-Transfer-Encoding: 8bit\r\n"; $data .= "\r\n"; $data .= "First Line\r\n"; $data .= "Second Line\r\n"; $data .= "..Third Line\r\n"; // RFC5321 4.5.2.Transparency $data .= "\r\n"; $data .= "\r\n\r\n.\r\n"; $this->socket->expects($this->at(0))->method('write')->with("DATA\r\n"); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(2))->method('read')->will($this->returnValue("354 OK\r\n")); $this->socket->expects($this->at(3))->method('write')->with($data); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(5))->method('read')->will($this->returnValue("250 OK\r\n")); $this->SmtpTransport->setCakeEmail($email); $this->SmtpTransport->sendData(); } /** * testQuit method * * @return void */ public function testQuit() { $this->socket->expects($this->at(0))->method('write')->with("QUIT\r\n"); $this->SmtpTransport->disconnect(); } /** * testEmptyConfigArray method * * @return void */ public function testEmptyConfigArray() { $expected = $this->SmtpTransport->config(array( 'client' => 'myhost.com', 'port' => 666 )); $this->assertEquals(666, $expected['port']); $result = $this->SmtpTransport->config(array()); $this->assertEquals($expected, $result); } /** * testGetLastResponse method * * @return void */ public function testGetLastResponse() { $this->assertEmpty($this->SmtpTransport->getLastResponse()); $this->socket->expects($this->any())->method('connect')->will($this->returnValue(true)); $this->socket->expects($this->at(0))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue("220 Welcome message\r\n")); $this->socket->expects($this->at(2))->method('write')->with("EHLO localhost\r\n"); $this->socket->expects($this->at(3))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue("250-PIPELINING\r\n")); $this->socket->expects($this->at(5))->method('read')->will($this->returnValue("250-SIZE 102400000\r\n")); $this->socket->expects($this->at(6))->method('read')->will($this->returnValue("250-VRFY\r\n")); $this->socket->expects($this->at(7))->method('read')->will($this->returnValue("250-ETRN\r\n")); $this->socket->expects($this->at(8))->method('read')->will($this->returnValue("250-STARTTLS\r\n")); $this->socket->expects($this->at(9))->method('read')->will($this->returnValue("250-AUTH PLAIN LOGIN\r\n")); $this->socket->expects($this->at(10))->method('read')->will($this->returnValue("250-AUTH=PLAIN LOGIN\r\n")); $this->socket->expects($this->at(11))->method('read')->will($this->returnValue("250-ENHANCEDSTATUSCODES\r\n")); $this->socket->expects($this->at(12))->method('read')->will($this->returnValue("250-8BITMIME\r\n")); $this->socket->expects($this->at(13))->method('read')->will($this->returnValue("250 DSN\r\n")); $this->SmtpTransport->connect(); $expected = array( array('code' => '250', 'message' => 'PIPELINING'), array('code' => '250', 'message' => 'SIZE 102400000'), array('code' => '250', 'message' => 'VRFY'), array('code' => '250', 'message' => 'ETRN'), array('code' => '250', 'message' => 'STARTTLS'), array('code' => '250', 'message' => 'AUTH PLAIN LOGIN'), array('code' => '250', 'message' => 'AUTH=PLAIN LOGIN'), array('code' => '250', 'message' => 'ENHANCEDSTATUSCODES'), array('code' => '250', 'message' => '8BITMIME'), array('code' => '250', 'message' => 'DSN') ); $result = $this->SmtpTransport->getLastResponse(); $this->assertEquals($expected, $result); $email = new CakeEmail(); $email->from('noreply@cakephp.org', 'CakePHP Test'); $email->to('cake@cakephp.org', 'CakePHP'); $this->socket->expects($this->at(0))->method('write')->with("MAIL FROM:\r\n"); $this->socket->expects($this->at(1))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(2))->method('read')->will($this->returnValue("250 OK\r\n")); $this->socket->expects($this->at(3))->method('write')->with("RCPT TO:\r\n"); $this->socket->expects($this->at(4))->method('read')->will($this->returnValue(false)); $this->socket->expects($this->at(5))->method('read')->will($this->returnValue("250 OK\r\n")); $this->SmtpTransport->setCakeEmail($email); $this->SmtpTransport->sendRcpt(); $expected = array( array('code' => '250', 'message' => 'OK'), ); $result = $this->SmtpTransport->getLastResponse(); $this->assertEquals($expected, $result); } /** * testBufferResponseLines method * * @return void */ public function testBufferResponseLines() { $reponseLines = array( '123', "456\tFOO", 'FOOBAR', '250-PIPELINING', '250-ENHANCEDSTATUSCODES', '250-8BITMIME', '250 DSN', ); $this->SmtpTransport->bufferResponseLines($reponseLines); $expected = array( array('code' => '123', 'message' => null), array('code' => '250', 'message' => 'PIPELINING'), array('code' => '250', 'message' => 'ENHANCEDSTATUSCODES'), array('code' => '250', 'message' => '8BITMIME'), array('code' => '250', 'message' => 'DSN') ); $result = $this->SmtpTransport->getLastResponse(); $this->assertEquals($expected, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Network/Http/000077500000000000000000000000001265552240500207155ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Network/Http/BasicAuthenticationTest.php000066400000000000000000000047221265552240500262140ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Network.Http * @since CakePHP(tm) v 2.0.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('HttpSocket', 'Network/Http'); App::uses('BasicAuthentication', 'Network/Http'); /** * class TestSslHttpSocket * * @package Cake.Test.Case.Network.Http */ class TestSslHttpSocket extends HttpSocket { /** * testSetProxy method * * @return void */ public function testSetProxy($proxy = null) { $this->_proxy = $proxy; $this->_setProxy(); } } /** * BasicMethodTest class * * @package Cake.Test.Case.Network.Http */ class BasicAuthenticationTest extends CakeTestCase { /** * testAuthentication method * * @return void */ public function testAuthentication() { $http = new HttpSocket(); $auth = array( 'method' => 'Basic', 'user' => 'mark', 'pass' => 'secret' ); BasicAuthentication::authentication($http, $auth); $this->assertEquals('Basic bWFyazpzZWNyZXQ=', $http->request['header']['Authorization']); } /** * testProxyAuthentication method * * @return void */ public function testProxyAuthentication() { $http = new HttpSocket(); $proxy = array( 'method' => 'Basic', 'user' => 'mark', 'pass' => 'secret' ); BasicAuthentication::proxyAuthentication($http, $proxy); $this->assertEquals('Basic bWFyazpzZWNyZXQ=', $http->request['header']['Proxy-Authorization']); } /** * testProxyAuthenticationSsl method * * @return void */ public function testProxyAuthenticationSsl() { $http = new TestSslHttpSocket(); $http->request['uri']['scheme'] = 'https'; $proxy = array( 'host' => 'localhost', 'port' => 3128, 'method' => 'Basic', 'user' => 'mark', 'pass' => 'secret' ); $http->testSetProxy($proxy); $this->assertEquals('Basic bWFyazpzZWNyZXQ=', $http->config['proxyauth']); $this->assertFalse(isset($http->request['header']['Proxy-Authorization'])); } } cakephp-2.8.0/lib/Cake/Test/Case/Network/Http/DigestAuthenticationTest.php000066400000000000000000000155271265552240500264170ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Network.Http * @since CakePHP(tm) v 2.0.0 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('HttpSocket', 'Network/Http'); App::uses('DigestAuthentication', 'Network/Http'); /** * Class DigestHttpSocket * * @package Cake.Test.Case.Network.Http */ class DigestHttpSocket extends HttpSocket { /** * nextHeader attribute * * @var string */ public $nextHeader = ''; /** * request method * * @param mixed $request * @return void */ public function request($request = array()) { if ($request === false) { if (isset($this->response['header']['WWW-Authenticate'])) { unset($this->response['header']['WWW-Authenticate']); } return; } $this->response['header']['WWW-Authenticate'] = $this->nextHeader; } } /** * DigestAuthenticationTest class * * @package Cake.Test.Case.Network.Http */ class DigestAuthenticationTest extends CakeTestCase { /** * Socket property * * @var mixed */ public $HttpSocket = null; /** * This function sets up a HttpSocket instance we are going to use for testing * * @return void */ public function setUp() { parent::setUp(); $this->HttpSocket = new DigestHttpSocket(); $this->HttpSocket->request['method'] = 'GET'; $this->HttpSocket->request['uri']['path'] = '/'; } /** * We use this function to clean up after the test case was executed * * @return void */ public function tearDown() { parent::tearDown(); unset($this->HttpSocket); } /** * testBasic method * * @return void */ public function testBasic() { $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51"'; $this->assertFalse(isset($this->HttpSocket->request['header']['Authorization'])); $auth = array('user' => 'admin', 'pass' => '1234'); DigestAuthentication::authentication($this->HttpSocket, $auth); $this->assertTrue(isset($this->HttpSocket->request['header']['Authorization'])); $this->assertEquals('The batcave', $auth['realm']); $this->assertEquals('4cded326c6c51', $auth['nonce']); } /** * testQop method * * @return void */ public function testQop() { $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51"'; $auth = array('user' => 'admin', 'pass' => '1234'); DigestAuthentication::authentication($this->HttpSocket, $auth); $expected = 'Digest username="admin", realm="The batcave", nonce="4cded326c6c51", uri="/", response="da7e2a46b471d77f70a9bb3698c8902b"'; $this->assertEquals($expected, $this->HttpSocket->request['header']['Authorization']); $this->assertFalse(isset($auth['qop'])); $this->assertFalse(isset($auth['nc'])); $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51",qop="auth"'; $auth = array('user' => 'admin', 'pass' => '1234'); DigestAuthentication::authentication($this->HttpSocket, $auth); $expected = '@Digest username="admin", realm="The batcave", nonce="4cded326c6c51", uri="/", response="[a-z0-9]{32}", qop="auth", nc=00000001, cnonce="[a-z0-9]+"@'; $this->assertRegExp($expected, $this->HttpSocket->request['header']['Authorization']); $this->assertEquals('auth', $auth['qop']); $this->assertEquals(2, $auth['nc']); } /** * testOpaque method * * @return void */ public function testOpaque() { $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51"'; $auth = array('user' => 'admin', 'pass' => '1234'); DigestAuthentication::authentication($this->HttpSocket, $auth); $this->assertFalse(strpos($this->HttpSocket->request['header']['Authorization'], 'opaque="d8ea7aa61a1693024c4cc3a516f49b3c"')); $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51",opaque="d8ea7aa61a1693024c4cc3a516f49b3c"'; $auth = array('user' => 'admin', 'pass' => '1234'); DigestAuthentication::authentication($this->HttpSocket, $auth); $this->assertTrue(strpos($this->HttpSocket->request['header']['Authorization'], 'opaque="d8ea7aa61a1693024c4cc3a516f49b3c"') > 0); } /** * testMultipleRequest method * * @return void */ public function testMultipleRequest() { $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51",qop="auth"'; $auth = array('user' => 'admin', 'pass' => '1234'); DigestAuthentication::authentication($this->HttpSocket, $auth); $this->assertTrue(strpos($this->HttpSocket->request['header']['Authorization'], 'nc=00000001') > 0); $this->assertEquals(2, $auth['nc']); DigestAuthentication::authentication($this->HttpSocket, $auth); $this->assertTrue(strpos($this->HttpSocket->request['header']['Authorization'], 'nc=00000002') > 0); $this->assertEquals(3, $auth['nc']); $responsePos = strpos($this->HttpSocket->request['header']['Authorization'], 'response='); $response = substr($this->HttpSocket->request['header']['Authorization'], $responsePos + 10, 32); $this->HttpSocket->nextHeader = ''; DigestAuthentication::authentication($this->HttpSocket, $auth); $this->assertTrue(strpos($this->HttpSocket->request['header']['Authorization'], 'nc=00000003') > 0); $this->assertEquals(4, $auth['nc']); $responsePos = strpos($this->HttpSocket->request['header']['Authorization'], 'response='); $responseB = substr($this->HttpSocket->request['header']['Authorization'], $responsePos + 10, 32); $this->assertNotEquals($response, $responseB); } /** * testPathChanged method * * @return void */ public function testPathChanged() { $this->HttpSocket->nextHeader = 'Digest realm="The batcave",nonce="4cded326c6c51"'; $this->HttpSocket->request['uri']['path'] = '/admin'; $auth = array('user' => 'admin', 'pass' => '1234'); DigestAuthentication::authentication($this->HttpSocket, $auth); $responsePos = strpos($this->HttpSocket->request['header']['Authorization'], 'response='); $response = substr($this->HttpSocket->request['header']['Authorization'], $responsePos + 10, 32); $this->assertNotEquals('da7e2a46b471d77f70a9bb3698c8902b', $response); } /** * testNoDigestResponse method * * @return void */ public function testNoDigestResponse() { $this->HttpSocket->nextHeader = false; $this->HttpSocket->request['uri']['path'] = '/admin'; $auth = array('user' => 'admin', 'pass' => '1234'); DigestAuthentication::authentication($this->HttpSocket, $auth); $this->assertFalse(isset($this->HttpSocket->request['header']['Authorization'])); } } cakephp-2.8.0/lib/Cake/Test/Case/Network/Http/HttpResponseTest.php000066400000000000000000000437531265552240500247400ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Network.Http * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('HttpResponse', 'Network/Http'); /** * TestHttpResponse class * * @package Cake.Test.Case.Network.Http */ class TestHttpResponse extends HttpResponse { /** * Convenience method for testing protected method * * @param array $header Header as an indexed array (field => value) * @return array Parsed header */ public function parseHeader($header) { return parent::_parseHeader($header); } /** * Convenience method for testing protected method * * @param string $body A string containing the body to decode * @param bool|string $encoding Can be false in case no encoding is being used, or a string representing the encoding * @return mixed Array or false */ public function decodeBody($body, $encoding = 'chunked') { return parent::_decodeBody($body, $encoding); } /** * Convenience method for testing protected method * * @param string $body A string containing the chunked body to decode * @return mixed Array or false */ public function decodeChunkedBody($body) { return parent::_decodeChunkedBody($body); } /** * Convenience method for testing protected method * * @param string $token Token to unescape * @return string Unescaped token */ public function unescapeToken($token, $chars = null) { return parent::_unescapeToken($token, $chars); } /** * Convenience method for testing protected method * * @param bool $hex true to get them as HEX values, false otherwise * @return array Escape chars */ public function tokenEscapeChars($hex = true, $chars = null) { return parent::_tokenEscapeChars($hex, $chars); } } /** * HttpResponseTest class * * @package Cake.Test.Case.Network.Http */ class HttpResponseTest extends CakeTestCase { /** * This function sets up a HttpResponse * * @return void */ public function setUp() { parent::setUp(); $this->HttpResponse = new TestHttpResponse(); } /** * testBody * * @return void */ public function testBody() { $this->HttpResponse->body = 'testing'; $this->assertEquals('testing', $this->HttpResponse->body()); $this->HttpResponse->body = null; $this->assertSame($this->HttpResponse->body(), ''); } /** * testToString * * @return void */ public function testToString() { $this->HttpResponse->body = 'other test'; $this->assertEquals('other test', $this->HttpResponse->body()); $this->assertEquals('other test', (string)$this->HttpResponse); $this->assertTrue(strpos($this->HttpResponse, 'test') > 0); $this->HttpResponse->body = null; $this->assertEquals('', (string)$this->HttpResponse); } /** * testGetHeader * * @return void */ public function testGetHeader() { $this->HttpResponse->headers = array( 'foo' => 'Bar', 'Some' => 'ok', 'HeAdEr' => 'value', 'content-Type' => 'text/plain' ); $this->assertEquals('Bar', $this->HttpResponse->getHeader('foo')); $this->assertEquals('Bar', $this->HttpResponse->getHeader('Foo')); $this->assertEquals('Bar', $this->HttpResponse->getHeader('FOO')); $this->assertEquals('value', $this->HttpResponse->getHeader('header')); $this->assertEquals('text/plain', $this->HttpResponse->getHeader('Content-Type')); $this->assertNull($this->HttpResponse->getHeader(0)); $this->assertEquals('Bar', $this->HttpResponse->getHeader('foo', false)); $this->assertEquals('not from class', $this->HttpResponse->getHeader('foo', array('foo' => 'not from class'))); } /** * testIsOk * * @return void */ public function testIsOk() { $this->HttpResponse->code = 0; $this->assertFalse($this->HttpResponse->isOk()); $this->HttpResponse->code = -1; $this->assertFalse($this->HttpResponse->isOk()); $this->HttpResponse->code = 'what?'; $this->assertFalse($this->HttpResponse->isOk()); $this->HttpResponse->code = 200; $this->assertTrue($this->HttpResponse->isOk()); $this->HttpResponse->code = 201; $this->assertTrue($this->HttpResponse->isOk()); $this->HttpResponse->code = 202; $this->assertTrue($this->HttpResponse->isOk()); $this->HttpResponse->code = 203; $this->assertTrue($this->HttpResponse->isOk()); $this->HttpResponse->code = 204; $this->assertTrue($this->HttpResponse->isOk()); $this->HttpResponse->code = 205; $this->assertTrue($this->HttpResponse->isOk()); $this->HttpResponse->code = 206; $this->assertTrue($this->HttpResponse->isOk()); $this->HttpResponse->code = 207; $this->assertFalse($this->HttpResponse->isOk()); $this->HttpResponse->code = 208; $this->assertFalse($this->HttpResponse->isOk()); $this->HttpResponse->code = 209; $this->assertFalse($this->HttpResponse->isOk()); $this->HttpResponse->code = 210; $this->assertFalse($this->HttpResponse->isOk()); $this->HttpResponse->code = 226; $this->assertFalse($this->HttpResponse->isOk()); $this->HttpResponse->code = 288; $this->assertFalse($this->HttpResponse->isOk()); $this->HttpResponse->code = 301; $this->assertFalse($this->HttpResponse->isOk()); } /** * testIsRedirect * * @return void */ public function testIsRedirect() { $this->HttpResponse->code = 0; $this->assertFalse($this->HttpResponse->isRedirect()); $this->HttpResponse->code = -1; $this->assertFalse($this->HttpResponse->isRedirect()); $this->HttpResponse->code = 201; $this->assertFalse($this->HttpResponse->isRedirect()); $this->HttpResponse->code = 'what?'; $this->assertFalse($this->HttpResponse->isRedirect()); $this->HttpResponse->code = 301; $this->assertFalse($this->HttpResponse->isRedirect()); $this->HttpResponse->code = 302; $this->assertFalse($this->HttpResponse->isRedirect()); $this->HttpResponse->code = 303; $this->assertFalse($this->HttpResponse->isRedirect()); $this->HttpResponse->code = 307; $this->assertFalse($this->HttpResponse->isRedirect()); $this->HttpResponse->code = 301; $this->HttpResponse->headers['Location'] = 'http://somewhere/'; $this->assertTrue($this->HttpResponse->isRedirect()); $this->HttpResponse->code = 302; $this->HttpResponse->headers['Location'] = 'http://somewhere/'; $this->assertTrue($this->HttpResponse->isRedirect()); $this->HttpResponse->code = 303; $this->HttpResponse->headers['Location'] = 'http://somewhere/'; $this->assertTrue($this->HttpResponse->isRedirect()); $this->HttpResponse->code = 307; $this->HttpResponse->headers['Location'] = 'http://somewhere/'; $this->assertTrue($this->HttpResponse->isRedirect()); } /** * Test that HttpSocket::parseHeader can take apart a given (and valid) $header string and turn it into an array. * * @return void */ public function testParseHeader() { $r = $this->HttpResponse->parseHeader(array('foo' => 'Bar', 'fOO-bAr' => 'quux')); $this->assertEquals(array('foo' => 'Bar', 'fOO-bAr' => 'quux'), $r); $r = $this->HttpResponse->parseHeader(true); $this->assertEquals(false, $r); $header = "Host: cakephp.org\t\r\n"; $r = $this->HttpResponse->parseHeader($header); $expected = array( 'Host' => 'cakephp.org' ); $this->assertEquals($expected, $r); $header = "Date:Sat, 07 Apr 2007 10:10:25 GMT\r\nX-Powered-By: PHP/5.1.2\r\n"; $r = $this->HttpResponse->parseHeader($header); $expected = array( 'Date' => 'Sat, 07 Apr 2007 10:10:25 GMT', 'X-Powered-By' => 'PHP/5.1.2' ); $this->assertEquals($expected, $r); $header = "people: Jim,John\r\nfoo-LAND: Bar\r\ncAKe-PHP: rocks\r\n"; $r = $this->HttpResponse->parseHeader($header); $expected = array( 'people' => 'Jim,John', 'foo-LAND' => 'Bar', 'cAKe-PHP' => 'rocks' ); $this->assertEquals($expected, $r); $header = "People: Jim,John,Tim\r\nPeople: Lisa,Tina,Chelsea\r\n"; $r = $this->HttpResponse->parseHeader($header); $expected = array( 'People' => array('Jim,John,Tim', 'Lisa,Tina,Chelsea') ); $this->assertEquals($expected, $r); $header = "Multi-Line: I am a \r\nmulti line\t\r\nfield value.\r\nSingle-Line: I am not\r\n"; $r = $this->HttpResponse->parseHeader($header); $expected = array( 'Multi-Line' => "I am a\r\nmulti line\r\nfield value.", 'Single-Line' => 'I am not' ); $this->assertEquals($expected, $r); $header = "Esc\"@\"ped: value\r\n"; $r = $this->HttpResponse->parseHeader($header); $expected = array( 'Esc@ped' => 'value' ); $this->assertEquals($expected, $r); } /** * testParseResponse method * * @return void */ public function testParseResponse() { $tests = array( 'simple-request' => array( 'response' => array( 'status-line' => "HTTP/1.x 200 OK\r\n", 'header' => "Date: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\n", 'body' => "

Hello World

\r\n

It's good to be html

" ), 'expectations' => array( 'httpVersion' => 'HTTP/1.x', 'code' => 200, 'reasonPhrase' => 'OK', 'headers' => array('Date' => 'Mon, 16 Apr 2007 04:14:16 GMT', 'Server' => 'CakeHttp Server'), 'body' => "

Hello World

\r\n

It's good to be html

" ) ), 'no-header' => array( 'response' => array( 'status-line' => "HTTP/1.x 404 OK\r\n", 'header' => null ), 'expectations' => array( 'code' => 404, 'headers' => array() ) ) ); $testResponse = array(); $expectations = array(); foreach ($tests as $name => $test) { $testResponse = array_merge($testResponse, $test['response']); $testResponse['response'] = $testResponse['status-line'] . $testResponse['header'] . "\r\n" . $testResponse['body']; $this->HttpResponse->parseResponse($testResponse['response']); $expectations = array_merge($expectations, $test['expectations']); foreach ($expectations as $property => $expectedVal) { $this->assertEquals($expectedVal, $this->HttpResponse->{$property}, 'Test "' . $name . '": response.' . $property . ' - %s'); } foreach (array('status-line', 'header', 'body', 'response') as $field) { $this->assertEquals($this->HttpResponse['raw'][$field], $testResponse[$field], 'Test response.raw.' . $field . ': %s'); } } } /** * data provider function for testInvalidParseResponseData * * @return array */ public static function invalidParseResponseDataProvider() { return array( array(array('foo' => 'bar')), array(true), array("HTTP Foo\r\nBar: La"), array('HTTP/1.1 TEST ERROR') ); } /** * testInvalidParseResponseData * * @dataProvider invalidParseResponseDataProvider * @expectedException SocketException * @return void */ public function testInvalidParseResponseData($value) { $this->HttpResponse->parseResponse($value); } /** * testDecodeBody method * * @return void */ public function testDecodeBody() { $r = $this->HttpResponse->decodeBody(true); $this->assertEquals(false, $r); $r = $this->HttpResponse->decodeBody('Foobar', false); $this->assertEquals(array('body' => 'Foobar', 'header' => false), $r); $encoding = 'chunked'; $sample = array( 'encoded' => "19\r\nThis is a chunked message\r\n0\r\n", 'decoded' => array('body' => "This is a chunked message", 'header' => false) ); $r = $this->HttpResponse->decodeBody($sample['encoded'], $encoding); $this->assertEquals($r, $sample['decoded']); $encoding = 'chunked'; $sample = array( 'encoded' => "19\nThis is a chunked message\r\n0\n", 'decoded' => array('body' => "This is a chunked message", 'header' => false) ); $r = $this->HttpResponse->decodeBody($sample['encoded'], $encoding); $this->assertEquals($r, $sample['decoded'], 'Inconsistent line terminators should be tolerated.'); } /** * testDecodeFooCoded * * @return void */ public function testDecodeFooCoded() { $r = $this->HttpResponse->decodeBody(true); $this->assertEquals(false, $r); $r = $this->HttpResponse->decodeBody('Foobar', false); $this->assertEquals(array('body' => 'Foobar', 'header' => false), $r); $encoding = 'foo-bar'; $sample = array( 'encoded' => '!Foobar!', 'decoded' => array('body' => '!Foobar!', 'header' => false), ); $r = $this->HttpResponse->decodeBody($sample['encoded'], $encoding); $this->assertEquals($r, $sample['decoded']); } /** * testDecodeChunkedBody method * * @return void */ public function testDecodeChunkedBody() { $r = $this->HttpResponse->decodeChunkedBody(true); $this->assertEquals(false, $r); $encoded = "19\r\nThis is a chunked message\r\n0\r\n"; $decoded = "This is a chunked message"; $r = $this->HttpResponse->decodeChunkedBody($encoded); $this->assertEquals($r['body'], $decoded); $this->assertEquals(false, $r['header']); $encoded = "19 \r\nThis is a chunked message\r\n0\r\n"; $r = $this->HttpResponse->decodeChunkedBody($encoded); $this->assertEquals($r['body'], $decoded); $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n0\r\n"; $decoded = "This is a chunked message\nThat is cool\n"; $r = $this->HttpResponse->decodeChunkedBody($encoded); $this->assertEquals($r['body'], $decoded); $this->assertEquals(false, $r['header']); $encoded = "19\r\nThis is a chunked message\r\nE;foo-chunk=5\r\n\nThat is cool\n\r\n0\r\n"; $r = $this->HttpResponse->decodeChunkedBody($encoded); $this->assertEquals($r['body'], $decoded); $this->assertEquals(false, $r['header']); $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n0\r\nfoo-header: bar\r\ncake: PHP\r\n\r\n"; $r = $this->HttpResponse->decodeChunkedBody($encoded); $this->assertEquals($r['body'], $decoded); $this->assertEquals(array('foo-header' => 'bar', 'cake' => 'PHP'), $r['header']); } /** * testDecodeChunkedBodyError method * * @return void */ public function testDecodeChunkedBodyError() { $encoded = "19\r\nThis is a chunked message\r\nE\r\n\nThat is cool\n\r\n"; $result = $this->HttpResponse->decodeChunkedBody($encoded); $expected = "This is a chunked message\nThat is cool\n"; $this->assertEquals($expected, $result['body']); } /** * testParseCookies method * * @return void */ public function testParseCookies() { $header = array( 'Set-Cookie' => array( 'foo=bar', 'people=jim,jack,johnny";";Path=/accounts', 'google=not=nice' ), 'Transfer-Encoding' => 'chunked', 'Date' => 'Sun, 18 Nov 2007 18:57:42 GMT', ); $cookies = $this->HttpResponse->parseCookies($header); $expected = array( 'foo' => array( 'value' => 'bar' ), 'people' => array( 'value' => 'jim,jack,johnny";"', 'path' => '/accounts', ), 'google' => array( 'value' => 'not=nice', ) ); $this->assertEquals($expected, $cookies); $header['Set-Cookie'][] = 'cakephp=great; Secure'; $expected['cakephp'] = array('value' => 'great', 'secure' => true); $cookies = $this->HttpResponse->parseCookies($header); $this->assertEquals($expected, $cookies); $header['Set-Cookie'] = 'foo=bar'; unset($expected['people'], $expected['cakephp'], $expected['google']); $cookies = $this->HttpResponse->parseCookies($header); $this->assertEquals($expected, $cookies); } /** * Test that escaped token strings are properly unescaped by HttpSocket::unescapeToken * * @return void */ public function testUnescapeToken() { $this->assertEquals('Foo', $this->HttpResponse->unescapeToken('Foo')); $escape = $this->HttpResponse->tokenEscapeChars(false); foreach ($escape as $char) { $token = 'My-special-"' . $char . '"-Token'; $unescapedToken = $this->HttpResponse->unescapeToken($token); $expectedToken = 'My-special-' . $char . '-Token'; $this->assertEquals($expectedToken, $unescapedToken, 'Test token unescaping for ASCII ' . ord($char)); } $token = 'Extreme-":"Token-" "-""""@"-test'; $escapedToken = $this->HttpResponse->unescapeToken($token); $expectedToken = 'Extreme-:Token- -"@-test'; $this->assertEquals($expectedToken, $escapedToken); } /** * testArrayAccess * * @return void */ public function testArrayAccess() { $this->HttpResponse->httpVersion = 'HTTP/1.1'; $this->HttpResponse->code = 200; $this->HttpResponse->reasonPhrase = 'OK'; $this->HttpResponse->headers = array( 'Server' => 'CakePHP', 'ContEnt-Type' => 'text/plain' ); $this->HttpResponse->cookies = array( 'foo' => array('value' => 'bar'), 'bar' => array('value' => 'foo') ); $this->HttpResponse->body = 'This is a test!'; $this->HttpResponse->raw = "HTTP/1.1 200 OK\r\nServer: CakePHP\r\nContEnt-Type: text/plain\r\n\r\nThis is a test!"; $expectedOne = "HTTP/1.1 200 OK\r\n"; $this->assertEquals($expectedOne, $this->HttpResponse['raw']['status-line']); $expectedTwo = "Server: CakePHP\r\nContEnt-Type: text/plain\r\n"; $this->assertEquals($expectedTwo, $this->HttpResponse['raw']['header']); $expectedThree = 'This is a test!'; $this->assertEquals($expectedThree, $this->HttpResponse['raw']['body']); $expected = $expectedOne . $expectedTwo . "\r\n" . $expectedThree; $this->assertEquals($expected, $this->HttpResponse['raw']['response']); $expected = 'HTTP/1.1'; $this->assertEquals($expected, $this->HttpResponse['status']['http-version']); $expected = 200; $this->assertEquals($expected, $this->HttpResponse['status']['code']); $expected = 'OK'; $this->assertEquals($expected, $this->HttpResponse['status']['reason-phrase']); $expected = array( 'Server' => 'CakePHP', 'ContEnt-Type' => 'text/plain' ); $this->assertEquals($expected, $this->HttpResponse['header']); $expected = 'This is a test!'; $this->assertEquals($expected, $this->HttpResponse['body']); $expected = array( 'foo' => array('value' => 'bar'), 'bar' => array('value' => 'foo') ); $this->assertEquals($expected, $this->HttpResponse['cookies']); $this->HttpResponse->raw = "HTTP/1.1 200 OK\r\n\r\nThis is a test!"; $this->assertNull($this->HttpResponse['raw']['header']); } } cakephp-2.8.0/lib/Cake/Test/Case/Network/Http/HttpSocketTest.php000066400000000000000000001667161265552240500243770ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Network.Http * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('HttpSocket', 'Network/Http'); App::uses('HttpResponse', 'Network/Http'); /** * TestAuthentication class * * @package Cake.Test.Case.Network.Http */ class TestAuthentication { /** * authentication method * * @param HttpSocket $http A HTTP socket. * @param array &$authInfo Some auth info. * @return void */ public static function authentication(HttpSocket $http, &$authInfo) { $http->request['header']['Authorization'] = 'Test ' . $authInfo['user'] . '.' . $authInfo['pass']; } /** * proxyAuthentication method * * @param HttpSocket $http A HTTP socket. * @param array &$proxyInfo Some proxy info. * @return void */ public static function proxyAuthentication(HttpSocket $http, &$proxyInfo) { $http->request['header']['Proxy-Authorization'] = 'Test ' . $proxyInfo['user'] . '.' . $proxyInfo['pass']; } } /** * CustomResponse */ class CustomResponse { /** * First 10 chars * * @var string */ public $first10; /** * Constructor * * @param string $message A message. */ public function __construct($message) { $this->first10 = substr($message, 0, 10); } } /** * TestHttpSocket */ class TestHttpSocket extends HttpSocket { /** * Convenience method for testing protected method * * @param string|array $uri URI (see {@link _parseUri()}) * @return array Current configuration settings */ public function configUri($uri = null) { return parent::_configUri($uri); } /** * Convenience method for testing protected method * * @param string|array $uri URI to parse * @param bool|array $base If true use default URI config, otherwise indexed array to set 'scheme', 'host', 'port', etc. * @return array Parsed URI */ public function parseUri($uri = null, $base = array()) { return parent::_parseUri($uri, $base); } /** * Convenience method for testing protected method * * @param array $uri A $uri array, or uses $this->config if left empty * @param string $uriTemplate The Uri template/format to use * @return string A fully qualified URL formatted according to $uriTemplate */ public function buildUri($uri = array(), $uriTemplate = '%scheme://%user:%pass@%host:%port/%path?%query#%fragment') { return parent::_buildUri($uri, $uriTemplate); } /** * Convenience method for testing protected method * * @param array $header Header to build * @return string Header built from array */ public function buildHeader($header, $mode = 'standard') { return parent::_buildHeader($header, $mode); } /** * Convenience method for testing protected method * * @param string|array $query A query string to parse into an array or an array to return directly "as is" * @return array The $query parsed into a possibly multi-level array. If an empty $query is given, an empty array is returned. */ public function parseQuery($query) { return parent::_parseQuery($query); } /** * Convenience method for testing protected method * * @param array $request Needs to contain a 'uri' key. Should also contain a 'method' key, otherwise defaults to GET. * @return string Request line */ public function buildRequestLine($request = array()) { return parent::_buildRequestLine($request); } /** * Convenience method for testing protected method * * @param bool $hex true to get them as HEX values, false otherwise * @return array Escape chars */ public function tokenEscapeChars($hex = true, $chars = null) { return parent::_tokenEscapeChars($hex, $chars); } /** * Convenience method for testing protected method * * @param string $token Token to escape * @return string Escaped token */ public function escapeToken($token, $chars = null) { return parent::_escapeToken($token, $chars); } } /** * HttpSocketTest class * * @package Cake.Test.Case.Network.Http */ class HttpSocketTest extends CakeTestCase { /** * Socket property * * @var mixed */ public $Socket = null; /** * RequestSocket property * * @var mixed */ public $RequestSocket = null; /** * This function sets up a TestHttpSocket instance we are going to use for testing * * @return void */ public function setUp() { parent::setUp(); $this->Socket = $this->getMock('TestHttpSocket', array('read', 'write', 'connect')); $this->RequestSocket = $this->getMock('TestHttpSocket', array('read', 'write', 'connect', 'request')); } /** * We use this function to clean up after the test case was executed * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Socket, $this->RequestSocket); } /** * Test that HttpSocket::__construct does what one would expect it to do * * @return void */ public function testConstruct() { $this->Socket->reset(); $baseConfig = $this->Socket->config; $this->Socket->expects($this->never())->method('connect'); $this->Socket->__construct(array('host' => 'foo-bar')); $baseConfig['host'] = 'foo-bar'; $this->assertEquals($this->Socket->config, $baseConfig); $this->Socket->reset(); $baseConfig = $this->Socket->config; $this->Socket->__construct('http://www.cakephp.org:23/'); $baseConfig['host'] = $baseConfig['request']['uri']['host'] = 'www.cakephp.org'; $baseConfig['port'] = $baseConfig['request']['uri']['port'] = 23; $baseConfig['request']['uri']['scheme'] = 'http'; $this->assertEquals($this->Socket->config, $baseConfig); $this->Socket->reset(); $this->Socket->__construct(array('request' => array('uri' => 'http://www.cakephp.org:23/'))); $this->assertEquals($this->Socket->config, $baseConfig); } /** * Test that HttpSocket::configUri works properly with different types of arguments * * @return void */ public function testConfigUri() { $this->Socket->reset(); $r = $this->Socket->configUri('https://bob:secret@www.cakephp.org:23/?query=foo'); $expected = array( 'persistent' => false, 'host' => 'www.cakephp.org', 'protocol' => 'tcp', 'port' => 23, 'timeout' => 30, 'ssl_verify_peer' => true, 'ssl_allow_self_signed' => false, 'ssl_verify_depth' => 5, 'ssl_verify_host' => true, 'request' => array( 'uri' => array( 'scheme' => 'https', 'host' => 'www.cakephp.org', 'port' => 23 ), 'redirect' => false, 'cookies' => array(), ) ); $this->assertEquals($expected, $this->Socket->config); $this->assertTrue($r); $r = $this->Socket->configUri(array('host' => 'www.foo-bar.org')); $expected['host'] = 'www.foo-bar.org'; $expected['request']['uri']['host'] = 'www.foo-bar.org'; $this->assertEquals($expected, $this->Socket->config); $this->assertTrue($r); $r = $this->Socket->configUri('http://www.foo.com'); $expected = array( 'persistent' => false, 'host' => 'www.foo.com', 'protocol' => 'tcp', 'port' => 80, 'timeout' => 30, 'ssl_verify_peer' => true, 'ssl_allow_self_signed' => false, 'ssl_verify_depth' => 5, 'ssl_verify_host' => true, 'request' => array( 'uri' => array( 'scheme' => 'http', 'host' => 'www.foo.com', 'port' => 80 ), 'redirect' => false, 'cookies' => array(), ) ); $this->assertEquals($expected, $this->Socket->config); $this->assertTrue($r); $r = $this->Socket->configUri('/this-is-broken'); $this->assertEquals($expected, $this->Socket->config); $this->assertFalse($r); $r = $this->Socket->configUri(false); $this->assertEquals($expected, $this->Socket->config); $this->assertFalse($r); } /** * Tests that HttpSocket::request (the heart of the HttpSocket) is working properly. * * @return void */ public function testRequest() { $this->Socket->expects($this->any()) ->method('read') ->will($this->returnValue(false)); $this->Socket->reset(); $response = $this->Socket->request(true); $this->assertFalse($response); $tests = array( array( 'request' => 'http://www.cakephp.org/?foo=bar', 'expectation' => array( 'config' => array( 'persistent' => false, 'host' => 'www.cakephp.org', 'protocol' => 'tcp', 'port' => 80, 'timeout' => 30, 'ssl_verify_peer' => true, 'ssl_allow_self_signed' => false, 'ssl_verify_depth' => 5, 'ssl_verify_host' => true, 'request' => array( 'uri' => array( 'scheme' => 'http', 'host' => 'www.cakephp.org', 'port' => 80 ), 'redirect' => false, 'cookies' => array() ) ), 'request' => array( 'method' => 'GET', 'uri' => array( 'scheme' => 'http', 'host' => 'www.cakephp.org', 'port' => 80, 'user' => null, 'pass' => null, 'path' => '/', 'query' => array('foo' => 'bar'), 'fragment' => null ), 'version' => '1.1', 'body' => '', 'line' => "GET /?foo=bar HTTP/1.1\r\n", 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n", 'raw' => "", 'redirect' => false, 'cookies' => array(), 'proxy' => array(), 'auth' => array() ) ) ), array( 'request' => array( 'uri' => array( 'host' => 'www.cakephp.org', 'query' => '?foo=bar' ) ) ), array( 'request' => 'www.cakephp.org/?foo=bar' ), array( 'request' => array( 'host' => '192.168.0.1', 'uri' => 'http://www.cakephp.org/?foo=bar' ), 'expectation' => array( 'request' => array( 'uri' => array('host' => 'www.cakephp.org') ), 'config' => array( 'request' => array( 'uri' => array('host' => 'www.cakephp.org') ), 'host' => '192.168.0.1' ) ) ), 'reset4' => array( 'request.uri.query' => array() ), array( 'request' => array( 'header' => array('Foo@woo' => 'bar-value') ), 'expectation' => array( 'request' => array( 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nFoo\"@\"woo: bar-value\r\n", 'line' => "GET / HTTP/1.1\r\n" ) ) ), array( 'request' => array('header' => array('Foo@woo' => 'bar-value', 'host' => 'foo.com'), 'uri' => 'http://www.cakephp.org/'), 'expectation' => array( 'request' => array( 'header' => "Host: foo.com\r\nConnection: close\r\nUser-Agent: CakePHP\r\nFoo\"@\"woo: bar-value\r\n" ), 'config' => array( 'host' => 'www.cakephp.org' ) ) ), array( 'request' => array('header' => "Foo: bar\r\n"), 'expectation' => array( 'request' => array( 'header' => "Foo: bar\r\n" ) ) ), array( 'request' => array('header' => "Foo: bar\r\n", 'uri' => 'http://www.cakephp.org/search?q=http_socket#ignore-me'), 'expectation' => array( 'request' => array( 'uri' => array( 'path' => '/search', 'query' => array('q' => 'http_socket'), 'fragment' => 'ignore-me' ), 'line' => "GET /search?q=http_socket HTTP/1.1\r\n" ) ) ), 'reset8' => array( 'request.uri.query' => array() ), array( 'request' => array( 'method' => 'POST', 'uri' => 'http://www.cakephp.org/posts/add', 'body' => array( 'name' => 'HttpSocket-is-released', 'date' => 'today' ) ), 'expectation' => array( 'request' => array( 'method' => 'POST', 'uri' => array( 'path' => '/posts/add', 'fragment' => null ), 'body' => "name=HttpSocket-is-released&date=today", 'line' => "POST /posts/add HTTP/1.1\r\n", 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n", 'raw' => "name=HttpSocket-is-released&date=today" ) ) ), array( 'request' => array( 'method' => 'POST', 'uri' => 'http://www.cakephp.org:8080/posts/add', 'body' => array( 'name' => 'HttpSocket-is-released', 'date' => 'today' ) ), 'expectation' => array( 'config' => array( 'port' => 8080, 'request' => array( 'uri' => array( 'port' => 8080 ) ) ), 'request' => array( 'uri' => array( 'port' => 8080 ), 'header' => "Host: www.cakephp.org:8080\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n" ) ) ), 'reset10' => array( 'config.protocol' => 'ssl' ), array( 'request' => array( 'method' => 'POST', 'uri' => 'https://www.cakephp.org/posts/add', 'body' => array( 'name' => 'HttpSocket-is-released', 'date' => 'today' ) ), 'expectation' => array( 'config' => array( 'port' => 443, 'request' => array( 'uri' => array( 'scheme' => 'https', 'port' => 443 ) ) ), 'request' => array( 'uri' => array( 'scheme' => 'https', 'port' => 443 ), 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\n" ) ) ), 'reset11' => array( 'config.protocol' => 'ssl' ), array( 'request' => array( 'version' => '1.0', 'method' => 'POST', 'uri' => 'https://www.cakephp.org/posts/add', 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today'), 'cookies' => array('foo' => array('value' => 'bar')) ), 'expectation' => array( 'request' => array( 'version' => '1.0', 'line' => "POST /posts/add HTTP/1.0\r\n", 'header' => "Host: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 38\r\nCookie: foo=bar\r\n", 'cookies' => array( 'foo' => array('value' => 'bar'), ) ) ) ) ); $expectation = array(); foreach ($tests as $i => $test) { if (strpos($i, 'reset') === 0) { foreach ($test as $path => $val) { $expectation = Hash::insert($expectation, $path, $val); } continue; } if (isset($test['expectation'])) { $expectation = Hash::merge($expectation, $test['expectation']); } $this->Socket->request($test['request']); $raw = $expectation['request']['raw']; $expectation['request']['raw'] = $expectation['request']['line'] . $expectation['request']['header'] . "\r\n" . $raw; $r = array('config' => $this->Socket->config, 'request' => $this->Socket->request); $this->assertEquals($r, $expectation, 'Failed test #' . $i . ' '); $expectation['request']['raw'] = $raw; } $this->Socket->reset(); $request = array('method' => 'POST', 'uri' => 'http://www.cakephp.org/posts/add', 'body' => array('name' => 'HttpSocket-is-released', 'date' => 'today')); $this->Socket->request($request); $this->assertEquals("name=HttpSocket-is-released&date=today", $this->Socket->request['body']); } /** * Test the scheme + port keys * * @return void */ public function testGetWithSchemeAndPort() { $this->Socket->expects($this->any()) ->method('read') ->will($this->returnValue(false)); $this->Socket->reset(); $request = array( 'uri' => array( 'scheme' => 'http', 'host' => 'cakephp.org', 'port' => 8080, 'path' => '/', ), 'method' => 'GET' ); $this->Socket->request($request); $this->assertContains('Host: cakephp.org:8080', $this->Socket->request['header']); } /** * Test URLs like http://cakephp.org/index.php?somestring without key/value pair for query * * @return void */ public function testRequestWithStringQuery() { $this->Socket->expects($this->any()) ->method('read') ->will($this->returnValue(false)); $this->Socket->reset(); $request = array( 'uri' => array( 'scheme' => 'http', 'host' => 'cakephp.org', 'path' => 'index.php', 'query' => 'somestring' ), 'method' => 'GET' ); $this->Socket->request($request); $this->assertContains("GET /index.php?somestring HTTP/1.1", $this->Socket->request['line']); } /** * The "*" asterisk character is only allowed for the following methods: OPTIONS. * * @expectedException SocketException * @return void */ public function testRequestNotAllowedUri() { $this->Socket->reset(); $request = array('uri' => '*', 'method' => 'GET'); $this->Socket->request($request); } /** * testRequest2 method * * @return void */ public function testRequest2() { $this->Socket->reset(); $request = array('uri' => 'htpp://www.cakephp.org/'); $number = mt_rand(0, 9999999); $this->Socket->expects($this->any())->method('connect')->will($this->returnValue(true)); $serverResponse = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

Hello, your lucky number is " . $number . "

"; $this->Socket->expects($this->at(0))->method('write') ->with("GET / HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n\r\n"); $this->Socket->expects($this->any()) ->method('read') ->will($this->onConsecutiveCalls($serverResponse, false)); $response = (string)$this->Socket->request($request); $this->assertEquals($response, "

Hello, your lucky number is " . $number . "

"); } /** * testRequest3 method * * @return void */ public function testRequest3() { $request = array('uri' => 'htpp://www.cakephp.org/'); $serverResponse = "HTTP/1.x 200 OK\r\nSet-Cookie: foo=bar\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

This is a cookie test!

"; $this->Socket->expects($this->any()) ->method('read') ->will($this->onConsecutiveCalls($serverResponse, false)); $this->Socket->connected = true; $this->Socket->request($request); $result = $this->Socket->response['cookies']; $expected = array( 'foo' => array( 'value' => 'bar' ) ); $this->assertEquals($expected, $result); $this->assertEquals($expected, $this->Socket->config['request']['cookies']['www.cakephp.org']); $this->assertFalse($this->Socket->connected); } /** * testRequestWithConstructor method * * @return void */ public function testRequestWithConstructor() { $request = array( 'request' => array( 'uri' => array( 'scheme' => 'http', 'host' => 'localhost', 'port' => '5984', 'user' => null, 'pass' => null ) ) ); $http = $this->getMock('TestHttpSocket', array('read', 'write', 'connect', 'request'), array($request)); $expected = array('method' => 'GET', 'uri' => '/_test'); $http->expects($this->at(0))->method('request')->with($expected); $http->get('/_test'); $expected = array('method' => 'GET', 'uri' => 'http://localhost:5984/_test?count=4'); $http->expects($this->at(0))->method('request')->with($expected); $http->get('/_test', array('count' => 4)); } /** * testRequestWithResource * * @return void */ public function testRequestWithResource() { $serverResponse = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

This is a test!

"; $this->Socket->expects($this->any()) ->method('read') ->will($this->onConsecutiveCalls($serverResponse, false, $serverResponse, false)); $this->Socket->connected = true; $f = fopen(TMP . 'download.txt', 'w'); if (!$f) { $this->markTestSkipped('Can not write in TMP directory.'); } $this->Socket->setContentResource($f); $result = (string)$this->Socket->request('http://www.cakephp.org/'); $this->assertEquals('', $result); $this->assertEquals('CakeHttp Server', $this->Socket->response['header']['Server']); fclose($f); $this->assertEquals(file_get_contents(TMP . 'download.txt'), '

This is a test!

'); unlink(TMP . 'download.txt'); $this->Socket->setContentResource(false); $result = (string)$this->Socket->request('http://www.cakephp.org/'); $this->assertEquals('

This is a test!

', $result); } /** * testRequestWithCrossCookie * * @return void */ public function testRequestWithCrossCookie() { $this->Socket->connected = true; $this->Socket->config['request']['cookies'] = array(); $serverResponse = "HTTP/1.x 200 OK\r\nSet-Cookie: foo=bar\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

This is a test!

"; $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); $expected = array('www.cakephp.org' => array('foo' => array('value' => 'bar'))); $this->Socket->request('http://www.cakephp.org/'); $this->assertEquals($expected, $this->Socket->config['request']['cookies']); $serverResponse = "HTTP/1.x 200 OK\r\nSet-Cookie: bar=foo\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

This is a test!

"; $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); $this->Socket->request('http://www.cakephp.org/other'); $this->assertEquals(array('foo' => array('value' => 'bar')), $this->Socket->request['cookies']); $expected['www.cakephp.org'] += array('bar' => array('value' => 'foo')); $this->assertEquals($expected, $this->Socket->config['request']['cookies']); $serverResponse = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

This is a test!

"; $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); $this->Socket->request('/other2'); $this->assertEquals($expected, $this->Socket->config['request']['cookies']); $serverResponse = "HTTP/1.x 200 OK\r\nSet-Cookie: foobar=ok\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

This is a test!

"; $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); $this->Socket->request('http://www.cake.com'); $this->assertTrue(empty($this->Socket->request['cookies'])); $expected['www.cake.com'] = array('foobar' => array('value' => 'ok')); $this->assertEquals($expected, $this->Socket->config['request']['cookies']); } /** * testRequestCustomResponse * * @return void */ public function testRequestCustomResponse() { $this->Socket->connected = true; $serverResponse = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

This is a test!

"; $this->Socket->expects($this->any()) ->method('read') ->will($this->onConsecutiveCalls($serverResponse, false)); $this->Socket->responseClass = 'CustomResponse'; $response = $this->Socket->request('http://www.cakephp.org/'); $this->assertInstanceOf('CustomResponse', $response); $this->assertEquals('HTTP/1.x 2', $response->first10); } /** * Test that redirect URLs are urldecoded * * @return void */ public function testRequestWithRedirectUrlEncoded() { $request = array( 'uri' => 'http://localhost/oneuri', 'redirect' => 1 ); $serverResponse1 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://i.cmpnet.com%2Ftechonline%2Fpdf%2Fa+b.pdf=\r\n\r\n"; $serverResponse2 = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

You have been redirected

"; $this->Socket->expects($this->at(1)) ->method('read') ->will($this->returnValue($serverResponse1)); $this->Socket->expects($this->at(3)) ->method('write') ->with($this->logicalAnd( $this->stringContains('Host: i.cmpnet.com'), $this->stringContains('GET /techonline/pdf/a+b.pdf') )); $this->Socket->expects($this->at(4)) ->method('read') ->will($this->returnValue($serverResponse2)); $this->Socket->expects($this->any()) ->method('read')->will($this->returnValue(false)); $response = $this->Socket->request($request); $this->assertEquals('

You have been redirected

', $response->body()); } /** * testRequestWithRedirect method * * @return void */ public function testRequestWithRedirectAsTrue() { $request = array( 'uri' => 'http://localhost/oneuri', 'redirect' => true ); $serverResponse1 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://localhost/anotheruri\r\n\r\n"; $serverResponse2 = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

You have been redirected

"; $this->Socket->expects($this->any()) ->method('read') ->will($this->onConsecutiveCalls($serverResponse1, false, $serverResponse2, false)); $response = $this->Socket->request($request); $this->assertEquals('

You have been redirected

', $response->body()); } /** * Test that redirects with a count limit are decremented. * * @return void */ public function testRequestWithRedirectAsInt() { $request = array( 'uri' => 'http://localhost/oneuri', 'redirect' => 2 ); $serverResponse1 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://localhost/anotheruri\r\n\r\n"; $serverResponse2 = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

You have been redirected

"; $this->Socket->expects($this->any()) ->method('read') ->will($this->onConsecutiveCalls($serverResponse1, false, $serverResponse2, false)); $this->Socket->request($request); $this->assertEquals(1, $this->Socket->request['redirect']); } /** * Test that redirects after the redirect count reaches 9 are not followed. * * @return void */ public function testRequestWithRedirectAsIntReachingZero() { $request = array( 'uri' => 'http://localhost/oneuri', 'redirect' => 1 ); $serverResponse1 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://localhost/oneruri\r\n\r\n"; $serverResponse2 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://localhost/anotheruri\r\n\r\n"; $this->Socket->expects($this->any()) ->method('read') ->will($this->onConsecutiveCalls($serverResponse1, false, $serverResponse2, false)); $response = $this->Socket->request($request); $this->assertEquals(0, $this->Socket->request['redirect']); $this->assertEquals(302, $response->code); $this->assertEquals('http://localhost/anotheruri', $response->getHeader('Location')); } /** * testProxy method * * @return void */ public function testProxy() { $this->Socket->reset(); $this->Socket->expects($this->any())->method('connect')->will($this->returnValue(true)); $this->Socket->expects($this->any())->method('read')->will($this->returnValue(false)); $this->Socket->configProxy('proxy.server', 123); $expected = "GET http://www.cakephp.org/ HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n\r\n"; $this->Socket->request('http://www.cakephp.org/'); $this->assertEquals($expected, $this->Socket->request['raw']); $this->assertEquals('proxy.server', $this->Socket->config['host']); $this->assertEquals(123, $this->Socket->config['port']); $expected = array( 'host' => 'proxy.server', 'port' => 123, 'method' => null, 'user' => null, 'pass' => null ); $this->assertEquals($expected, $this->Socket->request['proxy']); $expected = "GET http://www.cakephp.org/bakery HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n\r\n"; $this->Socket->request('/bakery'); $this->assertEquals($expected, $this->Socket->request['raw']); $this->assertEquals('proxy.server', $this->Socket->config['host']); $this->assertEquals(123, $this->Socket->config['port']); $expected = array( 'host' => 'proxy.server', 'port' => 123, 'method' => null, 'user' => null, 'pass' => null ); $this->assertEquals($expected, $this->Socket->request['proxy']); $expected = "GET http://www.cakephp.org/ HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nProxy-Authorization: Test mark.secret\r\n\r\n"; $this->Socket->configProxy('proxy.server', 123, 'Test', 'mark', 'secret'); $this->Socket->request('http://www.cakephp.org/'); $this->assertEquals($expected, $this->Socket->request['raw']); $this->assertEquals('proxy.server', $this->Socket->config['host']); $this->assertEquals(123, $this->Socket->config['port']); $expected = array( 'host' => 'proxy.server', 'port' => 123, 'method' => 'Test', 'user' => 'mark', 'pass' => 'secret' ); $this->assertEquals($expected, $this->Socket->request['proxy']); $this->Socket->configAuth('Test', 'login', 'passwd'); $expected = "GET http://www.cakephp.org/ HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\nProxy-Authorization: Test mark.secret\r\nAuthorization: Test login.passwd\r\n\r\n"; $this->Socket->request('http://www.cakephp.org/'); $this->assertEquals($expected, $this->Socket->request['raw']); $expected = array( 'host' => 'proxy.server', 'port' => 123, 'method' => 'Test', 'user' => 'mark', 'pass' => 'secret' ); $this->assertEquals($expected, $this->Socket->request['proxy']); $expected = array( 'Test' => array( 'user' => 'login', 'pass' => 'passwd' ) ); $this->assertEquals($expected, $this->Socket->request['auth']); } /** * testUrl method * * @return void */ public function testUrl() { $this->Socket->reset(true); $this->assertEquals(false, $this->Socket->url(true)); $url = $this->Socket->url('www.cakephp.org'); $this->assertEquals('http://www.cakephp.org/', $url); $url = $this->Socket->url('https://www.cakephp.org/posts/add'); $this->assertEquals('https://www.cakephp.org/posts/add', $url); $url = $this->Socket->url('http://www.cakephp/search?q=socket', '/%path?%query'); $this->assertEquals('/search?q=socket', $url); $this->Socket->config['request']['uri']['host'] = 'bakery.cakephp.org'; $url = $this->Socket->url(); $this->assertEquals('http://bakery.cakephp.org/', $url); $this->Socket->configUri('http://www.cakephp.org'); $url = $this->Socket->url('/search?q=bar'); $this->assertEquals('http://www.cakephp.org/search?q=bar', $url); $url = $this->Socket->url(array('host' => 'www.foobar.org', 'query' => array('q' => 'bar'))); $this->assertEquals('http://www.foobar.org/?q=bar', $url); $url = $this->Socket->url(array('path' => '/supersearch', 'query' => array('q' => 'bar'))); $this->assertEquals('http://www.cakephp.org/supersearch?q=bar', $url); $this->Socket->configUri('http://www.google.com'); $url = $this->Socket->url('/search?q=socket'); $this->assertEquals('http://www.google.com/search?q=socket', $url); $url = $this->Socket->url(); $this->assertEquals('http://www.google.com/', $url); $this->Socket->configUri('https://www.google.com'); $url = $this->Socket->url('/search?q=socket'); $this->assertEquals('https://www.google.com/search?q=socket', $url); $this->Socket->reset(); $this->Socket->configUri('www.google.com:443'); $url = $this->Socket->url('/search?q=socket'); $this->assertEquals('https://www.google.com/search?q=socket', $url); $this->Socket->reset(); $this->Socket->configUri('www.google.com:8080'); $url = $this->Socket->url('/search?q=socket'); $this->assertEquals('http://www.google.com:8080/search?q=socket', $url); } /** * testGet method * * @return void */ public function testGet() { $this->RequestSocket->reset(); $this->RequestSocket->expects($this->at(0)) ->method('request') ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/')); $this->RequestSocket->expects($this->at(1)) ->method('request') ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/?foo=bar')); $this->RequestSocket->expects($this->at(2)) ->method('request') ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/?foo=bar')); $this->RequestSocket->expects($this->at(3)) ->method('request') ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/?foo=23&foobar=42')); $this->RequestSocket->expects($this->at(4)) ->method('request') ->with(array('method' => 'GET', 'uri' => 'http://www.google.com/', 'version' => '1.0')); $this->RequestSocket->expects($this->at(5)) ->method('request') ->with(array('method' => 'GET', 'uri' => 'https://secure.example.com/test.php?one=two')); $this->RequestSocket->expects($this->at(6)) ->method('request') ->with(array('method' => 'GET', 'uri' => 'https://example.com/oauth/access?clientid=123&redirect_uri=http%3A%2F%2Fexample.com&code=456')); $this->RequestSocket->get('http://www.google.com/'); $this->RequestSocket->get('http://www.google.com/', array('foo' => 'bar')); $this->RequestSocket->get('http://www.google.com/', 'foo=bar'); $this->RequestSocket->get('http://www.google.com/?foo=bar', array('foobar' => '42', 'foo' => '23')); $this->RequestSocket->get('http://www.google.com/', null, array('version' => '1.0')); $this->RequestSocket->get('https://secure.example.com/test.php', array('one' => 'two')); $this->RequestSocket->get('https://example.com/oauth/access', array( 'clientid' => '123', 'redirect_uri' => 'http://example.com', 'code' => 456 )); } /** * Test the head method * * @return void */ public function testHead() { $this->RequestSocket->reset(); $this->RequestSocket->expects($this->at(0)) ->method('request') ->with(array('method' => 'HEAD', 'uri' => 'http://www.google.com/')); $this->RequestSocket->expects($this->at(1)) ->method('request') ->with(array('method' => 'HEAD', 'uri' => 'http://www.google.com/?foo=bar')); $this->RequestSocket->expects($this->at(2)) ->method('request') ->with(array('method' => 'HEAD', 'uri' => 'http://www.google.com/?foo=bar')); $this->RequestSocket->expects($this->at(3)) ->method('request') ->with(array('method' => 'HEAD', 'uri' => 'http://www.google.com/?foo=23&foobar=42')); $this->RequestSocket->expects($this->at(4)) ->method('request') ->with(array('method' => 'HEAD', 'uri' => 'http://www.google.com/', 'version' => '1.0')); $this->RequestSocket->expects($this->at(5)) ->method('request') ->with(array('method' => 'HEAD', 'uri' => 'https://secure.example.com/test.php?one=two')); $this->RequestSocket->expects($this->at(6)) ->method('request') ->with(array('method' => 'HEAD', 'uri' => 'https://example.com/oauth/access?clientid=123&redirect_uri=http%3A%2F%2Fexample.com&code=456')); $this->RequestSocket->head('http://www.google.com/'); $this->RequestSocket->head('http://www.google.com/', array('foo' => 'bar')); $this->RequestSocket->head('http://www.google.com/', 'foo=bar'); $this->RequestSocket->head('http://www.google.com/?foo=bar', array('foobar' => '42', 'foo' => '23')); $this->RequestSocket->head('http://www.google.com/', null, array('version' => '1.0')); $this->RequestSocket->head('https://secure.example.com/test.php', array('one' => 'two')); $this->RequestSocket->head('https://example.com/oauth/access', array( 'clientid' => '123', 'redirect_uri' => 'http://example.com', 'code' => 456 )); } /** * Test authentication * * @return void */ public function testAuth() { $this->Socket->expects($this->any()) ->method('read')->will($this->returnValue(false)); $this->Socket->get('http://mark:secret@example.com/test'); $this->assertTrue(strpos($this->Socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false); $this->Socket->configAuth(false); $this->Socket->get('http://example.com/test'); $this->assertFalse(strpos($this->Socket->request['header'], 'Authorization:')); $this->Socket->configAuth('Test', 'mark', 'passwd'); $this->Socket->get('http://example.com/test'); $this->assertTrue(strpos($this->Socket->request['header'], 'Authorization: Test mark.passwd') !== false); $this->Socket->configAuth(false); $this->Socket->request(array( 'method' => 'GET', 'uri' => 'http://example.com/test', 'auth' => array( 'method' => 'Basic', 'user' => 'joel', 'pass' => 'hunter2' ) )); $this->assertEquals($this->Socket->request['auth'], array('Basic' => array('user' => 'joel', 'pass' => 'hunter2'))); $this->assertTrue(strpos($this->Socket->request['header'], 'Authorization: Basic am9lbDpodW50ZXIy') !== false); $this->Socket->configAuth('Basic', 'mark', 'password'); $this->Socket->request(array( 'method' => 'GET', 'uri' => 'http://example.com/test', 'header' => array( 'Authorization' => 'OtherAuth Hi.There' ) )); $this->assertPattern('/Authorization: OtherAuth Hi\.There/m', $this->Socket->request['header']); } /** * test that two consecutive get() calls reset the authentication credentials. * * @return void */ public function testConsecutiveGetResetsAuthCredentials() { $this->Socket->expects($this->any()) ->method('read')->will($this->returnValue(false)); $this->Socket->get('http://mark:secret@example.com/test'); $this->assertEquals('mark', $this->Socket->request['uri']['user']); $this->assertEquals('secret', $this->Socket->request['uri']['pass']); $this->assertTrue(strpos($this->Socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false); $this->Socket->get('/test2'); $this->assertTrue(strpos($this->Socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false); $this->Socket->request(array( 'method' => 'GET', 'uri' => 'http://example.com/test', 'header' => array( 'Authorization' => 'OtherAuth Hi.There' ) )); $this->assertPattern('/Authorization: OtherAuth Hi\.There/m', $this->Socket->request['header']); $this->Socket->get('/test3'); $this->assertTrue(strpos($this->Socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false); } /** * testPostPutDelete method * * @return void */ public function testPost() { $this->RequestSocket->reset(); $this->RequestSocket->expects($this->at(0)) ->method('request') ->with(array('method' => 'POST', 'uri' => 'http://www.google.com/', 'body' => array())); $this->RequestSocket->expects($this->at(1)) ->method('request') ->with(array('method' => 'POST', 'uri' => 'http://www.google.com/', 'body' => array('Foo' => 'bar'))); $this->RequestSocket->expects($this->at(2)) ->method('request') ->with(array('method' => 'POST', 'uri' => 'http://www.google.com/', 'body' => null, 'line' => 'Hey Server')); $this->RequestSocket->post('http://www.google.com/'); $this->RequestSocket->post('http://www.google.com/', array('Foo' => 'bar')); $this->RequestSocket->post('http://www.google.com/', null, array('line' => 'Hey Server')); } /** * testPut * * @return void */ public function testPut() { $this->RequestSocket->reset(); $this->RequestSocket->expects($this->at(0)) ->method('request') ->with(array('method' => 'PUT', 'uri' => 'http://www.google.com/', 'body' => array())); $this->RequestSocket->expects($this->at(1)) ->method('request') ->with(array('method' => 'PUT', 'uri' => 'http://www.google.com/', 'body' => array('Foo' => 'bar'))); $this->RequestSocket->expects($this->at(2)) ->method('request') ->with(array('method' => 'PUT', 'uri' => 'http://www.google.com/', 'body' => null, 'line' => 'Hey Server')); $this->RequestSocket->put('http://www.google.com/'); $this->RequestSocket->put('http://www.google.com/', array('Foo' => 'bar')); $this->RequestSocket->put('http://www.google.com/', null, array('line' => 'Hey Server')); } /** * testPatch * * @return void */ public function testPatch() { $this->RequestSocket->reset(); $this->RequestSocket->expects($this->at(0)) ->method('request') ->with(array('method' => 'PATCH', 'uri' => 'http://www.google.com/', 'body' => array())); $this->RequestSocket->expects($this->at(1)) ->method('request') ->with(array('method' => 'PATCH', 'uri' => 'http://www.google.com/', 'body' => array('Foo' => 'bar'))); $this->RequestSocket->expects($this->at(2)) ->method('request') ->with(array('method' => 'PATCH', 'uri' => 'http://www.google.com/', 'body' => null, 'line' => 'Hey Server')); $this->RequestSocket->patch('http://www.google.com/'); $this->RequestSocket->patch('http://www.google.com/', array('Foo' => 'bar')); $this->RequestSocket->patch('http://www.google.com/', null, array('line' => 'Hey Server')); } /** * testDelete * * @return void */ public function testDelete() { $this->RequestSocket->reset(); $this->RequestSocket->expects($this->at(0)) ->method('request') ->with(array('method' => 'DELETE', 'uri' => 'http://www.google.com/', 'body' => array())); $this->RequestSocket->expects($this->at(1)) ->method('request') ->with(array('method' => 'DELETE', 'uri' => 'http://www.google.com/', 'body' => array('Foo' => 'bar'))); $this->RequestSocket->expects($this->at(2)) ->method('request') ->with(array('method' => 'DELETE', 'uri' => 'http://www.google.com/', 'body' => null, 'line' => 'Hey Server')); $this->RequestSocket->delete('http://www.google.com/'); $this->RequestSocket->delete('http://www.google.com/', array('Foo' => 'bar')); $this->RequestSocket->delete('http://www.google.com/', null, array('line' => 'Hey Server')); } /** * testBuildRequestLine method * * @return void */ public function testBuildRequestLine() { $this->Socket->reset(); $this->Socket->quirksMode = true; $r = $this->Socket->buildRequestLine('Foo'); $this->assertEquals('Foo', $r); $this->Socket->quirksMode = false; $r = $this->Socket->buildRequestLine(true); $this->assertEquals(false, $r); $r = $this->Socket->buildRequestLine(array('foo' => 'bar', 'method' => 'foo')); $this->assertEquals(false, $r); $r = $this->Socket->buildRequestLine(array('method' => 'GET', 'uri' => 'http://www.cakephp.org/search?q=socket')); $this->assertEquals("GET /search?q=socket HTTP/1.1\r\n", $r); $request = array( 'method' => 'GET', 'uri' => array( 'path' => '/search', 'query' => array('q' => 'socket') ) ); $r = $this->Socket->buildRequestLine($request); $this->assertEquals("GET /search?q=socket HTTP/1.1\r\n", $r); unset($request['method']); $r = $this->Socket->buildRequestLine($request); $this->assertEquals("GET /search?q=socket HTTP/1.1\r\n", $r); $request = array('method' => 'OPTIONS', 'uri' => '*'); $r = $this->Socket->buildRequestLine($request); $this->assertEquals("OPTIONS * HTTP/1.1\r\n", $r); $request['method'] = 'GET'; $this->Socket->quirksMode = true; $r = $this->Socket->buildRequestLine($request); $this->assertEquals("GET * HTTP/1.1\r\n", $r); $r = $this->Socket->buildRequestLine("GET * HTTP/1.1\r\n"); $this->assertEquals("GET * HTTP/1.1\r\n", $r); $request = array( 'version' => '1.0', 'method' => 'GET', 'uri' => array( 'path' => '/search', 'query' => array('q' => 'socket') ) ); $r = $this->Socket->buildRequestLine($request); $this->assertEquals("GET /search?q=socket HTTP/1.0\r\n", $r); } /** * testBadBuildRequestLine method * * @expectedException SocketException * @return void */ public function testBadBuildRequestLine() { $this->Socket->buildRequestLine('Foo'); } /** * testBadBuildRequestLine2 method * * @expectedException SocketException * @return void */ public function testBadBuildRequestLine2() { $this->Socket->buildRequestLine("GET * HTTP/1.1\r\n"); } /** * Asserts that HttpSocket::parseUri is working properly * * @return void */ public function testParseUri() { $this->Socket->reset(); $uri = $this->Socket->parseUri(array('invalid' => 'uri-string')); $this->assertEquals(false, $uri); $uri = $this->Socket->parseUri(array('invalid' => 'uri-string'), array('host' => 'somehost')); $this->assertEquals(array('host' => 'somehost', 'invalid' => 'uri-string'), $uri); $uri = $this->Socket->parseUri(false); $this->assertEquals(false, $uri); $uri = $this->Socket->parseUri('/my-cool-path'); $this->assertEquals(array('path' => '/my-cool-path'), $uri); $uri = $this->Socket->parseUri('http://bob:foo123@www.cakephp.org:40/search?q=dessert#results'); $this->assertEquals($uri, array( 'scheme' => 'http', 'host' => 'www.cakephp.org', 'port' => 40, 'user' => 'bob', 'pass' => 'foo123', 'path' => '/search', 'query' => array('q' => 'dessert'), 'fragment' => 'results' )); $uri = $this->Socket->parseUri('http://www.cakephp.org/'); $this->assertEquals($uri, array( 'scheme' => 'http', 'host' => 'www.cakephp.org', 'path' => '/' )); $uri = $this->Socket->parseUri('http://www.cakephp.org', true); $this->assertEquals($uri, array( 'scheme' => 'http', 'host' => 'www.cakephp.org', 'port' => 80, 'user' => null, 'pass' => null, 'path' => '/', 'query' => array(), 'fragment' => null )); $uri = $this->Socket->parseUri('https://www.cakephp.org', true); $this->assertEquals($uri, array( 'scheme' => 'https', 'host' => 'www.cakephp.org', 'port' => 443, 'user' => null, 'pass' => null, 'path' => '/', 'query' => array(), 'fragment' => null )); $uri = $this->Socket->parseUri('www.cakephp.org:443/query?foo', true); $this->assertEquals($uri, array( 'scheme' => 'https', 'host' => 'www.cakephp.org', 'port' => 443, 'user' => null, 'pass' => null, 'path' => '/query', 'query' => array('foo' => ""), 'fragment' => null )); $uri = $this->Socket->parseUri('http://www.cakephp.org', array('host' => 'piephp.org', 'user' => 'bob', 'fragment' => 'results')); $this->assertEquals($uri, array( 'host' => 'www.cakephp.org', 'user' => 'bob', 'fragment' => 'results', 'scheme' => 'http' )); $uri = $this->Socket->parseUri('https://www.cakephp.org', array('scheme' => 'http', 'port' => 23)); $this->assertEquals($uri, array( 'scheme' => 'https', 'port' => 23, 'host' => 'www.cakephp.org' )); $uri = $this->Socket->parseUri('www.cakephp.org:59', array('scheme' => array('http', 'https'), 'port' => 80)); $this->assertEquals($uri, array( 'scheme' => 'http', 'port' => 59, 'host' => 'www.cakephp.org' )); $uri = $this->Socket->parseUri(array('scheme' => 'http', 'host' => 'www.google.com', 'port' => 8080), array('scheme' => array('http', 'https'), 'host' => 'www.google.com', 'port' => array(80, 443))); $this->assertEquals($uri, array( 'scheme' => 'http', 'host' => 'www.google.com', 'port' => 8080 )); $uri = $this->Socket->parseUri('http://www.cakephp.org/?param1=value1¶m2=value2%3Dvalue3'); $this->assertEquals($uri, array( 'scheme' => 'http', 'host' => 'www.cakephp.org', 'path' => '/', 'query' => array( 'param1' => 'value1', 'param2' => 'value2=value3' ) )); $uri = $this->Socket->parseUri('http://www.cakephp.org/?param1=value1¶m2=value2=value3'); $this->assertEquals($uri, array( 'scheme' => 'http', 'host' => 'www.cakephp.org', 'path' => '/', 'query' => array( 'param1' => 'value1', 'param2' => 'value2=value3' ) )); } /** * Tests that HttpSocket::buildUri can turn all kinds of uri arrays (and strings) into fully or partially qualified URI's * * @return void */ public function testBuildUri() { $this->Socket->reset(); $r = $this->Socket->buildUri(true); $this->assertEquals(false, $r); $r = $this->Socket->buildUri('foo.com'); $this->assertEquals('http://foo.com/', $r); $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org')); $this->assertEquals('http://www.cakephp.org/', $r); $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'scheme' => 'https')); $this->assertEquals('https://www.cakephp.org/', $r); $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'port' => 23)); $this->assertEquals('http://www.cakephp.org:23/', $r); $r = $this->Socket->buildUri(array('path' => 'www.google.com/search', 'query' => 'q=cakephp')); $this->assertEquals('http://www.google.com/search?q=cakephp', $r); $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'scheme' => 'https', 'port' => 79)); $this->assertEquals('https://www.cakephp.org:79/', $r); $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'path' => 'foo')); $this->assertEquals('http://www.cakephp.org/foo', $r); $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'path' => '/foo')); $this->assertEquals('http://www.cakephp.org/foo', $r); $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'path' => '/search', 'query' => array('q' => 'HttpSocket'))); $this->assertEquals('http://www.cakephp.org/search?q=HttpSocket', $r); $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'fragment' => 'bar')); $this->assertEquals('http://www.cakephp.org/#bar', $r); $r = $this->Socket->buildUri(array( 'scheme' => 'https', 'host' => 'www.cakephp.org', 'port' => 25, 'user' => 'bob', 'pass' => 'secret', 'path' => '/cool', 'query' => array('foo' => 'bar'), 'fragment' => 'comment' )); $this->assertEquals('https://bob:secret@www.cakephp.org:25/cool?foo=bar#comment', $r); $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org', 'fragment' => 'bar'), '%fragment?%host'); $this->assertEquals('bar?www.cakephp.org', $r); $r = $this->Socket->buildUri(array('host' => 'www.cakephp.org'), '%fragment???%host'); $this->assertEquals('???www.cakephp.org', $r); $r = $this->Socket->buildUri(array('path' => '*'), '/%path?%query'); $this->assertEquals('*', $r); $r = $this->Socket->buildUri(array('scheme' => 'foo', 'host' => 'www.cakephp.org')); $this->assertEquals('foo://www.cakephp.org:80/', $r); } /** * Asserts that HttpSocket::parseQuery is working properly * * @return void */ public function testParseQuery() { $this->Socket->reset(); $query = $this->Socket->parseQuery(array('framework' => 'cakephp')); $this->assertEquals(array('framework' => 'cakephp'), $query); $query = $this->Socket->parseQuery(''); $this->assertEquals(array(), $query); $query = $this->Socket->parseQuery('framework=cakephp'); $this->assertEquals(array('framework' => 'cakephp'), $query); $query = $this->Socket->parseQuery('?framework=cakephp'); $this->assertEquals(array('framework' => 'cakephp'), $query); $query = $this->Socket->parseQuery('a&b&c'); $this->assertEquals(array('a' => '', 'b' => '', 'c' => ''), $query); $query = $this->Socket->parseQuery('value=12345'); $this->assertEquals(array('value' => '12345'), $query); $query = $this->Socket->parseQuery('a[0]=foo&a[1]=bar&a[2]=cake'); $this->assertEquals(array('a' => array(0 => 'foo', 1 => 'bar', 2 => 'cake')), $query); $query = $this->Socket->parseQuery('a[]=foo&a[]=bar&a[]=cake'); $this->assertEquals(array('a' => array(0 => 'foo', 1 => 'bar', 2 => 'cake')), $query); $query = $this->Socket->parseQuery('a[][]=foo&a[][]=bar&a[][]=cake'); $expectedQuery = array( 'a' => array( 0 => array( 0 => 'foo' ), 1 => array( 0 => 'bar' ), array( 0 => 'cake' ) ) ); $this->assertEquals($expectedQuery, $query); $query = $this->Socket->parseQuery('a[][]=foo&a[bar]=php&a[][]=bar&a[][]=cake'); $expectedQuery = array( 'a' => array( array('foo'), 'bar' => 'php', array('bar'), array('cake') ) ); $this->assertEquals($expectedQuery, $query); $query = $this->Socket->parseQuery('user[]=jim&user[3]=tom&user[]=bob'); $expectedQuery = array( 'user' => array( 0 => 'jim', 3 => 'tom', 4 => 'bob' ) ); $this->assertEquals($expectedQuery, $query); $queryStr = 'user[0]=foo&user[0][items][]=foo&user[0][items][]=bar&user[][name]=jim&user[1][items][personal][]=book&user[1][items][personal][]=pen&user[1][items][]=ball&user[count]=2&empty'; $query = $this->Socket->parseQuery($queryStr); $expectedQuery = array( 'user' => array( 0 => array( 'items' => array( 'foo', 'bar' ) ), 1 => array( 'name' => 'jim', 'items' => array( 'personal' => array( 'book', 'pen' ), 'ball' ) ), 'count' => '2' ), 'empty' => '' ); $this->assertEquals($expectedQuery, $query); $query = 'openid.ns=example.com&foo=bar&foo=baz'; $result = $this->Socket->parseQuery($query); $expected = array( 'openid.ns' => 'example.com', 'foo' => array('bar', 'baz') ); $this->assertEquals($expected, $result); } /** * Tests that HttpSocket::buildHeader can turn a given $header array into a proper header string according to * HTTP 1.1 specs. * * @return void */ public function testBuildHeader() { $this->Socket->reset(); $r = $this->Socket->buildHeader(true); $this->assertEquals(false, $r); $r = $this->Socket->buildHeader('My raw header'); $this->assertEquals('My raw header', $r); $r = $this->Socket->buildHeader(array('Host' => 'www.cakephp.org')); $this->assertEquals("Host: www.cakephp.org\r\n", $r); $r = $this->Socket->buildHeader(array('Host' => 'www.cakephp.org', 'Connection' => 'Close')); $this->assertEquals("Host: www.cakephp.org\r\nConnection: Close\r\n", $r); $r = $this->Socket->buildHeader(array('People' => array('Bob', 'Jim', 'John'))); $this->assertEquals("People: Bob,Jim,John\r\n", $r); $r = $this->Socket->buildHeader(array('Multi-Line-Field' => "This is my\r\nMulti Line field")); $this->assertEquals("Multi-Line-Field: This is my\r\n Multi Line field\r\n", $r); $r = $this->Socket->buildHeader(array('Multi-Line-Field' => "This is my\r\n Multi Line field")); $this->assertEquals("Multi-Line-Field: This is my\r\n Multi Line field\r\n", $r); $r = $this->Socket->buildHeader(array('Multi-Line-Field' => "This is my\r\n\tMulti Line field")); $this->assertEquals("Multi-Line-Field: This is my\r\n\tMulti Line field\r\n", $r); $r = $this->Socket->buildHeader(array('Test@Field' => "My value")); $this->assertEquals("Test\"@\"Field: My value\r\n", $r); } /** * testBuildCookies method * * @return void */ public function testBuildCookies() { $cookies = array( 'foo' => array( 'value' => 'bar' ), 'people' => array( 'value' => 'jim,jack,johnny;', 'path' => '/accounts' ), 'key' => 'value' ); $expect = "Cookie: foo=bar; people=jim,jack,johnny\";\"; key=value\r\n"; $result = $this->Socket->buildCookies($cookies); $this->assertEquals($expect, $result); } /** * Tests that HttpSocket::_tokenEscapeChars() returns the right characters. * * @return void */ public function testTokenEscapeChars() { $this->Socket->reset(); $expected = array( '\x22', '\x28', '\x29', '\x3c', '\x3e', '\x40', '\x2c', '\x3b', '\x3a', '\x5c', '\x2f', '\x5b', '\x5d', '\x3f', '\x3d', '\x7b', '\x7d', '\x20', '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', '\x7f' ); $r = $this->Socket->tokenEscapeChars(); $this->assertEquals($expected, $r); foreach ($expected as $key => $char) { $expected[$key] = chr(hexdec(substr($char, 2))); } $r = $this->Socket->tokenEscapeChars(false); $this->assertEquals($expected, $r); } /** * Test that HttpSocket::escapeToken is escaping all characters as described in RFC 2616 (HTTP 1.1 specs) * * @return void */ public function testEscapeToken() { $this->Socket->reset(); $this->assertEquals('Foo', $this->Socket->escapeToken('Foo')); $escape = $this->Socket->tokenEscapeChars(false); foreach ($escape as $char) { $token = 'My-special-' . $char . '-Token'; $escapedToken = $this->Socket->escapeToken($token); $expectedToken = 'My-special-"' . $char . '"-Token'; $this->assertEquals($expectedToken, $escapedToken, 'Test token escaping for ASCII ' . ord($char)); } $token = 'Extreme-:Token- -"@-test'; $escapedToken = $this->Socket->escapeToken($token); $expectedToken = 'Extreme-":"Token-" "-""""@"-test'; $this->assertEquals($expectedToken, $escapedToken); } /** * This tests asserts HttpSocket::reset() resets a HttpSocket instance to it's initial state (before Object::__construct * got executed) * * @return void */ public function testReset() { $this->Socket->reset(); $initialState = get_class_vars('HttpSocket'); foreach ($initialState as $property => $value) { $this->Socket->{$property} = 'Overwritten'; } $return = $this->Socket->reset(); foreach ($initialState as $property => $value) { $this->assertEquals($this->Socket->{$property}, $value); } $this->assertEquals(true, $return); } /** * This tests asserts HttpSocket::reset(false) resets certain HttpSocket properties to their initial state (before * Object::__construct got executed). * * @return void */ public function testPartialReset() { $this->Socket->reset(); $partialResetProperties = array('request', 'response'); $initialState = get_class_vars('HttpSocket'); foreach ($initialState as $property => $value) { $this->Socket->{$property} = 'Overwritten'; } $return = $this->Socket->reset(false); foreach ($initialState as $property => $originalValue) { if (in_array($property, $partialResetProperties)) { $this->assertEquals($this->Socket->{$property}, $originalValue); } else { $this->assertEquals('Overwritten', $this->Socket->{$property}); } } $this->assertEquals(true, $return); } /** * Test that requests fail when peer verification fails. * * @return void */ public function testVerifyPeer() { $this->skipIf(!extension_loaded('openssl'), 'OpenSSL is not enabled cannot test SSL.'); $socket = new HttpSocket(); try { $socket->get('https://tv.eurosport.com/'); $this->markTestSkipped('Found valid certificate, was expecting invalid certificate.'); } catch (SocketException $e) { $message = $e->getMessage(); $this->skipIf(strpos($message, 'Invalid HTTP') !== false, 'Invalid HTTP Response received, skipping.'); $this->assertContains('Peer certificate CN', $message); $this->assertContains('Failed to enable crypto', $message); } } /** * Data provider for status codes. * * @return array */ public function statusProvider() { return array( array('HTTP/1.1 200 ', '200'), array('HTTP/1.1 200 ', '200'), array('HTTP/1.1 200', '200'), array('HTTP/1.1 200 OK', '200', 'OK'), array('HTTP/1.1 404 Not Found', '404', 'Not Found'), array('HTTP/1.1 404 Not Found', '404', 'Not Found'), ); } /** * test response status parsing * * @dataProvider statusProvider * @return void */ public function testResponseStatusParsing($status, $code, $msg = '') { $this->Socket->connected = true; $serverResponse = $status . "\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\n\r\n

This is a test!

"; $this->Socket->expects($this->any()) ->method('read') ->will($this->onConsecutiveCalls($serverResponse, false)); $response = $this->Socket->request('http://www.cakephp.org/'); $this->assertInstanceOf('HttpSocketResponse', $response); $expected = array( 'http-version' => 'HTTP/1.1', 'code' => $code, 'reason-phrase' => $msg ); $this->assertEquals($expected, $response['status']); } } cakephp-2.8.0/lib/Cake/Test/Case/Routing/000077500000000000000000000000001265552240500177745ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Routing/DispatcherTest.php000066400000000000000000001410211265552240500234320ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Routing * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Dispatcher', 'Routing'); App::uses('DispatcherFilter', 'Routing'); if (!class_exists('AppController', false)) { require_once CAKE . 'Test' . DS . 'test_app' . DS . 'Controller' . DS . 'AppController.php'; } elseif (!defined('APP_CONTROLLER_EXISTS')) { define('APP_CONTROLLER_EXISTS', true); } /** * A testing stub that doesn't send headers. * * @package Cake.Test.Case.Routing */ class DispatcherMockCakeResponse extends CakeResponse { protected function _sendHeader($name, $value = null) { return $name . ' ' . $value; } } /** * TestDispatcher class * * @package Cake.Test.Case.Routing */ class TestDispatcher extends Dispatcher { /** * Controller instance, made publicly available for testing * * @var Controller */ public $controller; /** * invoke method * * @param Controller $controller * @param CakeRequest $request * @return CakeResponse */ protected function _invoke(Controller $controller, CakeRequest $request) { $this->controller = $controller; return parent::_invoke($controller, $request); } /** * Helper function to test single method attaching for dispatcher filters * * @param CakeEvent $event * @return void */ public function filterTest($event) { $event->data['request']->params['eventName'] = $event->name(); } /** * Helper function to test single method attaching for dispatcher filters * * @param CakeEvent * @return void */ public function filterTest2($event) { $event->stopPropagation(); return $event->data['response']; } } /** * MyPluginAppController class * * @package Cake.Test.Case.Routing */ class MyPluginAppController extends AppController { } /** * Abstract Class DispatcherTestAbstractController */ abstract class DispatcherTestAbstractController extends Controller { abstract public function index(); } /** * Interface DispatcherTestInterfaceController */ interface DispatcherTestInterfaceController { public function index(); } /** * MyPluginController class * * @package Cake.Test.Case.Routing */ class MyPluginController extends MyPluginAppController { /** * uses property * * @var array */ public $uses = array(); /** * index method * * @return void */ public function index() { return true; } /** * add method * * @return void */ public function add() { return true; } /** * admin_add method * * @param mixed $id * @return void */ public function admin_add($id = null) { return $id; } } /** * SomePagesController class * * @package Cake.Test.Case.Routing */ class SomePagesController extends AppController { /** * uses property * * @var array */ public $uses = array(); /** * display method * * @param string $page * @return void */ public function display($page = null) { return $page; } /** * index method * * @return void */ public function index() { return true; } /** * Test method for returning responses. * * @return CakeResponse */ public function responseGenerator() { return new CakeResponse(array('body' => 'new response')); } /** * Test file sending * * @return CakeResponse */ public function sendfile() { $this->response->file(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS . 'css' . DS . 'test_asset.css'); return $this->response; } } /** * OtherPagesController class * * @package Cake.Test.Case.Routing */ class OtherPagesController extends MyPluginAppController { /** * uses property * * @var array */ public $uses = array(); /** * display method * * @param string $page * @return void */ public function display($page = null) { return $page; } /** * index method * * @return void */ public function index() { return true; } } /** * TestDispatchPagesController class * * @package Cake.Test.Case.Routing */ class TestDispatchPagesController extends AppController { /** * uses property * * @var array */ public $uses = array(); /** * admin_index method * * @return void */ public function admin_index() { return true; } /** * camelCased method * * @return void */ public function camelCased() { return true; } } /** * ArticlesTestAppController class * * @package Cake.Test.Case.Routing */ class ArticlesTestAppController extends AppController { } /** * ArticlesTestController class * * @package Cake.Test.Case.Routing */ class ArticlesTestController extends ArticlesTestAppController { /** * uses property * * @var array */ public $uses = array(); /** * admin_index method * * @return void */ public function admin_index() { return true; } /** * fake index method. * * @return void */ public function index() { return true; } } /** * SomePostsController class * * @package Cake.Test.Case.Routing */ class SomePostsController extends AppController { /** * uses property * * @var array */ public $uses = array(); /** * autoRender property * * @var bool */ public $autoRender = false; /** * beforeFilter method * * @return void */ public function beforeFilter() { if ($this->params['action'] === 'index') { $this->params['action'] = 'view'; } else { $this->params['action'] = 'change'; } $this->params['pass'] = array('changed'); } /** * index method * * @return void */ public function index() { return true; } /** * change method * * @return void */ public function change() { return true; } } /** * TestCachedPagesController class * * @package Cake.Test.Case.Routing */ class TestCachedPagesController extends Controller { /** * uses property * * @var array */ public $uses = array(); /** * helpers property * * @var array */ public $helpers = array('Cache', 'Html'); /** * cacheAction property * * @var array */ public $cacheAction = array( 'index' => '+2 sec', 'test_nocache_tags' => '+2 sec', 'view' => '+2 sec' ); /** * Mock out the response object so it doesn't send headers. * * @var string */ protected $_responseClass = 'DispatcherMockCakeResponse'; /** * viewPath property * * @var string */ public $viewPath = 'Posts'; /** * index method * * @return void */ public function index() { $this->render(); } /** * test_nocache_tags method * * @return void */ public function test_nocache_tags() { $this->render(); } /** * view method * * @return void */ public function view($id = null) { $this->render('index'); } /** * test cached forms / tests view object being registered * * @return void */ public function cache_form() { $this->cacheAction = 10; $this->helpers[] = 'Form'; } /** * Test cached views with themes. * * @return void */ public function themed() { $this->cacheAction = 10; $this->viewClass = 'Theme'; $this->theme = 'TestTheme'; } } /** * TimesheetsController class * * @package Cake.Test.Case.Routing */ class TimesheetsController extends Controller { /** * uses property * * @var array */ public $uses = array(); /** * index method * * @return void */ public function index() { return true; } } /** * TestFilterDispatcher class * * @package Cake.Test.Case.Routing */ class TestFilterDispatcher extends DispatcherFilter { public $priority = 10; /** * TestFilterDispatcher::beforeDispatch() * * @param mixed $event * @return CakeResponse|bool */ public function beforeDispatch(CakeEvent $event) { $event->stopPropagation(); $response = $event->data['request']; $response->addParams(array('settings' => $this->settings)); return null; } /** * TestFilterDispatcher::afterDispatch() * * @param mixed $event * @return mixed boolean to stop the event dispatching or null to continue */ public function afterDispatch(CakeEvent $event) { } } /** * DispatcherTest class * * @package Cake.Test.Case.Routing */ class DispatcherTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->_get = $_GET; $_GET = array(); $this->_post = $_POST; $this->_files = $_FILES; $this->_server = $_SERVER; $this->_app = Configure::read('App'); Configure::write('App.base', false); Configure::write('App.baseUrl', false); Configure::write('App.dir', 'app'); Configure::write('App.webroot', 'webroot'); $this->_cache = Configure::read('Cache'); Configure::write('Cache.disable', true); $this->_debug = Configure::read('debug'); App::build(); App::objects('plugin', null, false); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); $_GET = $this->_get; $_POST = $this->_post; $_FILES = $this->_files; $_SERVER = $this->_server; App::build(); CakePlugin::unload(); Configure::write('App', $this->_app); Configure::write('Cache', $this->_cache); Configure::write('debug', $this->_debug); Configure::write('Dispatcher.filters', array()); } /** * testParseParamsWithoutZerosAndEmptyPost method * * @return void * @triggers DispatcherTest $Dispatcher, array('request' => $request) */ public function testParseParamsWithoutZerosAndEmptyPost() { $Dispatcher = new Dispatcher(); $request = new CakeRequest("/testcontroller/testaction/params1/params2/params3"); $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $request)); $Dispatcher->parseParams($event); $this->assertSame($request['controller'], 'testcontroller'); $this->assertSame($request['action'], 'testaction'); $this->assertSame($request['pass'][0], 'params1'); $this->assertSame($request['pass'][1], 'params2'); $this->assertSame($request['pass'][2], 'params3'); $this->assertFalse(!empty($request['form'])); } /** * testParseParamsReturnsPostedData method * * @return void * @triggers DispatcherTest $Dispatcher, array('request' => $request) */ public function testParseParamsReturnsPostedData() { $_POST['testdata'] = "My Posted Content"; $Dispatcher = new Dispatcher(); $request = new CakeRequest("/"); $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $request)); $Dispatcher->parseParams($event); $Dispatcher->parseParams($event); $this->assertEquals("My Posted Content", $request['data']['testdata']); } /** * testParseParamsWithSingleZero method * * @return void * @triggers DispatcherTest $Dispatcher, array('request' => $test) */ public function testParseParamsWithSingleZero() { $Dispatcher = new Dispatcher(); $test = new CakeRequest("/testcontroller/testaction/1/0/23"); $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $test)); $Dispatcher->parseParams($event); $this->assertSame($test['controller'], 'testcontroller'); $this->assertSame($test['action'], 'testaction'); $this->assertSame($test['pass'][0], '1'); $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][1]); $this->assertSame($test['pass'][2], '23'); } /** * testParseParamsWithManySingleZeros method * * @return void * @triggers DispatcherTest $Dispatcher, array('request' => $test) */ public function testParseParamsWithManySingleZeros() { $Dispatcher = new Dispatcher(); $test = new CakeRequest("/testcontroller/testaction/0/0/0/0/0/0"); $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $test)); $Dispatcher->parseParams($event); $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][0]); $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][1]); $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][2]); $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][3]); $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][4]); $this->assertRegExp('/\\A(?:0)\\z/', $test['pass'][5]); } /** * testParseParamsWithManyZerosInEachSectionOfUrl method * * @return void * @triggers DispatcherTest $Dispatcher, array('request' => $test) */ public function testParseParamsWithManyZerosInEachSectionOfUrl() { $Dispatcher = new Dispatcher(); $test = new CakeRequest("/testcontroller/testaction/000/0000/00000/000000/000000/0000000"); $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $test)); $Dispatcher->parseParams($event); $this->assertRegExp('/\\A(?:000)\\z/', $test['pass'][0]); $this->assertRegExp('/\\A(?:0000)\\z/', $test['pass'][1]); $this->assertRegExp('/\\A(?:00000)\\z/', $test['pass'][2]); $this->assertRegExp('/\\A(?:000000)\\z/', $test['pass'][3]); $this->assertRegExp('/\\A(?:000000)\\z/', $test['pass'][4]); $this->assertRegExp('/\\A(?:0000000)\\z/', $test['pass'][5]); } /** * testParseParamsWithMixedOneToManyZerosInEachSectionOfUrl method * * @return void * @triggers DispatcherTest $Dispatcher, array('request' => $test) */ public function testParseParamsWithMixedOneToManyZerosInEachSectionOfUrl() { $Dispatcher = new Dispatcher(); $test = new CakeRequest("/testcontroller/testaction/01/0403/04010/000002/000030/0000400"); $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $test)); $Dispatcher->parseParams($event); $this->assertRegExp('/\\A(?:01)\\z/', $test['pass'][0]); $this->assertRegExp('/\\A(?:0403)\\z/', $test['pass'][1]); $this->assertRegExp('/\\A(?:04010)\\z/', $test['pass'][2]); $this->assertRegExp('/\\A(?:000002)\\z/', $test['pass'][3]); $this->assertRegExp('/\\A(?:000030)\\z/', $test['pass'][4]); $this->assertRegExp('/\\A(?:0000400)\\z/', $test['pass'][5]); } /** * testQueryStringOnRoot method * * @return void * @triggers DispatcherTest $Dispatcher, array('request' => $request) * @triggers DispatcherTest $Dispatcher, array('request' => $request) */ public function testQueryStringOnRoot() { Router::reload(); Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home')); Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display')); Router::connect('/:controller/:action/*'); $_GET = array('coffee' => 'life', 'sleep' => 'sissies'); $Dispatcher = new Dispatcher(); $request = new CakeRequest('posts/home/?coffee=life&sleep=sissies'); $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $request)); $Dispatcher->parseParams($event); $this->assertRegExp('/posts/', $request['controller']); $this->assertRegExp('/home/', $request['action']); $this->assertTrue(isset($request['url']['sleep'])); $this->assertTrue(isset($request['url']['coffee'])); $Dispatcher = new Dispatcher(); $request = new CakeRequest('/?coffee=life&sleep=sissy'); $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $request)); $Dispatcher->parseParams($event); $this->assertRegExp('/pages/', $request['controller']); $this->assertRegExp('/display/', $request['action']); $this->assertTrue(isset($request['url']['sleep'])); $this->assertTrue(isset($request['url']['coffee'])); $this->assertEquals('life', $request['url']['coffee']); } /** * testMissingController method * * @expectedException MissingControllerException * @expectedExceptionMessage Controller class SomeControllerController could not be found. * @return void */ public function testMissingController() { Router::connect('/:controller/:action/*'); $Dispatcher = new TestDispatcher(); Configure::write('App.baseUrl', '/index.php'); $url = new CakeRequest('some_controller/home/param:value/param2:value2'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); } /** * testMissingControllerInterface method * * @expectedException MissingControllerException * @expectedExceptionMessage Controller class DispatcherTestInterfaceController could not be found. * @return void */ public function testMissingControllerInterface() { Router::connect('/:controller/:action/*'); $Dispatcher = new TestDispatcher(); Configure::write('App.baseUrl', '/index.php'); $url = new CakeRequest('dispatcher_test_interface/index'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); } /** * testMissingControllerInterface method * * @expectedException MissingControllerException * @expectedExceptionMessage Controller class DispatcherTestAbstractController could not be found. * @return void */ public function testMissingControllerAbstract() { Router::connect('/:controller/:action/*'); $Dispatcher = new TestDispatcher(); Configure::write('App.baseUrl', '/index.php'); $url = new CakeRequest('dispatcher_test_abstract/index'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); } /** * testDispatch method * * @return void */ public function testDispatchBasic() { App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); $Dispatcher = new TestDispatcher(); Configure::write('App.baseUrl', '/index.php'); $url = new CakeRequest('pages/home/param:value/param2:value2'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $expected = 'Pages'; $this->assertEquals($expected, $Dispatcher->controller->name); $expected = array('0' => 'home', 'param' => 'value', 'param2' => 'value2'); $this->assertSame($expected, $Dispatcher->controller->passedArgs); Configure::write('App.baseUrl', '/pages/index.php'); $url = new CakeRequest('pages/home'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $expected = 'Pages'; $this->assertEquals($expected, $Dispatcher->controller->name); $url = new CakeRequest('pages/home/'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertNull($Dispatcher->controller->plugin); $expected = 'Pages'; $this->assertEquals($expected, $Dispatcher->controller->name); unset($Dispatcher); require CAKE . 'Config' . DS . 'routes.php'; $Dispatcher = new TestDispatcher(); Configure::write('App.baseUrl', '/timesheets/index.php'); $url = new CakeRequest('timesheets'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $expected = 'Timesheets'; $this->assertEquals($expected, $Dispatcher->controller->name); $url = new CakeRequest('timesheets/'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertEquals('Timesheets', $Dispatcher->controller->name); $this->assertEquals('/timesheets/index.php', $url->base); $url = new CakeRequest('test_dispatch_pages/camelCased'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertEquals('TestDispatchPages', $Dispatcher->controller->name); $url = new CakeRequest('test_dispatch_pages/camelCased/something. .'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertEquals('something. .', $Dispatcher->controller->params['pass'][0], 'Period was chopped off. %s'); } /** * Test that Dispatcher handles actions that return response objects. * * @return void */ public function testDispatchActionReturnsResponse() { Router::connect('/:controller/:action'); $Dispatcher = new Dispatcher(); $request = new CakeRequest('some_pages/responseGenerator'); $response = $this->getMock('CakeResponse', array('_sendHeader')); ob_start(); $Dispatcher->dispatch($request, $response); $result = ob_get_clean(); $this->assertEquals('new response', $result); } /** * testDispatchActionSendsFile * * @return void */ public function testDispatchActionSendsFile() { Router::connect('/:controller/:action'); $Dispatcher = new Dispatcher(); $request = new CakeRequest('some_pages/sendfile'); $response = $this->getMock('CakeResponse', array( 'header', 'type', 'download', '_sendHeader', '_setContentType', '_isActive', '_clearBuffer', '_flushBuffer' )); $response->expects($this->never()) ->method('body'); $response->expects($this->exactly(1)) ->method('_isActive') ->will($this->returnValue(true)); ob_start(); $Dispatcher->dispatch($request, $response); $result = ob_get_clean(); $this->assertEquals("/* this is the test asset css file */\n", $result); } /** * testAdminDispatch method * * @return void */ public function testAdminDispatch() { $_POST = array(); $Dispatcher = new TestDispatcher(); Configure::write('Routing.prefixes', array('admin')); Configure::write('App.baseUrl', '/cake/repo/branches/1.2.x.x/index.php'); $url = new CakeRequest('admin/test_dispatch_pages/index/param:value/param2:value2'); $response = $this->getMock('CakeResponse'); Router::reload(); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertEquals('TestDispatchPages', $Dispatcher->controller->name); $this->assertSame($Dispatcher->controller->passedArgs, array('param' => 'value', 'param2' => 'value2')); $this->assertTrue($Dispatcher->controller->params['admin']); $expected = '/cake/repo/branches/1.2.x.x/index.php/admin/test_dispatch_pages/index/param:value/param2:value2'; $this->assertSame($expected, $Dispatcher->controller->here); $expected = '/cake/repo/branches/1.2.x.x/index.php'; $this->assertSame($expected, $Dispatcher->controller->base); } /** * testPluginDispatch method * * @return void * @triggers DispatcherTest $Dispatcher, array('request' => $url) */ public function testPluginDispatch() { $_POST = array(); Router::reload(); $Dispatcher = new TestDispatcher(); Router::connect( '/my_plugin/:controller/*', array('plugin' => 'my_plugin', 'controller' => 'pages', 'action' => 'display') ); $url = new CakeRequest('my_plugin/some_pages/home/param:value/param2:value2'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $event = new CakeEvent('DispatcherTest', $Dispatcher, array('request' => $url)); $Dispatcher->parseParams($event); $expected = array( 'pass' => array('home'), 'named' => array('param' => 'value', 'param2' => 'value2'), 'plugin' => 'my_plugin', 'controller' => 'some_pages', 'action' => 'display' ); foreach ($expected as $key => $value) { $this->assertEquals($value, $url[$key], 'Value mismatch ' . $key . ' %'); } $this->assertSame($Dispatcher->controller->plugin, 'MyPlugin'); $this->assertSame($Dispatcher->controller->name, 'SomePages'); $this->assertSame($Dispatcher->controller->params['controller'], 'some_pages'); $this->assertSame($Dispatcher->controller->passedArgs, array('0' => 'home', 'param' => 'value', 'param2' => 'value2')); } /** * testAutomaticPluginDispatch method * * @return void */ public function testAutomaticPluginDispatch() { $_POST = array(); $_SERVER['PHP_SELF'] = '/cake/repo/branches/1.2.x.x/index.php'; Router::reload(); $Dispatcher = new TestDispatcher(); Router::connect( '/my_plugin/:controller/:action/*', array('plugin' => 'my_plugin', 'controller' => 'pages', 'action' => 'display') ); $Dispatcher->base = false; $url = new CakeRequest('my_plugin/other_pages/index/param:value/param2:value2'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertSame($Dispatcher->controller->plugin, 'MyPlugin'); $this->assertSame($Dispatcher->controller->name, 'OtherPages'); $this->assertSame($Dispatcher->controller->action, 'index'); $this->assertSame($Dispatcher->controller->passedArgs, array('param' => 'value', 'param2' => 'value2')); $expected = '/cake/repo/branches/1.2.x.x/my_plugin/other_pages/index/param:value/param2:value2'; $this->assertSame($expected, $url->here); $expected = '/cake/repo/branches/1.2.x.x'; $this->assertSame($expected, $url->base); } /** * testAutomaticPluginControllerDispatch method * * @return void */ public function testAutomaticPluginControllerDispatch() { $plugins = App::objects('plugin'); $plugins[] = 'MyPlugin'; $plugins[] = 'ArticlesTest'; CakePlugin::load('MyPlugin', array('path' => '/fake/path')); Router::reload(); $Dispatcher = new TestDispatcher(); $Dispatcher->base = false; $url = new CakeRequest('my_plugin/my_plugin/add/param:value/param2:value2'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertSame($Dispatcher->controller->plugin, 'MyPlugin'); $this->assertSame($Dispatcher->controller->name, 'MyPlugin'); $this->assertSame($Dispatcher->controller->action, 'add'); $this->assertEquals(array('param' => 'value', 'param2' => 'value2'), $Dispatcher->controller->params['named']); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; $Dispatcher = new TestDispatcher(); $Dispatcher->base = false; // Simulates the Route for a real plugin, installed in APP/plugins Router::connect('/my_plugin/:controller/:action/*', array('plugin' => 'my_plugin')); $plugin = 'MyPlugin'; $pluginUrl = Inflector::underscore($plugin); $url = new CakeRequest($pluginUrl); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertSame($Dispatcher->controller->plugin, 'MyPlugin'); $this->assertSame($Dispatcher->controller->name, 'MyPlugin'); $this->assertSame($Dispatcher->controller->action, 'index'); $expected = $pluginUrl; $this->assertEquals($expected, $Dispatcher->controller->params['controller']); Configure::write('Routing.prefixes', array('admin')); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; $Dispatcher = new TestDispatcher(); $url = new CakeRequest('admin/my_plugin/my_plugin/add/5/param:value/param2:value2'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertEquals('my_plugin', $Dispatcher->controller->params['plugin']); $this->assertEquals('my_plugin', $Dispatcher->controller->params['controller']); $this->assertEquals('admin_add', $Dispatcher->controller->params['action']); $this->assertEquals(array(5), $Dispatcher->controller->params['pass']); $this->assertEquals(array('param' => 'value', 'param2' => 'value2'), $Dispatcher->controller->params['named']); $this->assertSame($Dispatcher->controller->plugin, 'MyPlugin'); $this->assertSame($Dispatcher->controller->name, 'MyPlugin'); $this->assertSame($Dispatcher->controller->action, 'admin_add'); $expected = array(0 => 5, 'param' => 'value', 'param2' => 'value2'); $this->assertEquals($expected, $Dispatcher->controller->passedArgs); Configure::write('Routing.prefixes', array('admin')); CakePlugin::load('ArticlesTest', array('path' => '/fake/path')); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; $Dispatcher = new TestDispatcher(); $Dispatcher->dispatch(new CakeRequest('admin/articles_test'), $response, array('return' => 1)); $this->assertSame($Dispatcher->controller->plugin, 'ArticlesTest'); $this->assertSame($Dispatcher->controller->name, 'ArticlesTest'); $this->assertSame($Dispatcher->controller->action, 'admin_index'); $expected = array( 'pass' => array(), 'named' => array(), 'controller' => 'articles_test', 'plugin' => 'articles_test', 'action' => 'admin_index', 'prefix' => 'admin', 'admin' => true, 'return' => 1 ); foreach ($expected as $key => $value) { $this->assertEquals($expected[$key], $Dispatcher->controller->request[$key], 'Value mismatch ' . $key); } } /** * test Plugin dispatching without controller name and using * plugin short form instead. * * @return void */ public function testAutomaticPluginDispatchWithShortAccess() { CakePlugin::load('MyPlugin', array('path' => '/fake/path')); Router::reload(); $Dispatcher = new TestDispatcher(); $Dispatcher->base = false; $url = new CakeRequest('my_plugin/'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertEquals('my_plugin', $Dispatcher->controller->params['controller']); $this->assertEquals('my_plugin', $Dispatcher->controller->params['plugin']); $this->assertEquals('index', $Dispatcher->controller->params['action']); $this->assertFalse(isset($Dispatcher->controller->params['pass'][0])); } /** * test plugin shortcut URLs with controllers that need to be loaded, * the above test uses a controller that has already been included. * * @return void */ public function testPluginShortCutUrlsWithControllerThatNeedsToBeLoaded() { $loaded = class_exists('TestPluginController', false); $this->skipIf($loaded, 'TestPluginController already loaded.'); Router::reload(); App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); $Dispatcher = new TestDispatcher(); $Dispatcher->base = false; $url = new CakeRequest('test_plugin/'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertEquals('test_plugin', $Dispatcher->controller->params['controller']); $this->assertEquals('test_plugin', $Dispatcher->controller->params['plugin']); $this->assertEquals('index', $Dispatcher->controller->params['action']); $this->assertFalse(isset($Dispatcher->controller->params['pass'][0])); $url = new CakeRequest('/test_plugin/tests/index'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertEquals('tests', $Dispatcher->controller->params['controller']); $this->assertEquals('test_plugin', $Dispatcher->controller->params['plugin']); $this->assertEquals('index', $Dispatcher->controller->params['action']); $this->assertFalse(isset($Dispatcher->controller->params['pass'][0])); $url = new CakeRequest('/test_plugin/tests/index/some_param'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertEquals('tests', $Dispatcher->controller->params['controller']); $this->assertEquals('test_plugin', $Dispatcher->controller->params['plugin']); $this->assertEquals('index', $Dispatcher->controller->params['action']); $this->assertEquals('some_param', $Dispatcher->controller->params['pass'][0]); App::build(); } /** * testAutomaticPluginControllerMissingActionDispatch method * * @expectedException MissingActionException * @expectedExceptionMessage Action MyPluginController::not_here() could not be found. * @return void */ public function testAutomaticPluginControllerMissingActionDispatch() { Router::reload(); $Dispatcher = new TestDispatcher(); $url = new CakeRequest('my_plugin/not_here/param:value/param2:value2'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); } /** * testAutomaticPluginControllerMissingActionDispatch method * * @expectedException MissingActionException * @expectedExceptionMessage Action MyPluginController::param:value() could not be found. * @return void */ public function testAutomaticPluginControllerIndexMissingAction() { Router::reload(); $Dispatcher = new TestDispatcher(); $url = new CakeRequest('my_plugin/param:value/param2:value2'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); } /** * Test dispatching into the TestPlugin in the test_app * * @return void */ public function testTestPluginDispatch() { $Dispatcher = new TestDispatcher(); App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); Router::reload(); Router::parse('/'); $url = new CakeRequest('/test_plugin/tests/index'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->assertTrue(class_exists('TestsController')); $this->assertTrue(class_exists('TestPluginAppController')); $this->assertTrue(class_exists('PluginsComponent')); $this->assertEquals('tests', $Dispatcher->controller->params['controller']); $this->assertEquals('test_plugin', $Dispatcher->controller->params['plugin']); $this->assertEquals('index', $Dispatcher->controller->params['action']); App::build(); } /** * Tests that it is possible to attach filter classes to the dispatch cycle * * @return void */ public function testDispatcherFilterSubscriber() { App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS), 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); Configure::write('Dispatcher.filters', array( array('callable' => 'TestPlugin.TestDispatcherFilter') )); $dispatcher = new TestDispatcher(); $request = new CakeRequest('/'); $request->params['altered'] = false; $response = $this->getMock('CakeResponse', array('send')); $dispatcher->dispatch($request, $response); $this->assertTrue($request->params['altered']); $this->assertEquals(304, $response->statusCode()); Configure::write('Dispatcher.filters', array( 'TestPlugin.Test2DispatcherFilter', 'TestPlugin.TestDispatcherFilter' )); $dispatcher = new TestDispatcher(); $request = new CakeRequest('/'); $request->params['altered'] = false; $response = $this->getMock('CakeResponse', array('send')); $dispatcher->dispatch($request, $response); $this->assertFalse($request->params['altered']); $this->assertEquals(500, $response->statusCode()); $this->assertNull($dispatcher->controller); } /** * Tests that it is possible to attach filter with config classes to the dispatch cycle * * @return void */ public function testDispatcherFilterSettings() { Configure::write('Dispatcher.filters', array( 'TestFilterDispatcher' => array('service' => 'google.com') )); $Dispatcher = new Dispatcher(); $url = new CakeRequest('some_pages/index'); $response = $this->getMock('CakeResponse'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $settings = $url->param('settings'); $this->assertEquals($settings, array('service' => 'google.com')); } /** * Tests that attaching an inexistent class as filter will throw an exception * * @expectedException MissingDispatcherFilterException * @return void */ public function testDispatcherFilterSuscriberMissing() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load('TestPlugin'); Configure::write('Dispatcher.filters', array( array('callable' => 'TestPlugin.NotAFilter') )); $dispatcher = new TestDispatcher(); $request = new CakeRequest('/'); $response = $this->getMock('CakeResponse', array('send')); $dispatcher->dispatch($request, $response); } /** * Tests it is possible to attach single callables as filters * * @return void */ public function testDispatcherFilterCallable() { App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) ), App::RESET); $dispatcher = new TestDispatcher(); Configure::write('Dispatcher.filters', array( array('callable' => array($dispatcher, 'filterTest'), 'on' => 'before') )); $request = new CakeRequest('/'); $response = $this->getMock('CakeResponse', array('send')); $dispatcher->dispatch($request, $response); $this->assertEquals('Dispatcher.beforeDispatch', $request->params['eventName']); $dispatcher = new TestDispatcher(); Configure::write('Dispatcher.filters', array( array('callable' => array($dispatcher, 'filterTest'), 'on' => 'after') )); $request = new CakeRequest('/'); $response = $this->getMock('CakeResponse', array('send')); $dispatcher->dispatch($request, $response); $this->assertEquals('Dispatcher.afterDispatch', $request->params['eventName']); $dispatcher = new TestDispatcher(); Configure::write('Dispatcher.filters', array( 'filterTest' => array('callable' => array($dispatcher, 'filterTest'), 'on' => 'before') )); $request = new CakeRequest('/'); $response = $this->getMock('CakeResponse', array('send')); $dispatcher->dispatch($request, $response); $this->assertEquals('Dispatcher.beforeDispatch', $request->params['eventName']); // Test that it is possible to skip the route connection process $dispatcher = new TestDispatcher(); Configure::write('Dispatcher.filters', array( array('callable' => array($dispatcher, 'filterTest2'), 'on' => 'before', 'priority' => 1) )); $request = new CakeRequest('/'); $response = $this->getMock('CakeResponse', array('send')); $dispatcher->dispatch($request, $response); $this->assertEmpty($dispatcher->controller); $expected = array('controller' => null, 'action' => null, 'plugin' => null, 'named' => array(), 'pass' => array()); $this->assertEquals($expected, $request->params); $dispatcher = new TestDispatcher(); Configure::write('Dispatcher.filters', array( array('callable' => array($dispatcher, 'filterTest2'), 'on' => 'before', 'priority' => 1) )); $request = new CakeRequest('/'); $request->params['return'] = true; $response = $this->getMock('CakeResponse', array('send')); $response->body('this is a body'); $result = $dispatcher->dispatch($request, $response); $this->assertEquals('this is a body', $result); $request = new CakeRequest('/'); $response = $this->getMock('CakeResponse', array('send')); $response->expects($this->once())->method('send'); $response->body('this is a body'); $result = $dispatcher->dispatch($request, $response); $this->assertNull($result); } /** * testChangingParamsFromBeforeFilter method * * @return void */ public function testChangingParamsFromBeforeFilter() { $Dispatcher = new TestDispatcher(); $response = $this->getMock('CakeResponse'); $url = new CakeRequest('some_posts/index/param:value/param2:value2'); try { $Dispatcher->dispatch($url, $response, array('return' => 1)); $this->fail('No exception.'); } catch (MissingActionException $e) { $this->assertEquals('Action SomePostsController::view() could not be found.', $e->getMessage()); } $url = new CakeRequest('some_posts/something_else/param:value/param2:value2'); $Dispatcher->dispatch($url, $response, array('return' => 1)); $expected = 'SomePosts'; $this->assertEquals($expected, $Dispatcher->controller->name); $expected = 'change'; $this->assertEquals($expected, $Dispatcher->controller->action); $expected = array('changed'); $this->assertSame($expected, $Dispatcher->controller->params['pass']); } /** * testStaticAssets method * * @return void */ public function testAssets() { Router::reload(); App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'Vendor' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS), 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); Configure::write('Dispatcher.filters', array('AssetDispatcher')); $Dispatcher = new TestDispatcher(); $response = $this->getMock('CakeResponse', array('_sendHeader')); try { $Dispatcher->dispatch(new CakeRequest('theme/test_theme/../webroot/css/test_asset.css'), $response); $this->fail('No exception'); } catch (MissingControllerException $e) { $this->assertEquals('Controller class ThemeController could not be found.', $e->getMessage()); } try { $Dispatcher->dispatch(new CakeRequest('theme/test_theme/pdfs'), $response); $this->fail('No exception'); } catch (MissingControllerException $e) { $this->assertEquals('Controller class ThemeController could not be found.', $e->getMessage()); } } /** * Data provider for asset filter * * - theme assets. * - plugin assets. * - plugin assets in sub directories. * - unknown plugin assets. * * @return array */ public static function assetProvider() { return array( array( 'theme/test_theme/flash/theme_test.swf', 'View/Themed/TestTheme/webroot/flash/theme_test.swf' ), array( 'theme/test_theme/pdfs/theme_test.pdf', 'View/Themed/TestTheme/webroot/pdfs/theme_test.pdf' ), array( 'theme/test_theme/img/test.jpg', 'View/Themed/TestTheme/webroot/img/test.jpg' ), array( 'theme/test_theme/css/test_asset.css', 'View/Themed/TestTheme/webroot/css/test_asset.css' ), array( 'theme/test_theme/js/theme.js', 'View/Themed/TestTheme/webroot/js/theme.js' ), array( 'theme/test_theme/js/one/theme_one.js', 'View/Themed/TestTheme/webroot/js/one/theme_one.js' ), array( 'theme/test_theme/space%20image.text', 'View/Themed/TestTheme/webroot/space image.text' ), array( 'test_plugin/root.js', 'Plugin/TestPlugin/webroot/root.js' ), array( 'test_plugin/flash/plugin_test.swf', 'Plugin/TestPlugin/webroot/flash/plugin_test.swf' ), array( 'test_plugin/pdfs/plugin_test.pdf', 'Plugin/TestPlugin/webroot/pdfs/plugin_test.pdf' ), array( 'test_plugin/js/test_plugin/test.js', 'Plugin/TestPlugin/webroot/js/test_plugin/test.js' ), array( 'test_plugin/css/test_plugin_asset.css', 'Plugin/TestPlugin/webroot/css/test_plugin_asset.css' ), array( 'test_plugin/img/cake.icon.gif', 'Plugin/TestPlugin/webroot/img/cake.icon.gif' ), array( 'plugin_js/js/plugin_js.js', 'Plugin/PluginJs/webroot/js/plugin_js.js' ), array( 'plugin_js/js/one/plugin_one.js', 'Plugin/PluginJs/webroot/js/one/plugin_one.js' ), array( 'test_plugin/css/unknown.extension', 'Plugin/TestPlugin/webroot/css/unknown.extension' ), array( 'test_plugin/css/theme_one.htc', 'Plugin/TestPlugin/webroot/css/theme_one.htc' ), ); } /** * Test assets * * @dataProvider assetProvider * @outputBuffering enabled * @return void */ public function testAsset($url, $file) { Router::reload(); App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'Vendor' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Vendor' . DS), 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); CakePlugin::load(array('TestPlugin', 'PluginJs')); Configure::write('Dispatcher.filters', array('AssetDispatcher')); $Dispatcher = new TestDispatcher(); $response = $this->getMock('CakeResponse', array('_sendHeader')); $Dispatcher->dispatch(new CakeRequest($url), $response); $result = ob_get_clean(); $path = CAKE . 'Test' . DS . 'test_app' . DS . str_replace('/', DS, $file); $file = file_get_contents($path); $this->assertEquals($file, $result); $expected = filesize($path); $headers = $response->header(); $this->assertEquals($expected, $headers['Content-Length']); } /** * test that missing asset processors trigger a 404 with no response body. * * @return void */ public function testMissingAssetProcessor404() { $response = $this->getMock('CakeResponse', array('send')); $Dispatcher = new TestDispatcher(); Configure::write('Asset.filter', array( 'js' => '', 'css' => null )); Configure::write('Dispatcher.filters', array('AssetDispatcher')); $request = new CakeRequest('ccss/cake.generic.css'); $Dispatcher->dispatch($request, $response); $this->assertEquals('404', $response->statusCode()); } /** * Data provider for cached actions. * * - Test simple views * - Test views with nocache tags * - Test requests with named + passed params. * - Test requests with query string params * - Test themed views. * * @return array */ public static function cacheActionProvider() { return array( array('/'), array('test_cached_pages/index'), array('TestCachedPages/index'), array('test_cached_pages/test_nocache_tags'), array('TestCachedPages/test_nocache_tags'), array('test_cached_pages/view/param/param'), array('test_cached_pages/view/foo:bar/value:goo'), array('test_cached_pages/view?q=cakephp'), array('test_cached_pages/themed'), ); } /** * testFullPageCachingDispatch method * * @dataProvider cacheActionProvider * @return void */ public function testFullPageCachingDispatch($url) { Configure::write('Cache.disable', false); Configure::write('Cache.check', true); Configure::write('debug', 2); Router::reload(); Router::connect('/', array('controller' => 'test_cached_pages', 'action' => 'index')); Router::connect('/:controller/:action/*'); App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS), ), App::RESET); $dispatcher = new TestDispatcher(); $request = new CakeRequest($url); $response = $this->getMock('CakeResponse', array('send')); $dispatcher->dispatch($request, $response); $out = $response->body(); Configure::write('Dispatcher.filters', array('CacheDispatcher')); $request = new CakeRequest($url); $response = $this->getMock('CakeResponse', array('send')); $dispatcher = new TestDispatcher(); $dispatcher->dispatch($request, $response); $cached = $response->body(); $cached = preg_replace('//', '', $cached); $this->assertTextEquals($out, $cached); $filename = $this->_cachePath($request->here()); unlink($filename); } /** * testHttpMethodOverrides method * * @return void * @triggers DispatcherTest $dispatcher, array('request' => $request) * @triggers DispatcherTest $dispatcher, array('request' => $request) * @triggers DispatcherTest $dispatcher, array('request' => $request) * @triggers DispatcherTest $dispatcher, array('request' => $request) * @triggers DispatcherTest $dispatcher, array('request' => $request) */ public function testHttpMethodOverrides() { Router::reload(); Router::mapResources('Posts'); $_SERVER['REQUEST_METHOD'] = 'POST'; $dispatcher = new Dispatcher(); $request = new CakeRequest('/posts'); $event = new CakeEvent('DispatcherTest', $dispatcher, array('request' => $request)); $dispatcher->parseParams($event); $expected = array('pass' => array(), 'named' => array(), 'plugin' => null, 'controller' => 'posts', 'action' => 'add', '[method]' => 'POST'); foreach ($expected as $key => $value) { $this->assertEquals($value, $request[$key], 'Value mismatch for ' . $key . ' %s'); } $_SERVER['REQUEST_METHOD'] = 'GET'; $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; $request = new CakeRequest('/posts/5'); $event = new CakeEvent('DispatcherTest', $dispatcher, array('request' => $request)); $dispatcher->parseParams($event); $expected = array( 'pass' => array('5'), 'named' => array(), 'id' => '5', 'plugin' => null, 'controller' => 'posts', 'action' => 'edit', '[method]' => 'PUT' ); foreach ($expected as $key => $value) { $this->assertEquals($value, $request[$key], 'Value mismatch for ' . $key . ' %s'); } unset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']); $_SERVER['REQUEST_METHOD'] = 'GET'; $request = new CakeRequest('/posts/5'); $event = new CakeEvent('DispatcherTest', $dispatcher, array('request' => $request)); $dispatcher->parseParams($event); $expected = array('pass' => array('5'), 'named' => array(), 'id' => '5', 'plugin' => null, 'controller' => 'posts', 'action' => 'view', '[method]' => 'GET'); foreach ($expected as $key => $value) { $this->assertEquals($value, $request[$key], 'Value mismatch for ' . $key . ' %s'); } $_POST['_method'] = 'PUT'; $request = new CakeRequest('/posts/5'); $event = new CakeEvent('DispatcherTest', $dispatcher, array('request' => $request)); $dispatcher->parseParams($event); $expected = array('pass' => array('5'), 'named' => array(), 'id' => '5', 'plugin' => null, 'controller' => 'posts', 'action' => 'edit', '[method]' => 'PUT'); foreach ($expected as $key => $value) { $this->assertEquals($value, $request[$key], 'Value mismatch for ' . $key . ' %s'); } $_POST['_method'] = 'POST'; $_POST['data'] = array('Post' => array('title' => 'New Post')); $_POST['extra'] = 'data'; $_SERVER = array(); $request = new CakeRequest('/posts'); $event = new CakeEvent('DispatcherTest', $dispatcher, array('request' => $request)); $dispatcher->parseParams($event); $expected = array( 'pass' => array(), 'named' => array(), 'plugin' => null, 'controller' => 'posts', 'action' => 'add', '[method]' => 'POST', 'data' => array('extra' => 'data', 'Post' => array('title' => 'New Post')), ); foreach ($expected as $key => $value) { $this->assertEquals($value, $request[$key], 'Value mismatch for ' . $key . ' %s'); } unset($_POST['_method']); } /** * cachePath method * * @param string $here * @return string */ protected function _cachePath($here) { $path = $here; if ($here === '/') { $path = 'home'; } $path = strtolower(Inflector::slug($path)); $filename = CACHE . 'views' . DS . $path . '.php'; if (!file_exists($filename)) { $filename = CACHE . 'views' . DS . $path . '_index.php'; } return $filename; } } cakephp-2.8.0/lib/Cake/Test/Case/Routing/Filter/000077500000000000000000000000001265552240500212215ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Routing/Filter/AssetDispatcherTest.php000066400000000000000000000227561265552240500256740ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/view/1196/Testing CakePHP(tm) Tests * @package Cake.Test.Case.Routing.Filter * @since CakePHP(tm) v 2.2 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('AssetDispatcher', 'Routing/Filter'); App::uses('CakeEvent', 'Event'); App::uses('CakeResponse', 'Network'); /** * Class AssetDispatcherTest * * @package Cake.Test.Case.Routing.Filter */ class AssetDispatcherTest extends CakeTestCase { /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); Configure::write('Dispatcher.filters', array()); } /** * test that asset filters work for theme and plugin assets * * @return void * @triggers DispatcherTest $this, compact('request', 'response') * @triggers DispatcherTest $this, compact('request', 'response') * @triggers DispatcherTest $this, compact('request', 'response') * @triggers DispatcherTest $this, compact('request', 'response') * @triggers DispatcherTest $this, compact('request', 'response') * @triggers DispatcherTest $this, compact('request', 'response') */ public function testAssetFilterForThemeAndPlugins() { $filter = new AssetDispatcher(); $response = $this->getMock('CakeResponse', array('_sendHeader')); Configure::write('Asset.filter', array( 'js' => '', 'css' => '' )); App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) ), App::RESET); $request = new CakeRequest('theme/test_theme/ccss/cake.generic.css'); $event = new CakeEvent('DispatcherTest', $this, compact('request', 'response')); $this->assertSame($response, $filter->beforeDispatch($event)); $this->assertTrue($event->isStopped()); $request = new CakeRequest('theme/test_theme/cjs/debug_kit.js'); $event = new CakeEvent('DispatcherTest', $this, compact('request', 'response')); $this->assertSame($response, $filter->beforeDispatch($event)); $this->assertTrue($event->isStopped()); $request = new CakeRequest('test_plugin/ccss/cake.generic.css'); $event = new CakeEvent('DispatcherTest', $this, compact('request', 'response')); $this->assertSame($response, $filter->beforeDispatch($event)); $this->assertTrue($event->isStopped()); $request = new CakeRequest('test_plugin/cjs/debug_kit.js'); $event = new CakeEvent('DispatcherTest', $this, compact('request', 'response')); $this->assertSame($response, $filter->beforeDispatch($event)); $this->assertTrue($event->isStopped()); $request = new CakeRequest('css/ccss/debug_kit.css'); $event = new CakeEvent('DispatcherTest', $this, compact('request', 'response')); $this->assertNull($filter->beforeDispatch($event)); $this->assertFalse($event->isStopped()); $request = new CakeRequest('js/cjs/debug_kit.js'); $event = new CakeEvent('DispatcherTest', $this, compact('request', 'response')); $this->assertNull($filter->beforeDispatch($event)); $this->assertFalse($event->isStopped()); } /** * AssetDispatcher should not 404 extensions that could be handled * by Routing. * * @return void * @triggers DispatcherTest $this, compact('request', 'response') */ public function testNoHandleRoutedExtension() { $filter = new AssetDispatcher(); $response = $this->getMock('CakeResponse', array('_sendHeader')); Configure::write('Asset.filter', array( 'js' => '', 'css' => '' )); App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) ), App::RESET); Router::parseExtensions('json'); Router::connect('/test_plugin/api/v1/:action', array('controller' => 'api')); CakePlugin::load('TestPlugin'); $request = new CakeRequest('test_plugin/api/v1/forwarding.json'); $event = new CakeEvent('DispatcherTest', $this, compact('request', 'response')); $this->assertNull($filter->beforeDispatch($event)); $this->assertFalse($event->isStopped(), 'Events for routed extensions should not be stopped'); } /** * Tests that $response->checkNotModified() is called and bypasses * file dispatching * * @return void * @triggers DispatcherTest $this, compact('request', 'response') * @triggers DispatcherTest $this, compact('request', 'response') */ public function testNotModified() { $filter = new AssetDispatcher(); Configure::write('Asset.filter', array( 'js' => '', 'css' => '' )); App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); $time = filemtime(App::themePath('TestTheme') . 'webroot' . DS . 'img' . DS . 'cake.power.gif'); $time = new DateTime('@' . $time); $response = $this->getMock('CakeResponse', array('send', 'checkNotModified')); $request = new CakeRequest('theme/test_theme/img/cake.power.gif'); $response->expects($this->once())->method('checkNotModified') ->with($request) ->will($this->returnValue(true)); $event = new CakeEvent('DispatcherTest', $this, compact('request', 'response')); ob_start(); $this->assertSame($response, $filter->beforeDispatch($event)); ob_end_clean(); $this->assertEquals(200, $response->statusCode()); $this->assertEquals($time->format('D, j M Y H:i:s') . ' GMT', $response->modified()); $response = $this->getMock('CakeResponse', array('_sendHeader', 'checkNotModified')); $request = new CakeRequest('theme/test_theme/img/cake.power.gif'); $response->expects($this->once())->method('checkNotModified') ->with($request) ->will($this->returnValue(true)); $response->expects($this->never())->method('send'); $event = new CakeEvent('DispatcherTest', $this, compact('request', 'response')); $this->assertSame($response, $filter->beforeDispatch($event)); $this->assertEquals($time->format('D, j M Y H:i:s') . ' GMT', $response->modified()); } /** * Test that no exceptions are thrown for //index.php type URLs. * * @return void * @triggers Dispatcher.beforeRequest $this, compact('request', 'response') */ public function test404OnDoubleSlash() { $filter = new AssetDispatcher(); $response = $this->getMock('CakeResponse', array('_sendHeader')); $request = new CakeRequest('//index.php'); $event = new CakeEvent('Dispatcher.beforeRequest', $this, compact('request', 'response')); $this->assertNull($filter->beforeDispatch($event)); $this->assertFalse($event->isStopped()); } /** * Test that attempts to traverse directories are prevented. * * @return void * @triggers Dispatcher.beforeRequest $this, compact('request', 'response') */ public function test404OnDoubleDot() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) ), App::RESET); $response = $this->getMock('CakeResponse', array('_sendHeader')); $request = new CakeRequest('theme/test_theme/../../../../../../VERSION.txt'); $event = new CakeEvent('Dispatcher.beforeRequest', $this, compact('request', 'response')); $response->expects($this->never())->method('send'); $filter = new AssetDispatcher(); $this->assertNull($filter->beforeDispatch($event)); $this->assertFalse($event->isStopped()); } /** * Test that attempts to traverse directories with urlencoded paths fail. * * @return void * @triggers Dispatcher.beforeRequest $this, compact('request', 'response') */ public function test404OnDoubleDotEncoded() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) ), App::RESET); $response = $this->getMock('CakeResponse', array('_sendHeader', 'send')); $request = new CakeRequest('theme/test_theme/%2e./%2e./%2e./%2e./%2e./%2e./VERSION.txt'); $event = new CakeEvent('Dispatcher.beforeRequest', $this, compact('request', 'response')); $response->expects($this->never())->method('send'); $filter = new AssetDispatcher(); $this->assertNull($filter->beforeDispatch($event)); $this->assertFalse($event->isStopped()); } /** * Test asset content length is unset * * If content length is unset, then the webserver can figure it out. * * @outputBuffering enabled * @return void */ public function testAssetContentLength() { Router::reload(); Configure::write('Dispatcher.filters', array('AssetDispatcher')); App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); $url = 'theme/test_theme/css/test_asset.css'; $file = 'View/Themed/TestTheme/webroot/css/test_asset.css'; $request = new CakeRequest($url); $response = $this->getMock('CakeResponse', array('_sendHeader', 'send')); $event = new CakeEvent('Dispatcher.beforeRequest', $this, compact('request', 'response')); $filter = new AssetDispatcher(); $filter->beforeDispatch($event); $result = ob_get_clean(); $path = CAKE . 'Test' . DS . 'test_app' . DS . str_replace('/', DS, $file); $file = file_get_contents($path); $this->assertEquals($file, $result); $headers = $response->header(); $this->assertFalse($headers['Content-Length']); } } cakephp-2.8.0/lib/Cake/Test/Case/Routing/Route/000077500000000000000000000000001265552240500210725ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Routing/Route/CakeRouteTest.php000066400000000000000000000772631265552240500243440ustar00rootroot00000000000000 null, 'prefixes' => array())); } /** * Test the construction of a CakeRoute * * @return void */ public function testConstruction() { $route = new CakeRoute('/:controller/:action/:id', array(), array('id' => '[0-9]+')); $this->assertEquals('/:controller/:action/:id', $route->template); $this->assertEquals(array(), $route->defaults); $this->assertEquals(array('id' => '[0-9]+'), $route->options); $this->assertFalse($route->compiled()); } /** * test Route compiling. * * @return void */ public function testBasicRouteCompiling() { $route = new CakeRoute('/', array('controller' => 'pages', 'action' => 'display', 'home')); $result = $route->compile(); $expected = '#^/*$#'; $this->assertEquals($expected, $result); $this->assertEquals(array(), $route->keys); $route = new CakeRoute('/:controller/:action', array('controller' => 'posts')); $result = $route->compile(); $this->assertRegExp($result, '/posts/edit'); $this->assertRegExp($result, '/posts/super_delete'); $this->assertNotRegExp($result, '/posts'); $this->assertNotRegExp($result, '/posts/super_delete/1'); $route = new CakeRoute('/posts/foo:id', array('controller' => 'posts', 'action' => 'view')); $result = $route->compile(); $this->assertRegExp($result, '/posts/foo:1'); $this->assertRegExp($result, '/posts/foo:param'); $this->assertNotRegExp($result, '/posts'); $this->assertNotRegExp($result, '/posts/'); $this->assertEquals(array('id'), $route->keys); $route = new CakeRoute('/:plugin/:controller/:action/*', array('plugin' => 'test_plugin', 'action' => 'index')); $result = $route->compile(); $this->assertRegExp($result, '/test_plugin/posts/index'); $this->assertRegExp($result, '/test_plugin/posts/edit/5'); $this->assertRegExp($result, '/test_plugin/posts/edit/5/name:value/nick:name'); } /** * test that route parameters that overlap don't cause errors. * * @return void */ public function testRouteParameterOverlap() { $route = new CakeRoute('/invoices/add/:idd/:id', array('controller' => 'invoices', 'action' => 'add')); $result = $route->compile(); $this->assertRegExp($result, '/invoices/add/1/3'); $route = new CakeRoute('/invoices/add/:id/:idd', array('controller' => 'invoices', 'action' => 'add')); $result = $route->compile(); $this->assertRegExp($result, '/invoices/add/1/3'); } /** * test compiling routes with keys that have patterns * * @return void */ public function testRouteCompilingWithParamPatterns() { $route = new CakeRoute( '/:controller/:action/:id', array(), array('id' => Router::ID) ); $result = $route->compile(); $this->assertRegExp($result, '/posts/edit/1'); $this->assertRegExp($result, '/posts/view/518098'); $this->assertNotRegExp($result, '/posts/edit/name-of-post'); $this->assertNotRegExp($result, '/posts/edit/4/other:param'); $this->assertEquals(array('id', 'controller', 'action'), $route->keys); $route = new CakeRoute( '/:lang/:controller/:action/:id', array('controller' => 'testing4'), array('id' => Router::ID, 'lang' => '[a-z]{3}') ); $result = $route->compile(); $this->assertRegExp($result, '/eng/posts/edit/1'); $this->assertRegExp($result, '/cze/articles/view/1'); $this->assertNotRegExp($result, '/language/articles/view/2'); $this->assertNotRegExp($result, '/eng/articles/view/name-of-article'); $this->assertEquals(array('lang', 'id', 'controller', 'action'), $route->keys); foreach (array(':', '@', ';', '$', '-') as $delim) { $route = new CakeRoute('/posts/:id' . $delim . ':title'); $result = $route->compile(); $this->assertRegExp($result, '/posts/1' . $delim . 'name-of-article'); $this->assertRegExp($result, '/posts/13244' . $delim . 'name-of_Article[]'); $this->assertNotRegExp($result, '/posts/11!nameofarticle'); $this->assertNotRegExp($result, '/posts/11'); $this->assertEquals(array('title', 'id'), $route->keys); } $route = new CakeRoute( '/posts/:id::title/:year', array('controller' => 'posts', 'action' => 'view'), array('id' => Router::ID, 'year' => Router::YEAR, 'title' => '[a-z-_]+') ); $result = $route->compile(); $this->assertRegExp($result, '/posts/1:name-of-article/2009/'); $this->assertRegExp($result, '/posts/13244:name-of-article/1999'); $this->assertNotRegExp($result, '/posts/hey_now:nameofarticle'); $this->assertNotRegExp($result, '/posts/:nameofarticle/2009'); $this->assertNotRegExp($result, '/posts/:nameofarticle/01'); $this->assertEquals(array('year', 'title', 'id'), $route->keys); $route = new CakeRoute( '/posts/:url_title-(uuid::id)', array('controller' => 'posts', 'action' => 'view'), array('pass' => array('id', 'url_title'), 'id' => Router::ID) ); $result = $route->compile(); $this->assertRegExp($result, '/posts/some_title_for_article-(uuid:12534)/'); $this->assertRegExp($result, '/posts/some_title_for_article-(uuid:12534)'); $this->assertNotRegExp($result, '/posts/'); $this->assertNotRegExp($result, '/posts/nameofarticle'); $this->assertNotRegExp($result, '/posts/nameofarticle-12347'); $this->assertEquals(array('url_title', 'id'), $route->keys); } /** * test more complex route compiling & parsing with mid route greedy stars * and optional routing parameters * * @return void */ public function testComplexRouteCompilingAndParsing() { $route = new CakeRoute( '/posts/:month/:day/:year/*', array('controller' => 'posts', 'action' => 'view'), array('year' => Router::YEAR, 'month' => Router::MONTH, 'day' => Router::DAY) ); $result = $route->compile(); $this->assertRegExp($result, '/posts/08/01/2007/title-of-post'); $result = $route->parse('/posts/08/01/2007/title-of-post'); $this->assertEquals(7, count($result)); $this->assertEquals('posts', $result['controller']); $this->assertEquals('view', $result['action']); $this->assertEquals('2007', $result['year']); $this->assertEquals('08', $result['month']); $this->assertEquals('01', $result['day']); $this->assertEquals('title-of-post', $result['pass'][0]); $route = new CakeRoute( "/:extra/page/:slug/*", array('controller' => 'pages', 'action' => 'view', 'extra' => null), array("extra" => '[a-z1-9_]*', "slug" => '[a-z1-9_]+', "action" => 'view') ); $result = $route->compile(); $this->assertRegExp($result, '/some_extra/page/this_is_the_slug'); $this->assertRegExp($result, '/page/this_is_the_slug'); $this->assertEquals(array('slug', 'extra'), $route->keys); $this->assertEquals(array('extra' => '[a-z1-9_]*', 'slug' => '[a-z1-9_]+', 'action' => 'view'), $route->options); $expected = array( 'controller' => 'pages', 'action' => 'view' ); $this->assertEquals($expected, $route->defaults); $route = new CakeRoute( '/:controller/:action/*', array('project' => false), array( 'controller' => 'source|wiki|commits|tickets|comments|view', 'action' => 'branches|history|branch|logs|view|start|add|edit|modify' ) ); $this->assertFalse($route->parse('/chaw_test/wiki')); $result = $route->compile(); $this->assertNotRegExp($result, '/some_project/source'); $this->assertRegExp($result, '/source/view'); $this->assertRegExp($result, '/source/view/other/params'); $this->assertNotRegExp($result, '/chaw_test/wiki'); $this->assertNotRegExp($result, '/source/wierd_action'); } /** * test that routes match their pattern. * * @return void */ public function testMatchBasic() { $route = new CakeRoute('/:controller/:action/:id', array('plugin' => null)); $result = $route->match(array('controller' => 'posts', 'action' => 'view', 'plugin' => null)); $this->assertFalse($result); $result = $route->match(array('plugin' => null, 'controller' => 'posts', 'action' => 'view', 0)); $this->assertFalse($result); $result = $route->match(array('plugin' => null, 'controller' => 'posts', 'action' => 'view', 'id' => 1)); $this->assertEquals('/posts/view/1', $result); $route = new CakeRoute('/', array('controller' => 'pages', 'action' => 'display', 'home')); $result = $route->match(array('controller' => 'pages', 'action' => 'display', 'home')); $this->assertEquals('/', $result); $result = $route->match(array('controller' => 'pages', 'action' => 'display', 'about')); $this->assertFalse($result); $route = new CakeRoute('/pages/*', array('controller' => 'pages', 'action' => 'display')); $result = $route->match(array('controller' => 'pages', 'action' => 'display', 'home')); $this->assertEquals('/pages/home', $result); $result = $route->match(array('controller' => 'pages', 'action' => 'display', 'about')); $this->assertEquals('/pages/about', $result); $route = new CakeRoute('/blog/:action', array('controller' => 'posts')); $result = $route->match(array('controller' => 'posts', 'action' => 'view')); $this->assertEquals('/blog/view', $result); $result = $route->match(array('controller' => 'nodes', 'action' => 'view')); $this->assertFalse($result); $result = $route->match(array('controller' => 'posts', 'action' => 'view', 1)); $this->assertFalse($result); $result = $route->match(array('controller' => 'posts', 'action' => 'view', 'id' => 2)); $this->assertFalse($result); $route = new CakeRoute('/foo/:controller/:action', array('action' => 'index')); $result = $route->match(array('controller' => 'posts', 'action' => 'view')); $this->assertEquals('/foo/posts/view', $result); $route = new CakeRoute('/:plugin/:id/*', array('controller' => 'posts', 'action' => 'view')); $result = $route->match(array('plugin' => 'test', 'controller' => 'posts', 'action' => 'view', 'id' => '1')); $this->assertEquals('/test/1/', $result); $result = $route->match(array('plugin' => 'fo', 'controller' => 'posts', 'action' => 'view', 'id' => '1', '0')); $this->assertEquals('/fo/1/0', $result); $result = $route->match(array('plugin' => 'fo', 'controller' => 'nodes', 'action' => 'view', 'id' => 1)); $this->assertFalse($result); $result = $route->match(array('plugin' => 'fo', 'controller' => 'posts', 'action' => 'edit', 'id' => 1)); $this->assertFalse($result); $route = new CakeRoute('/admin/subscriptions/:action/*', array( 'controller' => 'subscribe', 'admin' => true, 'prefix' => 'admin' )); $url = array('controller' => 'subscribe', 'admin' => true, 'action' => 'edit', 1); $result = $route->match($url); $expected = '/admin/subscriptions/edit/1'; $this->assertEquals($expected, $result); $url = array( 'controller' => 'subscribe', 'admin' => true, 'action' => 'edit_admin_e', 1 ); $result = $route->match($url); $expected = '/admin/subscriptions/edit_admin_e/1'; $this->assertEquals($expected, $result); $url = array('controller' => 'subscribe', 'admin' => true, 'action' => 'admin_edit', 1); $result = $route->match($url); $expected = '/admin/subscriptions/edit/1'; $this->assertEquals($expected, $result); } /** * test that non-greedy routes fail with extra passed args * * @return void */ public function testGreedyRouteFailurePassedArg() { $route = new CakeRoute('/:controller/:action', array('plugin' => null)); $result = $route->match(array('controller' => 'posts', 'action' => 'view', '0')); $this->assertFalse($result); $route = new CakeRoute('/:controller/:action', array('plugin' => null)); $result = $route->match(array('controller' => 'posts', 'action' => 'view', 'test')); $this->assertFalse($result); } /** * test that non-greedy routes fail with extra passed args * * @return void */ public function testGreedyRouteFailureNamedParam() { $route = new CakeRoute('/:controller/:action', array('plugin' => null)); $result = $route->match(array('controller' => 'posts', 'action' => 'view', 'page' => 1)); $this->assertFalse($result); } /** * test that falsey values do not interrupt a match. * * @return void */ public function testMatchWithFalseyValues() { $route = new CakeRoute('/:controller/:action/*', array('plugin' => null)); $result = $route->match(array( 'controller' => 'posts', 'action' => 'index', 'plugin' => null, 'admin' => false )); $this->assertEquals('/posts/index/', $result); } /** * test match() with greedy routes, named parameters and passed args. * * @return void */ public function testMatchWithNamedParametersAndPassedArgs() { Router::connectNamed(true); $route = new CakeRoute('/:controller/:action/*', array('plugin' => null)); $result = $route->match(array('controller' => 'posts', 'action' => 'index', 'plugin' => null, 'page' => 1)); $this->assertEquals('/posts/index/page:1', $result); $result = $route->match(array('controller' => 'posts', 'action' => 'view', 'plugin' => null, 5)); $this->assertEquals('/posts/view/5', $result); $result = $route->match(array('controller' => 'posts', 'action' => 'view', 'plugin' => null, 0)); $this->assertEquals('/posts/view/0', $result); $result = $route->match(array('controller' => 'posts', 'action' => 'view', 'plugin' => null, '0')); $this->assertEquals('/posts/view/0', $result); $result = $route->match(array('controller' => 'posts', 'action' => 'view', 'plugin' => null, 5, 'page' => 1, 'limit' => 20, 'order' => 'title')); $this->assertEquals('/posts/view/5/page:1/limit:20/order:title', $result); $result = $route->match(array('controller' => 'posts', 'action' => 'view', 'plugin' => null, 'word space', 'order' => 'ฮ˜')); $this->assertEquals('/posts/view/word%20space/order:%CE%98', $result); $route = new CakeRoute('/test2/*', array('controller' => 'pages', 'action' => 'display', 2)); $result = $route->match(array('controller' => 'pages', 'action' => 'display', 1)); $this->assertFalse($result); $result = $route->match(array('controller' => 'pages', 'action' => 'display', 2, 'something')); $this->assertEquals('/test2/something', $result); $result = $route->match(array('controller' => 'pages', 'action' => 'display', 5, 'something')); $this->assertFalse($result); } /** * Ensure that named parameters are urldecoded * * @return void */ public function testParseNamedParametersUrlDecode() { Router::connectNamed(true); $route = new CakeRoute('/:controller/:action/*', array('plugin' => null)); $result = $route->parse('/posts/index/page:%CE%98'); $this->assertEquals('ฮ˜', $result['named']['page']); $result = $route->parse('/posts/index/page[]:%CE%98'); $this->assertEquals('ฮ˜', $result['named']['page'][0]); $result = $route->parse('/posts/index/something%20else/page[]:%CE%98'); $this->assertEquals('ฮ˜', $result['named']['page'][0]); $this->assertEquals('something else', $result['pass'][0]); } /** * Ensure that keys at named parameters are urldecoded * * @return void */ public function testParseNamedKeyUrlDecode() { Router::connectNamed(true); $route = new CakeRoute('/:controller/:action/*', array('plugin' => null)); // checking /post/index/user[0]:a/user[1]:b $result = $route->parse('/posts/index/user%5B0%5D:a/user%5B1%5D:b'); $this->assertArrayHasKey('user', $result['named']); $this->assertEquals(array('a', 'b'), $result['named']['user']); // checking /post/index/user[]:a/user[]:b $result = $route->parse('/posts/index/user%5B%5D:a/user%5B%5D:b'); $this->assertArrayHasKey('user', $result['named']); $this->assertEquals(array('a', 'b'), $result['named']['user']); } /** * test that named params with null/false are excluded * * @return void */ public function testNamedParamsWithNullFalse() { $route = new CakeRoute('/:controller/:action/*'); $result = $route->match(array('controller' => 'posts', 'action' => 'index', 'page' => null, 'sort' => false)); $this->assertEquals('/posts/index/', $result); } /** * test that match with patterns works. * * @return void */ public function testMatchWithPatterns() { $route = new CakeRoute('/:controller/:action/:id', array('plugin' => null), array('id' => '[0-9]+')); $result = $route->match(array('controller' => 'posts', 'action' => 'view', 'id' => 'foo')); $this->assertFalse($result); $result = $route->match(array('plugin' => null, 'controller' => 'posts', 'action' => 'view', 'id' => '9')); $this->assertEquals('/posts/view/9', $result); $result = $route->match(array('plugin' => null, 'controller' => 'posts', 'action' => 'view', 'id' => '922')); $this->assertEquals('/posts/view/922', $result); $result = $route->match(array('plugin' => null, 'controller' => 'posts', 'action' => 'view', 'id' => 'a99')); $this->assertFalse($result); } /** * test persistParams ability to persist parameters from $params and remove params. * * @return void */ public function testPersistParams() { $route = new CakeRoute( '/:lang/:color/blog/:action', array('controller' => 'posts'), array('persist' => array('lang', 'color')) ); $url = array('controller' => 'posts', 'action' => 'index'); $params = array('lang' => 'en', 'color' => 'blue'); $result = $route->persistParams($url, $params); $this->assertEquals('en', $result['lang']); $this->assertEquals('blue', $result['color']); $url = array('controller' => 'posts', 'action' => 'index', 'color' => 'red'); $params = array('lang' => 'en', 'color' => 'blue'); $result = $route->persistParams($url, $params); $this->assertEquals('en', $result['lang']); $this->assertEquals('red', $result['color']); } /** * test persist with a non array value * * @return void */ public function testPersistParamsNonArray() { $url = array('controller' => 'posts', 'action' => 'index'); $params = array('lang' => 'en', 'color' => 'blue'); $route = new CakeRoute( '/:lang/:color/blog/:action', array('controller' => 'posts') // No persist options ); $result = $route->persistParams($url, $params); $this->assertEquals($url, $result); $route = new CakeRoute( '/:lang/:color/blog/:action', array('controller' => 'posts'), array('persist' => false) ); $result = $route->persistParams($url, $params); $this->assertEquals($url, $result); $route = new CakeRoute( '/:lang/:color/blog/:action', array('controller' => 'posts'), array('persist' => 'derp') ); $result = $route->persistParams($url, $params); $this->assertEquals($url, $result); } /** * test the parse method of CakeRoute. * * @return void */ public function testParse() { $route = new CakeRoute( '/:controller/:action/:id', array('controller' => 'testing4', 'id' => null), array('id' => Router::ID) ); $route->compile(); $result = $route->parse('/posts/view/1'); $this->assertEquals('posts', $result['controller']); $this->assertEquals('view', $result['action']); $this->assertEquals('1', $result['id']); $route = new Cakeroute( '/admin/:controller', array('prefix' => 'admin', 'admin' => 1, 'action' => 'index') ); $route->compile(); $result = $route->parse('/admin/'); $this->assertFalse($result); $result = $route->parse('/admin/posts'); $this->assertEquals('posts', $result['controller']); $this->assertEquals('index', $result['action']); } /** * Test that :key elements are urldecoded * * @return void */ public function testParseUrlDecodeElements() { $route = new Cakeroute( '/:controller/:slug', array('action' => 'view') ); $route->compile(); $result = $route->parse('/posts/%E2%88%82%E2%88%82'); $this->assertEquals('posts', $result['controller']); $this->assertEquals('view', $result['action']); $this->assertEquals('โˆ‚โˆ‚', $result['slug']); $result = $route->parse('/posts/โˆ‚โˆ‚'); $this->assertEquals('posts', $result['controller']); $this->assertEquals('view', $result['action']); $this->assertEquals('โˆ‚โˆ‚', $result['slug']); } /** * test numerically indexed defaults, get appended to pass * * @return void */ public function testParseWithPassDefaults() { $route = new Cakeroute('/:controller', array('action' => 'display', 'home')); $result = $route->parse('/posts'); $expected = array( 'controller' => 'posts', 'action' => 'display', 'pass' => array('home'), 'named' => array() ); $this->assertEquals($expected, $result); } /** * test that http header conditions can cause route failures. * * @return void */ public function testParseWithHttpHeaderConditions() { $_SERVER['REQUEST_METHOD'] = 'GET'; $route = new CakeRoute('/sample', array('controller' => 'posts', 'action' => 'index', '[method]' => 'POST')); $this->assertFalse($route->parse('/sample')); } /** * test that patterns work for :action * * @return void */ public function testPatternOnAction() { $route = new CakeRoute( '/blog/:action/*', array('controller' => 'blog_posts'), array('action' => 'other|actions') ); $result = $route->match(array('controller' => 'blog_posts', 'action' => 'foo')); $this->assertFalse($result); $result = $route->match(array('controller' => 'blog_posts', 'action' => 'actions')); $this->assertNotEmpty($result); $result = $route->parse('/blog/other'); $expected = array('controller' => 'blog_posts', 'action' => 'other', 'pass' => array(), 'named' => array()); $this->assertEquals($expected, $result); $result = $route->parse('/blog/foobar'); $this->assertFalse($result); } /** * test the parseArgs method * * @return void */ public function testParsePassedArgument() { $route = new CakeRoute('/:controller/:action/*'); $result = $route->parse('/posts/edit/1/2/0'); $expected = array( 'controller' => 'posts', 'action' => 'edit', 'pass' => array('1', '2', '0'), 'named' => array() ); $this->assertEquals($expected, $result); $result = $route->parse('/posts/edit/a-string/page:1/sort:value'); $expected = array( 'controller' => 'posts', 'action' => 'edit', 'pass' => array('a-string'), 'named' => array( 'page' => 1, 'sort' => 'value' ) ); $this->assertEquals($expected, $result); } /** * test that only named parameter rules are followed. * * @return void */ public function testParseNamedParametersWithRules() { $route = new CakeRoute('/:controller/:action/*', array(), array( 'named' => array( 'wibble', 'fish' => array('action' => 'index'), 'fizz' => array('controller' => array('comments', 'other')), 'pattern' => 'val-[\d]+' ) )); $result = $route->parse('/posts/display/wibble:spin/fish:trout/fizz:buzz/unknown:value'); $expected = array( 'controller' => 'posts', 'action' => 'display', 'pass' => array('fish:trout', 'fizz:buzz', 'unknown:value'), 'named' => array( 'wibble' => 'spin' ) ); $this->assertEquals($expected, $result, 'Fish should not be parsed, as action != index'); $result = $route->parse('/posts/index/wibble:spin/fish:trout/fizz:buzz'); $expected = array( 'controller' => 'posts', 'action' => 'index', 'pass' => array('fizz:buzz'), 'named' => array( 'wibble' => 'spin', 'fish' => 'trout' ) ); $this->assertEquals($expected, $result, 'Fizz should be parsed, as controller == comments|other'); $result = $route->parse('/comments/index/wibble:spin/fish:trout/fizz:buzz'); $expected = array( 'controller' => 'comments', 'action' => 'index', 'pass' => array(), 'named' => array( 'wibble' => 'spin', 'fish' => 'trout', 'fizz' => 'buzz' ) ); $this->assertEquals($expected, $result, 'All params should be parsed as conditions were met.'); $result = $route->parse('/comments/index/pattern:val--'); $expected = array( 'controller' => 'comments', 'action' => 'index', 'pass' => array('pattern:val--'), 'named' => array() ); $this->assertEquals($expected, $result, 'Named parameter pattern unmet.'); $result = $route->parse('/comments/index/pattern:val-2'); $expected = array( 'controller' => 'comments', 'action' => 'index', 'pass' => array(), 'named' => array('pattern' => 'val-2') ); $this->assertEquals($expected, $result, 'Named parameter pattern met.'); } /** * test that greedyNamed ignores rules. * * @return void */ public function testParseGreedyNamed() { $route = new CakeRoute('/:controller/:action/*', array(), array( 'named' => array( 'fizz' => array('controller' => 'comments'), 'pattern' => 'val-[\d]+', ), 'greedyNamed' => true )); $result = $route->parse('/posts/display/wibble:spin/fizz:buzz/pattern:ignored'); $expected = array( 'controller' => 'posts', 'action' => 'display', 'pass' => array('fizz:buzz', 'pattern:ignored'), 'named' => array( 'wibble' => 'spin', ) ); $this->assertEquals($expected, $result, 'Greedy named grabs everything, rules are followed'); } /** * Having greedNamed enabled should not capture routing.prefixes. * * @return void */ public function testMatchGreedyNamedExcludesPrefixes() { Configure::write('Routing.prefixes', array('admin')); Router::reload(); $route = new CakeRoute('/sales/*', array('controller' => 'sales', 'action' => 'index')); $this->assertFalse($route->match(array('controller' => 'sales', 'action' => 'index', 'admin' => 1)), 'Greedy named consume routing prefixes.'); } /** * test that parsing array format named parameters works * * @return void */ public function testParseArrayNamedParameters() { $route = new CakeRoute('/:controller/:action/*'); $result = $route->parse('/tests/action/var[]:val1/var[]:val2'); $expected = array( 'controller' => 'tests', 'action' => 'action', 'named' => array( 'var' => array( 'val1', 'val2' ) ), 'pass' => array(), ); $this->assertEquals($expected, $result); $result = $route->parse('/tests/action/theanswer[is]:42/var[]:val2/var[]:val3'); $expected = array( 'controller' => 'tests', 'action' => 'action', 'named' => array( 'theanswer' => array( 'is' => 42 ), 'var' => array( 'val2', 'val3' ) ), 'pass' => array(), ); $this->assertEquals($expected, $result); $result = $route->parse('/tests/action/theanswer[is][not]:42/theanswer[]:5/theanswer[is]:6'); $expected = array( 'controller' => 'tests', 'action' => 'action', 'named' => array( 'theanswer' => array( 5, 'is' => array( 6, 'not' => 42 ) ), ), 'pass' => array(), ); $this->assertEquals($expected, $result); } /** * Test that match can handle array named parameters * * @return void */ public function testMatchNamedParametersArray() { $route = new CakeRoute('/:controller/:action/*'); $url = array( 'controller' => 'posts', 'action' => 'index', 'filter' => array( 'one', 'model' => 'value' ) ); $result = $route->match($url); $expected = '/posts/index/filter%5B0%5D:one/filter%5Bmodel%5D:value'; $this->assertEquals($expected, $result); $url = array( 'controller' => 'posts', 'action' => 'index', 'filter' => array( 'one', 'model' => array( 'two', 'order' => 'field' ) ) ); $result = $route->match($url); $expected = '/posts/index/filter%5B0%5D:one/filter%5Bmodel%5D%5B0%5D:two/filter%5Bmodel%5D%5Border%5D:field'; $this->assertEquals($expected, $result); } /** * Test matching of parameters where one parameter name starts with another parameter name * * @return void */ public function testMatchSimilarParameters() { $route = new CakeRoute('/:thisParam/:thisParamIsLonger'); $url = array( 'thisParamIsLonger' => 'bar', 'thisParam' => 'foo', ); $result = $route->match($url); $expected = '/foo/bar'; $this->assertEquals($expected, $result); } /** * Test match() with trailing ** style routes. * * @return void */ public function testMatchTrailing() { $route = new CakeRoute('/pages/**', array('controller' => 'pages', 'action' => 'display')); $id = 'test/ spaces/ๆผขๅญ—/laโ€ รฎn'; $result = $route->match(array( 'controller' => 'pages', 'action' => 'display', $id )); $expected = '/pages/test/%20spaces/%E6%BC%A2%E5%AD%97/la%E2%80%A0%C3%AEn'; $this->assertEquals($expected, $result); } /** * test restructuring args with pass key * * @return void */ public function testPassArgRestructure() { $route = new CakeRoute('/:controller/:action/:slug', array(), array( 'pass' => array('slug') )); $result = $route->parse('/posts/view/my-title'); $expected = array( 'controller' => 'posts', 'action' => 'view', 'slug' => 'my-title', 'pass' => array('my-title'), 'named' => array() ); $this->assertEquals($expected, $result, 'Slug should have moved'); } /** * Test the /** special type on parsing. * * @return void */ public function testParseTrailing() { $route = new CakeRoute('/:controller/:action/**'); $result = $route->parse('/posts/index/1/2/3/foo:bar'); $expected = array( 'controller' => 'posts', 'action' => 'index', 'pass' => array('1/2/3/foo:bar'), 'named' => array() ); $this->assertEquals($expected, $result); $result = $route->parse('/posts/index/http://example.com'); $expected = array( 'controller' => 'posts', 'action' => 'index', 'pass' => array('http://example.com'), 'named' => array() ); $this->assertEquals($expected, $result); } /** * Test the /** special type on parsing - UTF8. * * @return void */ public function testParseTrailingUTF8() { $route = new CakeRoute('/category/**', array('controller' => 'categories', 'action' => 'index')); $result = $route->parse('/category/%D9%85%D9%88%D8%A8%D8%A7%DB%8C%D9%84'); $expected = array( 'controller' => 'categories', 'action' => 'index', 'pass' => array('ู…ูˆุจุงŒู„'), 'named' => array() ); $this->assertEquals($expected, $result); } /** * test that utf-8 patterns work for :section * * @return void */ public function testUTF8PatternOnSection() { $route = new CakeRoute( '/:section', array('plugin' => 'blogs', 'controller' => 'posts', 'action' => 'index'), array( 'persist' => array('section'), 'section' => 'ุขู…ูˆุฒุด|weblog' ) ); $result = $route->parse('/%D8%A2%D9%85%D9%88%D8%B2%D8%B4'); $expected = array('section' => 'ุขู…ูˆุฒุด', 'plugin' => 'blogs', 'controller' => 'posts', 'action' => 'index', 'pass' => array(), 'named' => array()); $this->assertEquals($expected, $result); $result = $route->parse('/weblog'); $expected = array('section' => 'weblog', 'plugin' => 'blogs', 'controller' => 'posts', 'action' => 'index', 'pass' => array(), 'named' => array()); $this->assertEquals($expected, $result); } /** * Test for __set_state magic method on CakeRoute * * @return void */ public function testSetState() { $route = CakeRoute::__set_state(array( 'keys' => array(), 'options' => array(), 'defaults' => array( 'controller' => 'pages', 'action' => 'display', 'home', ), 'template' => '/', '_greedy' => false, '_compiledRoute' => null, '_headerMap' => array ( 'type' => 'content_type', 'method' => 'request_method', 'server' => 'server_name', ), )); $this->assertInstanceOf('CakeRoute', $route); $this->assertSame('/', $route->match(array('controller' => 'pages', 'action' => 'display', 'home'))); $this->assertFalse($route->match(array('controller' => 'pages', 'action' => 'display', 'about'))); $expected = array('controller' => 'pages', 'action' => 'display', 'pass' => array('home'), 'named' => array()); $this->assertEquals($expected, $route->parse('/')); } } cakephp-2.8.0/lib/Cake/Test/Case/Routing/Route/PluginShortRouteTest.php000066400000000000000000000041201265552240500257350ustar00rootroot00000000000000 null, 'prefixes' => array())); Router::reload(); } /** * test the parsing of routes. * * @return void */ public function testParsing() { $route = new PluginShortRoute('/:plugin', array('action' => 'index'), array('plugin' => 'foo|bar')); $result = $route->parse('/foo'); $this->assertEquals('foo', $result['plugin']); $this->assertEquals('foo', $result['controller']); $this->assertEquals('index', $result['action']); $result = $route->parse('/wrong'); $this->assertFalse($result, 'Wrong plugin name matched %s'); } /** * test the reverse routing of the plugin shortcut URLs. * * @return void */ public function testMatch() { $route = new PluginShortRoute('/:plugin', array('action' => 'index'), array('plugin' => 'foo|bar')); $result = $route->match(array('plugin' => 'foo', 'controller' => 'posts', 'action' => 'index')); $this->assertFalse($result, 'plugin controller mismatch was converted. %s'); $result = $route->match(array('plugin' => 'foo', 'controller' => 'foo', 'action' => 'index')); $this->assertEquals('/foo', $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Routing/Route/RedirectRouteTest.php000066400000000000000000000121601265552240500252230ustar00rootroot00000000000000 null, 'prefixes' => array())); Router::reload(); } /** * test the parsing of routes. * * @return void */ public function testParsing() { $route = new RedirectRoute('/home', array('controller' => 'posts')); $route->stop = false; $route->response = $this->getMock('CakeResponse', array('_sendHeader')); $route->parse('/home'); $header = $route->response->header(); $this->assertEquals(Router::url('/posts', true), $header['Location']); $route = new RedirectRoute('/home', array('controller' => 'posts', 'action' => 'index')); $route->stop = false; $route->response = $this->getMock('CakeResponse', array('_sendHeader')); $route->parse('/home'); $header = $route->response->header(); $this->assertEquals(Router::url('/posts', true), $header['Location']); $this->assertEquals(301, $route->response->statusCode()); $route = new RedirectRoute('/google', 'http://google.com'); $route->stop = false; $route->response = $this->getMock('CakeResponse', array('_sendHeader')); $route->parse('/google'); $header = $route->response->header(); $this->assertEquals('http://google.com', $header['Location']); $route = new RedirectRoute('/posts/*', array('controller' => 'posts', 'action' => 'view'), array('status' => 302)); $route->stop = false; $route->response = $this->getMock('CakeResponse', array('_sendHeader')); $route->parse('/posts/2'); $header = $route->response->header(); $this->assertEquals(Router::url('/posts/view', true), $header['Location']); $this->assertEquals(302, $route->response->statusCode()); $route = new RedirectRoute('/posts/*', array('controller' => 'posts', 'action' => 'view'), array('persist' => true)); $route->stop = false; $route->response = $this->getMock('CakeResponse', array('_sendHeader')); $route->parse('/posts/2'); $header = $route->response->header(); $this->assertEquals(Router::url('/posts/view/2', true), $header['Location']); $route = new RedirectRoute('/posts/*', '/test', array('persist' => true)); $route->stop = false; $route->response = $this->getMock('CakeResponse', array('_sendHeader')); $route->parse('/posts/2'); $header = $route->response->header(); $this->assertEquals(Router::url('/test', true), $header['Location']); $route = new RedirectRoute('/my_controllers/:action/*', array('controller' => 'tags', 'action' => 'add'), array('persist' => true)); $route->stop = false; $route->response = $this->getMock('CakeResponse', array('_sendHeader')); $route->parse('/my_controllers/do_something/passme/named:param'); $header = $route->response->header(); $this->assertEquals(Router::url('/tags/add/passme/named:param', true), $header['Location']); $route = new RedirectRoute('/my_controllers/:action/*', array('controller' => 'tags', 'action' => 'add')); $route->stop = false; $route->response = $this->getMock('CakeResponse', array('_sendHeader')); $route->parse('/my_controllers/do_something/passme/named:param'); $header = $route->response->header(); $this->assertEquals(Router::url('/tags/add', true), $header['Location']); $route = new RedirectRoute('/:lang/my_controllers', array('controller' => 'tags', 'action' => 'add'), array('lang' => '(nl|en)', 'persist' => array('lang'))); $route->stop = false; $route->response = $this->getMock('CakeResponse', array('_sendHeader')); $route->parse('/nl/my_controllers/'); $header = $route->response->header(); $this->assertEquals(Router::url('/tags/add/lang:nl', true), $header['Location']); Router::$routes = array(); // reset default routes Router::connect('/:lang/preferred_controllers', array('controller' => 'tags', 'action' => 'add'), array('lang' => '(nl|en)', 'persist' => array('lang'))); $route = new RedirectRoute('/:lang/my_controllers', array('controller' => 'tags', 'action' => 'add'), array('lang' => '(nl|en)', 'persist' => array('lang'))); $route->stop = false; $route->response = $this->getMock('CakeResponse', array('_sendHeader')); $route->parse('/nl/my_controllers/'); $header = $route->response->header(); $this->assertEquals(Router::url('/nl/preferred_controllers', true), $header['Location']); } } cakephp-2.8.0/lib/Cake/Test/Case/Routing/RouterTest.php000066400000000000000000003063231265552240500226340ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Routing * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Router', 'Routing'); App::uses('CakeResponse', 'Network'); if (!defined('FULL_BASE_URL')) { define('FULL_BASE_URL', 'http://cakephp.org'); } /** * RouterTest class * * @package Cake.Test.Case.Routing */ class RouterTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); Configure::write('Routing', array('admin' => null, 'prefixes' => array())); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); CakePlugin::unload(); Router::fullBaseUrl(''); Configure::write('App.fullBaseUrl', 'http://localhost'); } /** * testFullBaseUrl method * * @return void */ public function testFullBaseUrl() { $this->assertRegExp('/^http(s)?:\/\//', Router::url('/', true)); $this->assertRegExp('/^http(s)?:\/\//', Router::url(null, true)); $this->assertRegExp('/^http(s)?:\/\//', Router::url(array('full_base' => true))); $this->assertSame(FULL_BASE_URL . '/', Router::url(array('full_base' => true))); } /** * Tests that the base URL can be changed at runtime. * * @return void */ public function testBaseUrl() { $this->assertEquals(FULL_BASE_URL, Router::fullBaseUrl()); Router::fullBaseUrl('http://example.com'); $this->assertEquals('http://example.com/', Router::url('/', true)); $this->assertEquals('http://example.com', Configure::read('App.fullBaseUrl')); Router::fullBaseUrl('https://example.com'); $this->assertEquals('https://example.com/', Router::url('/', true)); $this->assertEquals('https://example.com', Configure::read('App.fullBaseUrl')); } /** * Test that Router uses App.base to build URL's when there are no stored * request objects. * * @return void */ public function testBaseUrlWithBasePath() { Configure::write('App.base', '/cakephp'); Router::fullBaseUrl('http://example.com'); $this->assertEquals('http://example.com/cakephp/tasks', Router::url('/tasks', true)); } /** * testRouteDefaultParams method * * @return void */ public function testRouteDefaultParams() { Router::connect('/:controller', array('controller' => 'posts')); $this->assertEquals(Router::url(array('action' => 'index')), '/'); } /** * testMapResources method * * @return void */ public function testMapResources() { $resources = Router::mapResources('Posts'); $_SERVER['REQUEST_METHOD'] = 'GET'; $result = Router::parse('/posts'); $this->assertEquals(array('pass' => array(), 'named' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'index', '[method]' => 'GET'), $result); $this->assertEquals(array('posts'), $resources); $_SERVER['REQUEST_METHOD'] = 'GET'; $result = Router::parse('/posts/13'); $this->assertEquals(array('pass' => array('13'), 'named' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'view', 'id' => '13', '[method]' => 'GET'), $result); $_SERVER['REQUEST_METHOD'] = 'POST'; $result = Router::parse('/posts'); $this->assertEquals(array('pass' => array(), 'named' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'add', '[method]' => 'POST'), $result); $_SERVER['REQUEST_METHOD'] = 'PUT'; $result = Router::parse('/posts/13'); $this->assertEquals(array('pass' => array('13'), 'named' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'edit', 'id' => '13', '[method]' => 'PUT'), $result); $result = Router::parse('/posts/475acc39-a328-44d3-95fb-015000000000'); $this->assertEquals(array('pass' => array('475acc39-a328-44d3-95fb-015000000000'), 'named' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'edit', 'id' => '475acc39-a328-44d3-95fb-015000000000', '[method]' => 'PUT'), $result); $_SERVER['REQUEST_METHOD'] = 'DELETE'; $result = Router::parse('/posts/13'); $this->assertEquals(array('pass' => array('13'), 'named' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'delete', 'id' => '13', '[method]' => 'DELETE'), $result); $_SERVER['REQUEST_METHOD'] = 'GET'; $result = Router::parse('/posts/add'); $this->assertSame(array(), $result); Router::reload(); $resources = Router::mapResources('Posts', array('id' => '[a-z0-9_]+')); $this->assertEquals(array('posts'), $resources); $_SERVER['REQUEST_METHOD'] = 'GET'; $result = Router::parse('/posts/add'); $this->assertEquals(array('pass' => array('add'), 'named' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'view', 'id' => 'add', '[method]' => 'GET'), $result); $_SERVER['REQUEST_METHOD'] = 'PUT'; $result = Router::parse('/posts/name'); $this->assertEquals(array('pass' => array('name'), 'named' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'edit', 'id' => 'name', '[method]' => 'PUT'), $result); } /** * testMapResources with plugin controllers. * * @return void */ public function testPluginMapResources() { App::build(array( 'Plugin' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS ) )); $resources = Router::mapResources('TestPlugin.TestPlugin'); $_SERVER['REQUEST_METHOD'] = 'GET'; $result = Router::parse('/test_plugin/test_plugin'); $expected = array( 'pass' => array(), 'named' => array(), 'plugin' => 'test_plugin', 'controller' => 'test_plugin', 'action' => 'index', '[method]' => 'GET' ); $this->assertEquals($expected, $result); $this->assertEquals(array('test_plugin'), $resources); $_SERVER['REQUEST_METHOD'] = 'GET'; $result = Router::parse('/test_plugin/test_plugin/13'); $expected = array( 'pass' => array('13'), 'named' => array(), 'plugin' => 'test_plugin', 'controller' => 'test_plugin', 'action' => 'view', 'id' => '13', '[method]' => 'GET' ); $this->assertEquals($expected, $result); } /** * testMapResources with custom connectOptions */ public function testMapResourcesConnectOptions() { App::build(array( 'Plugin' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS ) )); CakePlugin::load('TestPlugin'); App::uses('TestRoute', 'TestPlugin.Routing/Route'); Router::mapResources('Posts', array( 'connectOptions' => array( 'routeClass' => 'TestPlugin.TestRoute', 'foo' => '^(bar)$', ), )); $route = end(Router::$routes); $this->assertInstanceOf('TestRoute', $route); $this->assertEquals('^(bar)$', $route->options['foo']); } /** * Test mapResources with a plugin and prefix. * * @return void */ public function testPluginMapResourcesWithPrefix() { App::build(array( 'Plugin' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS ) )); $resources = Router::mapResources('TestPlugin.TestPlugin', array('prefix' => '/api/')); $_SERVER['REQUEST_METHOD'] = 'GET'; $result = Router::parse('/api/test_plugin'); $expected = array( 'pass' => array(), 'named' => array(), 'plugin' => 'test_plugin', 'controller' => 'test_plugin', 'action' => 'index', '[method]' => 'GET' ); $this->assertEquals($expected, $result); $this->assertEquals(array('test_plugin'), $resources); Router::mapResources('Posts', array('prefix' => 'api')); $_SERVER['REQUEST_METHOD'] = 'GET'; $result = Router::parse('/api/posts'); $expected = array( 'pass' => array(), 'named' => array(), 'plugin' => null, 'controller' => 'posts', 'action' => 'index', '[method]' => 'GET' ); $this->assertEquals($expected, $result); } /** * testMultipleResourceRoute method * * @return void */ public function testMultipleResourceRoute() { Router::connect('/:controller', array('action' => 'index', '[method]' => array('GET', 'POST'))); $_SERVER['REQUEST_METHOD'] = 'GET'; $result = Router::parse('/posts'); $this->assertEquals(array('pass' => array(), 'named' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'index', '[method]' => array('GET', 'POST')), $result); $_SERVER['REQUEST_METHOD'] = 'POST'; $result = Router::parse('/posts'); $this->assertEquals(array('pass' => array(), 'named' => array(), 'plugin' => '', 'controller' => 'posts', 'action' => 'index', '[method]' => array('GET', 'POST')), $result); } /** * testGenerateUrlResourceRoute method * * @return void */ public function testGenerateUrlResourceRoute() { Router::mapResources('Posts'); $result = Router::url(array('controller' => 'posts', 'action' => 'index', '[method]' => 'GET')); $expected = '/posts'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'posts', 'action' => 'view', '[method]' => 'GET', 'id' => 10)); $expected = '/posts/10'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'posts', 'action' => 'add', '[method]' => 'POST')); $expected = '/posts'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'posts', 'action' => 'edit', '[method]' => 'PUT', 'id' => 10)); $expected = '/posts/10'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'posts', 'action' => 'delete', '[method]' => 'DELETE', 'id' => 10)); $expected = '/posts/10'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'posts', 'action' => 'edit', '[method]' => 'POST', 'id' => 10)); $expected = '/posts/10'; $this->assertEquals($expected, $result); } /** * testUrlNormalization method * * @return void */ public function testUrlNormalization() { $expected = '/users/logout'; $result = Router::normalize('/users/logout/'); $this->assertEquals($expected, $result); $result = Router::normalize('//users//logout//'); $this->assertEquals($expected, $result); $result = Router::normalize('users/logout'); $this->assertEquals($expected, $result); $result = Router::normalize(array('controller' => 'users', 'action' => 'logout')); $this->assertEquals($expected, $result); $result = Router::normalize('/'); $this->assertEquals('/', $result); $result = Router::normalize('http://google.com/'); $this->assertEquals('http://google.com/', $result); $result = Router::normalize('http://google.com//'); $this->assertEquals('http://google.com//', $result); $result = Router::normalize('/users/login/scope://foo'); $this->assertEquals('/users/login/scope:/foo', $result); $result = Router::normalize('/recipe/recipes/add'); $this->assertEquals('/recipe/recipes/add', $result); $request = new CakeRequest(); $request->base = '/us'; Router::setRequestInfo($request); $result = Router::normalize('/us/users/logout/'); $this->assertEquals('/users/logout', $result); Router::reload(); $request = new CakeRequest(); $request->base = '/cake_12'; Router::setRequestInfo($request); $result = Router::normalize('/cake_12/users/logout/'); $this->assertEquals('/users/logout', $result); Router::reload(); $_back = Configure::read('App.baseUrl'); Configure::write('App.baseUrl', '/'); $request = new CakeRequest(); $request->base = '/'; Router::setRequestInfo($request); $result = Router::normalize('users/login'); $this->assertEquals('/users/login', $result); Configure::write('App.baseUrl', $_back); Router::reload(); $request = new CakeRequest(); $request->base = 'beer'; Router::setRequestInfo($request); $result = Router::normalize('beer/admin/beers_tags/add'); $this->assertEquals('/admin/beers_tags/add', $result); $result = Router::normalize('/admin/beers_tags/add'); $this->assertEquals('/admin/beers_tags/add', $result); } /** * test generation of basic URLs. * * @return void */ public function testUrlGenerationBasic() { extract(Router::getNamedExpressions()); $request = new CakeRequest(); $request->addParams(array( 'action' => 'index', 'plugin' => null, 'controller' => 'subscribe', 'admin' => true )); $request->base = '/magazine'; $request->here = '/magazine'; $request->webroot = '/magazine/'; Router::setRequestInfo($request); $result = Router::url(); $this->assertEquals('/magazine', $result); Router::reload(); Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home')); $out = Router::url(array('controller' => 'pages', 'action' => 'display', 'home')); $this->assertEquals('/', $out); Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display')); $result = Router::url(array('controller' => 'pages', 'action' => 'display', 'about')); $expected = '/pages/about'; $this->assertEquals($expected, $result); Router::reload(); Router::connect('/:plugin/:id/*', array('controller' => 'posts', 'action' => 'view'), array('id' => $ID)); Router::parse('/'); $result = Router::url(array('plugin' => 'cake_plugin', 'controller' => 'posts', 'action' => 'view', 'id' => '1')); $expected = '/cake_plugin/1'; $this->assertEquals($expected, $result); $result = Router::url(array('plugin' => 'cake_plugin', 'controller' => 'posts', 'action' => 'view', 'id' => '1', '0')); $expected = '/cake_plugin/1/0'; $this->assertEquals($expected, $result); Router::reload(); Router::connect('/:controller/:action/:id', array(), array('id' => $ID)); Router::parse('/'); $result = Router::url(array('controller' => 'posts', 'action' => 'view', 'id' => '1')); $expected = '/posts/view/1'; $this->assertEquals($expected, $result); Router::reload(); Router::connect('/:controller/:id', array('action' => 'view')); Router::parse('/'); $result = Router::url(array('controller' => 'posts', 'action' => 'view', 'id' => '1')); $expected = '/posts/1'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'posts', 'action' => 'index', '0')); $expected = '/posts/index/0'; $this->assertEquals($expected, $result); Router::connect('/view/*', array('controller' => 'posts', 'action' => 'view')); Router::promote(); $result = Router::url(array('controller' => 'posts', 'action' => 'view', '1')); $expected = '/view/1'; $this->assertEquals($expected, $result); Router::reload(); $request = new CakeRequest(); $request->addParams(array( 'action' => 'index', 'plugin' => null, 'controller' => 'real_controller_name' )); $request->base = '/'; $request->here = '/'; $request->webroot = '/'; Router::setRequestInfo($request); Router::connect('short_controller_name/:action/*', array('controller' => 'real_controller_name')); Router::parse('/'); $result = Router::url(array('controller' => 'real_controller_name', 'page' => '1')); $expected = '/short_controller_name/index/page:1'; $this->assertEquals($expected, $result); $result = Router::url(array('action' => 'add')); $expected = '/short_controller_name/add'; $this->assertEquals($expected, $result); Router::reload(); Router::parse('/'); $request = new CakeRequest(); $request->addParams(array( 'action' => 'index', 'plugin' => null, 'controller' => 'users', 'url' => array('url' => 'users') )); $request->base = '/'; $request->here = '/'; $request->webroot = '/'; Router::setRequestInfo($request); $result = Router::url(array('action' => 'login')); $expected = '/users/login'; $this->assertEquals($expected, $result); Router::reload(); Router::connect('/page/*', array('plugin' => null, 'controller' => 'pages', 'action' => 'view')); Router::parse('/'); $result = Router::url(array('plugin' => 'my_plugin', 'controller' => 'pages', 'action' => 'view', 'my-page')); $expected = '/my_plugin/pages/view/my-page'; $this->assertEquals($expected, $result); Router::reload(); Router::connect('/contact/:action', array('plugin' => 'contact', 'controller' => 'contact')); Router::parse('/'); $result = Router::url(array('plugin' => 'contact', 'controller' => 'contact', 'action' => 'me')); $expected = '/contact/me'; $this->assertEquals($expected, $result); Router::reload(); $request = new CakeRequest(); $request->addParams(array( 'action' => 'index', 'plugin' => 'myplugin', 'controller' => 'mycontroller', 'admin' => false )); $request->base = '/'; $request->here = '/'; $request->webroot = '/'; Router::setRequestInfo($request); $result = Router::url(array('plugin' => null, 'controller' => 'myothercontroller')); $expected = '/myothercontroller'; $this->assertEquals($expected, $result); } /** * Test that catch all routes work with a variety of falsey inputs. * * @return void */ public function testUrlCatchAllRoute() { Router::connect('/*', array('controller' => 'categories', 'action' => 'index')); $result = Router::url(array('controller' => 'categories', 'action' => 'index', '0')); $this->assertEquals('/0', $result); $expected = array( 'plugin' => null, 'controller' => 'categories', 'action' => 'index', 'pass' => array('0'), 'named' => array() ); $result = Router::parse('/0'); $this->assertEquals($expected, $result); $result = Router::parse('0'); $this->assertEquals($expected, $result); } /** * Tests using arrays in named parameters * * @return void */ public function testArrayNamedParameters() { $result = Router::url(array('controller' => 'tests', 'pages' => array( 1, 2, 3 ))); $expected = '/tests/index/pages%5B0%5D:1/pages%5B1%5D:2/pages%5B2%5D:3'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'tests', 'pages' => array( 'param1' => array( 'one', 'two' ), 'three' ) )); $expected = '/tests/index/pages%5Bparam1%5D%5B0%5D:one/pages%5Bparam1%5D%5B1%5D:two/pages%5B0%5D:three'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'tests', 'pages' => array( 'param1' => array( 'one' => 1, 'two' => 2 ), 'three' ) )); $expected = '/tests/index/pages%5Bparam1%5D%5Bone%5D:1/pages%5Bparam1%5D%5Btwo%5D:2/pages%5B0%5D:three'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'tests', 'super' => array( 'nested' => array( 'array' => 'awesome', 'something' => 'else' ), 'cool' ) )); $expected = '/tests/index/super%5Bnested%5D%5Barray%5D:awesome/super%5Bnested%5D%5Bsomething%5D:else/super%5B0%5D:cool'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'tests', 'namedParam' => array( 'keyed' => 'is an array', 'test' ))); $expected = '/tests/index/namedParam%5Bkeyed%5D:is%20an%20array/namedParam%5B0%5D:test'; $this->assertEquals($expected, $result); } /** * Test generation of routes with query string parameters. * * @return void */ public function testUrlGenerationWithQueryStrings() { $result = Router::url(array('controller' => 'posts', 'action' => 'index', '0', '?' => 'var=test&var2=test2')); $expected = '/posts/index/0?var=test&var2=test2'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'posts', '0', '?' => 'var=test&var2=test2')); $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'posts', '0', '?' => array('var' => 'test', 'var2' => 'test2'))); $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'posts', '0', '?' => array('var' => null))); $this->assertEquals('/posts/index/0', $result); $result = Router::url(array('controller' => 'posts', '0', '?' => 'var=test&var2=test2', '#' => 'unencoded string %')); $expected = '/posts/index/0?var=test&var2=test2#unencoded string %'; $this->assertEquals($expected, $result); } /** * test that regex validation of keyed route params is working. * * @return void */ public function testUrlGenerationWithRegexQualifiedParams() { Router::connect( ':language/galleries', array('controller' => 'galleries', 'action' => 'index'), array('language' => '[a-z]{3}') ); Router::connect( '/:language/:admin/:controller/:action/*', array('admin' => 'admin'), array('language' => '[a-z]{3}', 'admin' => 'admin') ); Router::connect('/:language/:controller/:action/*', array(), array('language' => '[a-z]{3}') ); $result = Router::url(array('admin' => false, 'language' => 'dan', 'action' => 'index', 'controller' => 'galleries')); $expected = '/dan/galleries'; $this->assertEquals($expected, $result); $result = Router::url(array('admin' => false, 'language' => 'eng', 'action' => 'index', 'controller' => 'galleries')); $expected = '/eng/galleries'; $this->assertEquals($expected, $result); Router::reload(); Router::connect('/:language/pages', array('controller' => 'pages', 'action' => 'index'), array('language' => '[a-z]{3}') ); Router::connect('/:language/:controller/:action/*', array(), array('language' => '[a-z]{3}')); $result = Router::url(array('language' => 'eng', 'action' => 'index', 'controller' => 'pages')); $expected = '/eng/pages'; $this->assertEquals($expected, $result); $result = Router::url(array('language' => 'eng', 'controller' => 'pages')); $this->assertEquals($expected, $result); $result = Router::url(array('language' => 'eng', 'controller' => 'pages', 'action' => 'add')); $expected = '/eng/pages/add'; $this->assertEquals($expected, $result); Router::reload(); Router::connect('/forestillinger/:month/:year/*', array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar'), array('month' => '0[1-9]|1[012]', 'year' => '[12][0-9]{3}') ); Router::parse('/'); $result = Router::url(array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar', 'month' => 10, 'year' => 2007, 'min-forestilling')); $expected = '/forestillinger/10/2007/min-forestilling'; $this->assertEquals($expected, $result); Router::reload(); Router::connect('/kalender/:month/:year/*', array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar'), array('month' => '0[1-9]|1[012]', 'year' => '[12][0-9]{3}') ); Router::connect('/kalender/*', array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar')); Router::parse('/'); $result = Router::url(array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar', 'min-forestilling')); $expected = '/kalender/min-forestilling'; $this->assertEquals($expected, $result); $result = Router::url(array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar', 'year' => 2007, 'month' => 10, 'min-forestilling')); $expected = '/kalender/10/2007/min-forestilling'; $this->assertEquals($expected, $result); Router::reload(); Router::connect('/:controller/:action/*', array(), array( 'controller' => 'source|wiki|commits|tickets|comments|view', 'action' => 'branches|history|branch|logs|view|start|add|edit|modify' )); } /** * Test URL generation with an admin prefix * * @return void */ public function testUrlGenerationWithAdminPrefix() { Configure::write('Routing.prefixes', array('admin')); Router::reload(); Router::connectNamed(array('event', 'lang')); Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home')); Router::connect('/pages/contact_us', array('controller' => 'pages', 'action' => 'contact_us')); Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display')); Router::connect('/reset/*', array('admin' => true, 'controller' => 'users', 'action' => 'reset')); Router::connect('/tests', array('controller' => 'tests', 'action' => 'index')); Router::parseExtensions('rss'); $request = new CakeRequest(); $request->addParams(array( 'controller' => 'registrations', 'action' => 'admin_index', 'plugin' => null, 'prefix' => 'admin', 'admin' => true, 'ext' => 'html' )); $request->base = ''; $request->here = '/admin/registrations/index'; $request->webroot = '/'; Router::setRequestInfo($request); $result = Router::url(array('page' => 2)); $expected = '/admin/registrations/index/page:2'; $this->assertEquals($expected, $result); Router::reload(); $request = new CakeRequest(); $request->addParams(array( 'controller' => 'subscriptions', 'action' => 'admin_index', 'plugin' => null, 'admin' => true, 'url' => array('url' => 'admin/subscriptions/index/page:2') )); $request->base = '/magazine'; $request->here = '/magazine/admin/subscriptions/index/page:2'; $request->webroot = '/magazine/'; Router::setRequestInfo($request); Router::parse('/'); $result = Router::url(array('page' => 3)); $expected = '/magazine/admin/subscriptions/index/page:3'; $this->assertEquals($expected, $result); Router::reload(); Router::connect('/admin/subscriptions/:action/*', array('controller' => 'subscribe', 'admin' => true, 'prefix' => 'admin')); Router::parse('/'); $request = new CakeRequest(); $request->addParams(array( 'action' => 'admin_index', 'plugin' => null, 'controller' => 'subscribe', 'admin' => true, 'url' => array('url' => 'admin/subscriptions/edit/1') )); $request->base = '/magazine'; $request->here = '/magazine/admin/subscriptions/edit/1'; $request->webroot = '/magazine/'; Router::setRequestInfo($request); $result = Router::url(array('action' => 'edit', 1)); $expected = '/magazine/admin/subscriptions/edit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('admin' => true, 'controller' => 'users', 'action' => 'login')); $expected = '/magazine/admin/users/login'; $this->assertEquals($expected, $result); Router::reload(); $request = new CakeRequest(); $request->addParams(array( 'admin' => true, 'action' => 'index', 'plugin' => null, 'controller' => 'users', 'url' => array('url' => 'users') )); $request->base = '/'; $request->here = '/'; $request->webroot = '/'; Router::setRequestInfo($request); Router::connect('/page/*', array('controller' => 'pages', 'action' => 'view', 'admin' => true, 'prefix' => 'admin')); Router::parse('/'); $result = Router::url(array('admin' => true, 'controller' => 'pages', 'action' => 'view', 'my-page')); $expected = '/page/my-page'; $this->assertEquals($expected, $result); Router::reload(); $request = new CakeRequest(); $request->addParams(array( 'plugin' => null, 'controller' => 'pages', 'action' => 'admin_add', 'prefix' => 'admin', 'admin' => true, 'url' => array('url' => 'admin/pages/add') )); $request->base = ''; $request->here = '/admin/pages/add'; $request->webroot = '/'; Router::setRequestInfo($request); Router::parse('/'); $result = Router::url(array('plugin' => null, 'controller' => 'pages', 'action' => 'add', 'id' => false)); $expected = '/admin/pages/add'; $this->assertEquals($expected, $result); Router::reload(); Router::parse('/'); $request = new CakeRequest(); $request->addParams(array( 'plugin' => null, 'controller' => 'pages', 'action' => 'admin_add', 'prefix' => 'admin', 'admin' => true, 'url' => array('url' => 'admin/pages/add') )); $request->base = ''; $request->here = '/admin/pages/add'; $request->webroot = '/'; Router::setRequestInfo($request); $result = Router::url(array('plugin' => null, 'controller' => 'pages', 'action' => 'add', 'id' => false)); $expected = '/admin/pages/add'; $this->assertEquals($expected, $result); Router::reload(); Router::connect('/admin/:controller/:action/:id', array('admin' => true), array('id' => '[0-9]+')); Router::parse('/'); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'pages', 'action' => 'admin_edit', 'pass' => array('284'), 'prefix' => 'admin', 'admin' => true, 'url' => array('url' => 'admin/pages/edit/284') ))->addPaths(array( 'base' => '', 'here' => '/admin/pages/edit/284', 'webroot' => '/' )) ); $result = Router::url(array('plugin' => null, 'controller' => 'pages', 'action' => 'edit', 'id' => '284')); $expected = '/admin/pages/edit/284'; $this->assertEquals($expected, $result); Router::reload(); Router::parse('/'); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'pages', 'action' => 'admin_add', 'prefix' => 'admin', 'admin' => true, 'url' => array('url' => 'admin/pages/add') ))->addPaths(array( 'base' => '', 'here' => '/admin/pages/add', 'webroot' => '/' )) ); $result = Router::url(array('plugin' => null, 'controller' => 'pages', 'action' => 'add', 'id' => false)); $expected = '/admin/pages/add'; $this->assertEquals($expected, $result); Router::reload(); Router::parse('/'); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'pages', 'action' => 'admin_edit', 'prefix' => 'admin', 'admin' => true, 'pass' => array('284'), 'url' => array('url' => 'admin/pages/edit/284') ))->addPaths(array( 'base' => '', 'here' => '/admin/pages/edit/284', 'webroot' => '/' )) ); $result = Router::url(array('plugin' => null, 'controller' => 'pages', 'action' => 'edit', 284)); $expected = '/admin/pages/edit/284'; $this->assertEquals($expected, $result); Router::reload(); Router::connect('/admin/posts/*', array('controller' => 'posts', 'action' => 'index', 'admin' => true)); Router::parse('/'); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'posts', 'action' => 'admin_index', 'prefix' => 'admin', 'admin' => true, 'pass' => array('284'), 'url' => array('url' => 'admin/posts') ))->addPaths(array( 'base' => '', 'here' => '/admin/posts', 'webroot' => '/' )) ); $result = Router::url(array('all')); $expected = '/admin/posts/all'; $this->assertEquals($expected, $result); } /** * testUrlGenerationWithExtensions method * * @return void */ public function testUrlGenerationWithExtensions() { Router::parse('/'); $result = Router::url(array('plugin' => null, 'controller' => 'articles', 'action' => 'add', 'id' => null, 'ext' => 'json')); $expected = '/articles/add.json'; $this->assertEquals($expected, $result); $result = Router::url(array('plugin' => null, 'controller' => 'articles', 'action' => 'add', 'ext' => 'json')); $expected = '/articles/add.json'; $this->assertEquals($expected, $result); $result = Router::url(array('plugin' => null, 'controller' => 'articles', 'action' => 'index', 'id' => null, 'ext' => 'json')); $expected = '/articles.json'; $this->assertEquals($expected, $result); $result = Router::url(array('plugin' => null, 'controller' => 'articles', 'action' => 'index', 'ext' => 'json')); $expected = '/articles.json'; $this->assertEquals($expected, $result); } /** * testPluginUrlGeneration method * * @return void */ public function testUrlGenerationPlugins() { $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => 'test', 'controller' => 'controller', 'action' => 'index' ))->addPaths(array( 'base' => '/base', 'here' => '/clients/sage/portal/donations', 'webroot' => '/base/' )) ); $this->assertEquals(Router::url('read/1'), '/base/test/controller/read/1'); Router::reload(); Router::connect('/:lang/:plugin/:controller/*', array('action' => 'index')); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'lang' => 'en', 'plugin' => 'shows', 'controller' => 'shows', 'action' => 'index', 'url' => array('url' => 'en/shows/'), ))->addPaths(array( 'base' => '', 'here' => '/en/shows', 'webroot' => '/' )) ); Router::parse('/en/shows/'); $result = Router::url(array( 'lang' => 'en', 'controller' => 'shows', 'action' => 'index', 'page' => '1', )); $expected = '/en/shows/shows/page:1'; $this->assertEquals($expected, $result); } /** * test that you can leave active plugin routes with plugin = null * * @return void */ public function testCanLeavePlugin() { Router::reload(); Router::connect( '/admin/other/:controller/:action/*', array( 'admin' => 1, 'plugin' => 'aliased', 'prefix' => 'admin' ) ); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'pass' => array(), 'admin' => true, 'prefix' => 'admin', 'plugin' => 'this', 'action' => 'admin_index', 'controller' => 'interesting', 'url' => array('url' => 'admin/this/interesting/index'), ))->addPaths(array( 'base' => '', 'here' => '/admin/this/interesting/index', 'webroot' => '/', )) ); $result = Router::url(array('plugin' => null, 'controller' => 'posts', 'action' => 'index')); $this->assertEquals('/admin/posts', $result); $result = Router::url(array('controller' => 'posts', 'action' => 'index')); $this->assertEquals('/admin/this/posts', $result); $result = Router::url(array('plugin' => 'aliased', 'controller' => 'posts', 'action' => 'index')); $this->assertEquals('/admin/other/posts/index', $result); } /** * Test that URL's fail to parse when they are prefixed with // * * @return void */ public function testUrlParseFailureDoubleSlash() { Router::connect('/posts', array('controller' => 'posts', 'action' => 'index')); $result = Router::parse('/posts'); $this->assertEquals( array('pass' => array(), 'named' => array(), 'plugin' => null, 'controller' => 'posts', 'action' => 'index'), $result ); $result = Router::parse('//posts'); $this->assertEquals(array(), $result); } /** * testUrlParsing method * * @return void */ public function testUrlParsing() { extract(Router::getNamedExpressions()); Router::connect('/posts/:value/:somevalue/:othervalue/*', array('controller' => 'posts', 'action' => 'view'), array('value', 'somevalue', 'othervalue')); $result = Router::parse('/posts/2007/08/01/title-of-post-here'); $expected = array('value' => '2007', 'somevalue' => '08', 'othervalue' => '01', 'controller' => 'posts', 'action' => 'view', 'plugin' => '', 'pass' => array('0' => 'title-of-post-here'), 'named' => array()); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/posts/:year/:month/:day/*', array('controller' => 'posts', 'action' => 'view'), array('year' => $Year, 'month' => $Month, 'day' => $Day)); $result = Router::parse('/posts/2007/08/01/title-of-post-here'); $expected = array('year' => '2007', 'month' => '08', 'day' => '01', 'controller' => 'posts', 'action' => 'view', 'plugin' => '', 'pass' => array('0' => 'title-of-post-here'), 'named' => array()); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/posts/:day/:year/:month/*', array('controller' => 'posts', 'action' => 'view'), array('year' => $Year, 'month' => $Month, 'day' => $Day)); $result = Router::parse('/posts/01/2007/08/title-of-post-here'); $expected = array('day' => '01', 'year' => '2007', 'month' => '08', 'controller' => 'posts', 'action' => 'view', 'plugin' => '', 'pass' => array('0' => 'title-of-post-here'), 'named' => array()); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/posts/:month/:day/:year/*', array('controller' => 'posts', 'action' => 'view'), array('year' => $Year, 'month' => $Month, 'day' => $Day)); $result = Router::parse('/posts/08/01/2007/title-of-post-here'); $expected = array('month' => '08', 'day' => '01', 'year' => '2007', 'controller' => 'posts', 'action' => 'view', 'plugin' => '', 'pass' => array('0' => 'title-of-post-here'), 'named' => array()); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/posts/:year/:month/:day/*', array('controller' => 'posts', 'action' => 'view')); $result = Router::parse('/posts/2007/08/01/title-of-post-here'); $expected = array('year' => '2007', 'month' => '08', 'day' => '01', 'controller' => 'posts', 'action' => 'view', 'plugin' => '', 'pass' => array('0' => 'title-of-post-here'), 'named' => array()); $this->assertEquals($expected, $result); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; $result = Router::parse('/pages/display/home'); $expected = array('plugin' => null, 'pass' => array('home'), 'controller' => 'pages', 'action' => 'display', 'named' => array()); $this->assertEquals($expected, $result); $result = Router::parse('pages/display/home/'); $this->assertEquals($expected, $result); $result = Router::parse('pages/display/home'); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/page/*', array('controller' => 'test')); $result = Router::parse('/page/my-page'); $expected = array('pass' => array('my-page'), 'plugin' => null, 'controller' => 'test', 'action' => 'index', 'named' => array()); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/:language/contact', array('language' => 'eng', 'plugin' => 'contact', 'controller' => 'contact', 'action' => 'index'), array('language' => '[a-z]{3}')); $result = Router::parse('/eng/contact'); $expected = array('pass' => array(), 'named' => array(), 'language' => 'eng', 'plugin' => 'contact', 'controller' => 'contact', 'action' => 'index'); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/forestillinger/:month/:year/*', array('plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar'), array('month' => '0[1-9]|1[012]', 'year' => '[12][0-9]{3}') ); $result = Router::parse('/forestillinger/10/2007/min-forestilling'); $expected = array('pass' => array('min-forestilling'), 'plugin' => 'shows', 'controller' => 'shows', 'action' => 'calendar', 'year' => 2007, 'month' => 10, 'named' => array()); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/:controller/:action/*'); Router::connect('/', array('plugin' => 'pages', 'controller' => 'pages', 'action' => 'display')); $result = Router::parse('/'); $expected = array('pass' => array(), 'named' => array(), 'controller' => 'pages', 'action' => 'display', 'plugin' => 'pages'); $this->assertEquals($expected, $result); $result = Router::parse('/posts/edit/0'); $expected = array('pass' => array(0), 'named' => array(), 'controller' => 'posts', 'action' => 'edit', 'plugin' => null); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/posts/:id::url_title', array('controller' => 'posts', 'action' => 'view'), array('pass' => array('id', 'url_title'), 'id' => '[\d]+')); $result = Router::parse('/posts/5:sample-post-title'); $expected = array('pass' => array('5', 'sample-post-title'), 'named' => array(), 'id' => 5, 'url_title' => 'sample-post-title', 'plugin' => null, 'controller' => 'posts', 'action' => 'view'); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/posts/:id::url_title/*', array('controller' => 'posts', 'action' => 'view'), array('pass' => array('id', 'url_title'), 'id' => '[\d]+')); $result = Router::parse('/posts/5:sample-post-title/other/params/4'); $expected = array('pass' => array('5', 'sample-post-title', 'other', 'params', '4'), 'named' => array(), 'id' => 5, 'url_title' => 'sample-post-title', 'plugin' => null, 'controller' => 'posts', 'action' => 'view'); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/posts/:url_title-(uuid::id)', array('controller' => 'posts', 'action' => 'view'), array('pass' => array('id', 'url_title'), 'id' => $UUID)); $result = Router::parse('/posts/sample-post-title-(uuid:47fc97a9-019c-41d1-a058-1fa3cbdd56cb)'); $expected = array('pass' => array('47fc97a9-019c-41d1-a058-1fa3cbdd56cb', 'sample-post-title'), 'named' => array(), 'id' => '47fc97a9-019c-41d1-a058-1fa3cbdd56cb', 'url_title' => 'sample-post-title', 'plugin' => null, 'controller' => 'posts', 'action' => 'view'); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/posts/view/*', array('controller' => 'posts', 'action' => 'view'), array('named' => false)); $result = Router::parse('/posts/view/foo:bar/routing:fun'); $expected = array('pass' => array('foo:bar', 'routing:fun'), 'named' => array(), 'plugin' => null, 'controller' => 'posts', 'action' => 'view'); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/posts/view/*', array('controller' => 'posts', 'action' => 'view'), array('named' => array('foo', 'answer'))); $result = Router::parse('/posts/view/foo:bar/routing:fun/answer:42'); $expected = array('pass' => array('routing:fun'), 'named' => array('foo' => 'bar', 'answer' => '42'), 'plugin' => null, 'controller' => 'posts', 'action' => 'view'); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/posts/view/*', array('controller' => 'posts', 'action' => 'view'), array('named' => array('foo', 'answer'), 'greedyNamed' => true)); $result = Router::parse('/posts/view/foo:bar/routing:fun/answer:42'); $expected = array('pass' => array(), 'named' => array('foo' => 'bar', 'routing' => 'fun', 'answer' => '42'), 'plugin' => null, 'controller' => 'posts', 'action' => 'view'); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/posts/view/*', array('controller' => 'posts', 'action' => 'view'), array('named' => array('foo', 'answer'), 'greedyNamed' => true)); $result = Router::parse('/posts/view/foo:bar/routing:fun/answer:42?id=123&tab=abc'); $expected = array('pass' => array(), 'named' => array('foo' => 'bar', 'routing' => 'fun', 'answer' => '42'), 'plugin' => null, 'controller' => 'posts', 'action' => 'view', '?' => array('id' => '123', 'tab' => 'abc')); $this->assertEquals($expected, $result); } /** * test that the persist key works. * * @return void */ public function testPersistentParameters() { Router::reload(); Router::connect( '/:lang/:color/posts/view/*', array('controller' => 'posts', 'action' => 'view'), array('persist' => array('lang', 'color')) ); Router::connect( '/:lang/:color/posts/index', array('controller' => 'posts', 'action' => 'index'), array('persist' => array('lang')) ); Router::connect('/:lang/:color/posts/edit/*', array('controller' => 'posts', 'action' => 'edit')); Router::connect('/about', array('controller' => 'pages', 'action' => 'view', 'about')); Router::parse('/en/red/posts/view/5'); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'lang' => 'en', 'color' => 'red', 'prefix' => 'admin', 'plugin' => null, 'action' => 'view', 'controller' => 'posts', ))->addPaths(array( 'base' => '/', 'here' => '/en/red/posts/view/5', 'webroot' => '/', )) ); $expected = '/en/red/posts/view/6'; $result = Router::url(array('controller' => 'posts', 'action' => 'view', 6)); $this->assertEquals($expected, $result); $expected = '/en/blue/posts/index'; $result = Router::url(array('controller' => 'posts', 'action' => 'index', 'color' => 'blue')); $this->assertEquals($expected, $result); $expected = '/posts/edit/6'; $result = Router::url(array('controller' => 'posts', 'action' => 'edit', 6, 'color' => null, 'lang' => null)); $this->assertEquals($expected, $result); $expected = '/posts'; $result = Router::url(array('controller' => 'posts', 'action' => 'index')); $this->assertEquals($expected, $result); $expected = '/posts/edit/7'; $result = Router::url(array('controller' => 'posts', 'action' => 'edit', 7)); $this->assertEquals($expected, $result); $expected = '/about'; $result = Router::url(array('controller' => 'pages', 'action' => 'view', 'about')); $this->assertEquals($expected, $result); } /** * testUuidRoutes method * * @return void */ public function testUuidRoutes() { Router::connect( '/subjects/add/:category_id', array('controller' => 'subjects', 'action' => 'add'), array('category_id' => '\w{8}-\w{4}-\w{4}-\w{4}-\w{12}') ); $result = Router::parse('/subjects/add/4795d601-19c8-49a6-930e-06a8b01d17b7'); $expected = array('pass' => array(), 'named' => array(), 'category_id' => '4795d601-19c8-49a6-930e-06a8b01d17b7', 'plugin' => null, 'controller' => 'subjects', 'action' => 'add'); $this->assertEquals($expected, $result); } /** * testRouteSymmetry method * * @return void */ public function testRouteSymmetry() { Router::connect( "/:extra/page/:slug/*", array('controller' => 'pages', 'action' => 'view', 'extra' => null), array("extra" => '[a-z1-9_]*', "slug" => '[a-z1-9_]+', "action" => 'view') ); $result = Router::parse('/some_extra/page/this_is_the_slug'); $expected = array('pass' => array(), 'named' => array(), 'plugin' => null, 'controller' => 'pages', 'action' => 'view', 'slug' => 'this_is_the_slug', 'extra' => 'some_extra'); $this->assertEquals($expected, $result); $result = Router::parse('/page/this_is_the_slug'); $expected = array('pass' => array(), 'named' => array(), 'plugin' => null, 'controller' => 'pages', 'action' => 'view', 'slug' => 'this_is_the_slug', 'extra' => null); $this->assertEquals($expected, $result); Router::reload(); Router::connect( "/:extra/page/:slug/*", array('controller' => 'pages', 'action' => 'view', 'extra' => null), array("extra" => '[a-z1-9_]*', "slug" => '[a-z1-9_]+') ); Router::parse('/'); $result = Router::url(array('admin' => null, 'plugin' => null, 'controller' => 'pages', 'action' => 'view', 'slug' => 'this_is_the_slug', 'extra' => null)); $expected = '/page/this_is_the_slug'; $this->assertEquals($expected, $result); $result = Router::url(array('admin' => null, 'plugin' => null, 'controller' => 'pages', 'action' => 'view', 'slug' => 'this_is_the_slug', 'extra' => 'some_extra')); $expected = '/some_extra/page/this_is_the_slug'; $this->assertEquals($expected, $result); } /** * Test parse and reverse symmetry * * @return void * @dataProvider parseReverseSymmetryData */ public function testParseReverseSymmetry($url) { $this->assertSame($url, Router::reverse(Router::parse($url) + array('url' => array()))); } /** * Data for parse and reverse test * * @return array */ public function parseReverseSymmetryData() { return array( array('/'), array('/controller/action'), array('/controller/action/param'), array('/controller/action?param1=value1¶m2=value2'), array('/controller/action/param?param1=value1'), array('/controller/action/named1:nv1'), array('/controller/action/named1:nv1?param1=value1') ); } /** * Test that Routing.prefixes are used when a Router instance is created * or reset * * @return void */ public function testRoutingPrefixesSetting() { $restore = Configure::read('Routing'); Configure::write('Routing.prefixes', array('admin', 'member', 'super_user')); Router::reload(); $result = Router::prefixes(); $expected = array('admin', 'member', 'super_user'); $this->assertEquals($expected, $result); Configure::write('Routing.prefixes', array('admin', 'member')); Router::reload(); $result = Router::prefixes(); $expected = array('admin', 'member'); $this->assertEquals($expected, $result); Configure::write('Routing', $restore); } /** * Test prefix routing and plugin combinations * * @return void */ public function testPrefixRoutingAndPlugins() { Configure::write('Routing.prefixes', array('admin')); $paths = App::path('plugins'); App::build(array( 'plugins' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS ) ), App::RESET); CakePlugin::load(array('TestPlugin')); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'admin' => true, 'controller' => 'controller', 'action' => 'action', 'plugin' => null, 'prefix' => 'admin' ))->addPaths(array( 'base' => '/', 'here' => '/', 'webroot' => '/base/', )) ); Router::parse('/'); $result = Router::url(array('plugin' => 'test_plugin', 'controller' => 'test_plugin', 'action' => 'index')); $expected = '/admin/test_plugin'; $this->assertEquals($expected, $result); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => 'test_plugin', 'controller' => 'show_tickets', 'action' => 'admin_edit', 'pass' => array('6'), 'prefix' => 'admin', 'admin' => true, 'form' => array(), 'url' => array('url' => 'admin/shows/show_tickets/edit/6') ))->addPaths(array( 'base' => '/', 'here' => '/admin/shows/show_tickets/edit/6', 'webroot' => '/', )) ); $result = Router::url(array( 'plugin' => 'test_plugin', 'controller' => 'show_tickets', 'action' => 'edit', 6, 'admin' => true, 'prefix' => 'admin' )); $expected = '/admin/test_plugin/show_tickets/edit/6'; $this->assertEquals($expected, $result); $result = Router::url(array( 'plugin' => 'test_plugin', 'controller' => 'show_tickets', 'action' => 'index', 'admin' => true )); $expected = '/admin/test_plugin/show_tickets'; $this->assertEquals($expected, $result); App::build(array('plugins' => $paths)); } /** * testParseExtensions method * * @return void */ public function testParseExtensions() { $this->assertEquals(array(), Router::extensions()); Router::parseExtensions('rss'); $this->assertEquals(array('rss'), Router::extensions()); } /** * testSetExtensions method * * @return void */ public function testSetExtensions() { Router::setExtensions(array('rss')); $this->assertEquals(array('rss'), Router::extensions()); require CAKE . 'Config' . DS . 'routes.php'; $result = Router::parse('/posts.rss'); $this->assertFalse(isset($result['ext'])); Router::parseExtensions(); $result = Router::parse('/posts.rss'); $this->assertEquals('rss', $result['ext']); $result = Router::parse('/posts.xml'); $this->assertFalse(isset($result['ext'])); Router::setExtensions(array('xml')); $result = Router::extensions(); $this->assertEquals(array('rss', 'xml'), $result); $result = Router::parse('/posts.xml'); $this->assertEquals('xml', $result['ext']); $result = Router::setExtensions(array('pdf'), false); $this->assertEquals(array('pdf'), $result); } /** * testExtensionParsing method * * @return void */ public function testExtensionParsing() { Router::parseExtensions(); require CAKE . 'Config' . DS . 'routes.php'; $result = Router::parse('/posts.rss'); $expected = array('plugin' => null, 'controller' => 'posts', 'action' => 'index', 'ext' => 'rss', 'pass' => array(), 'named' => array()); $this->assertEquals($expected, $result); $result = Router::parse('/posts/view/1.rss'); $expected = array('plugin' => null, 'controller' => 'posts', 'action' => 'view', 'pass' => array('1'), 'named' => array(), 'ext' => 'rss'); $this->assertEquals($expected, $result); $result = Router::parse('/posts/view/1.rss?query=test'); $expected['?'] = array('query' => 'test'); $this->assertEquals($expected, $result); $result = Router::parse('/posts/view/1.atom'); unset($expected['?']); $expected['ext'] = 'atom'; $this->assertEquals($expected, $result); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; Router::parseExtensions('rss', 'xml'); $result = Router::parse('/posts.xml'); $expected = array('plugin' => null, 'controller' => 'posts', 'action' => 'index', 'ext' => 'xml', 'pass' => array(), 'named' => array()); $this->assertEquals($expected, $result); $result = Router::parse('/posts.atom?hello=goodbye'); $expected = array('plugin' => null, 'controller' => 'posts.atom', 'action' => 'index', 'pass' => array(), 'named' => array(), '?' => array('hello' => 'goodbye')); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/controller/action', array('controller' => 'controller', 'action' => 'action', 'ext' => 'rss')); $result = Router::parse('/controller/action'); $expected = array('controller' => 'controller', 'action' => 'action', 'plugin' => null, 'ext' => 'rss', 'named' => array(), 'pass' => array()); $this->assertEquals($expected, $result); Router::reload(); Router::parseExtensions('rss'); Router::connect('/controller/action', array('controller' => 'controller', 'action' => 'action', 'ext' => 'rss')); $result = Router::parse('/controller/action'); $expected = array('controller' => 'controller', 'action' => 'action', 'plugin' => null, 'ext' => 'rss', 'named' => array(), 'pass' => array()); $this->assertEquals($expected, $result); } /** * testQuerystringGeneration method * * @return void */ public function testQuerystringGeneration() { $result = Router::url(array('controller' => 'posts', 'action' => 'index', '0', '?' => 'var=test&var2=test2')); $expected = '/posts/index/0?var=test&var2=test2'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'posts', 'action' => 'index', '0', '?' => array('var' => 'test', 'var2' => 'test2'))); $this->assertEquals($expected, $result); $expected .= '&more=test+data'; $result = Router::url(array('controller' => 'posts', 'action' => 'index', '0', '?' => array('var' => 'test', 'var2' => 'test2', 'more' => 'test data'))); $this->assertEquals($expected, $result); // Test bug #4614 $restore = ini_get('arg_separator.output'); ini_set('arg_separator.output', '&'); $result = Router::url(array('controller' => 'posts', 'action' => 'index', '0', '?' => array('var' => 'test', 'var2' => 'test2', 'more' => 'test data'))); $this->assertEquals($expected, $result); ini_set('arg_separator.output', $restore); $result = Router::url(array('controller' => 'posts', 'action' => 'index', '0', '?' => array('var' => 'test', 'var2' => 'test2')), array('escape' => true)); $expected = '/posts/index/0?var=test&var2=test2'; $this->assertEquals($expected, $result); } /** * testConnectNamed method * * @return void */ public function testConnectNamed() { $named = Router::connectNamed(false, array('default' => true)); $this->assertFalse($named['greedyNamed']); $this->assertEquals(array_keys($named['rules']), $named['default']); Router::reload(); Router::connect('/foo/*', array('controller' => 'bar', 'action' => 'fubar')); Router::connectNamed(array(), array('separator' => '=')); $result = Router::parse('/foo/param1=value1/param2=value2'); $expected = array('pass' => array(), 'named' => array('param1' => 'value1', 'param2' => 'value2'), 'controller' => 'bar', 'action' => 'fubar', 'plugin' => null); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/controller/action/*', array('controller' => 'controller', 'action' => 'action'), array('named' => array('param1' => 'value[\d]'))); Router::connectNamed(array(), array('greedy' => false, 'separator' => '=')); $result = Router::parse('/controller/action/param1=value1/param2=value2'); $expected = array('pass' => array('param2=value2'), 'named' => array('param1' => 'value1'), 'controller' => 'controller', 'action' => 'action', 'plugin' => null); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/:controller/:action/*'); Router::connectNamed(array('page'), array('default' => false, 'greedy' => false)); $result = Router::parse('/categories/index/limit=5'); $this->assertTrue(empty($result['named'])); } /** * testNamedArgsUrlGeneration method * * @return void */ public function testNamedArgsUrlGeneration() { $result = Router::url(array('controller' => 'posts', 'action' => 'index', 'published' => 1, 'deleted' => 1)); $expected = '/posts/index/published:1/deleted:1'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'posts', 'action' => 'index', 'published' => 0, 'deleted' => 0)); $expected = '/posts/index/published:0/deleted:0'; $this->assertEquals($expected, $result); Router::reload(); extract(Router::getNamedExpressions()); Router::connectNamed(array('file' => '[\w\.\-]+\.(html|png)')); Router::connect('/', array('controller' => 'graphs', 'action' => 'index')); Router::connect('/:id/*', array('controller' => 'graphs', 'action' => 'view'), array('id' => $ID)); $result = Router::url(array('controller' => 'graphs', 'action' => 'view', 'id' => 12, 'file' => 'asdf.png')); $expected = '/12/file:asdf.png'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'graphs', 'action' => 'view', 12, 'file' => 'asdf.foo')); $expected = '/graphs/view/12/file:asdf.foo'; $this->assertEquals($expected, $result); Configure::write('Routing.prefixes', array('admin')); Router::reload(); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'admin' => true, 'controller' => 'controller', 'action' => 'index', 'plugin' => null ))->addPaths(array( 'base' => '/', 'here' => '/', 'webroot' => '/base/', )) ); Router::parse('/'); $result = Router::url(array('page' => 1, 0 => null, 'sort' => 'controller', 'direction' => 'asc', 'order' => null)); $expected = "/admin/controller/index/page:1/sort:controller/direction:asc"; $this->assertEquals($expected, $result); Router::reload(); $request = new CakeRequest('admin/controller/index'); $request->addParams(array( 'admin' => true, 'controller' => 'controller', 'action' => 'index', 'plugin' => null )); $request->base = '/'; Router::setRequestInfo($request); Router::parse('/admin/controller/index/type:whatever'); $result = Router::url(array('type' => 'new')); $expected = "/admin/controller/index/type:new"; $this->assertEquals($expected, $result); } /** * testNamedArgsUrlParsing method * * @return void */ public function testNamedArgsUrlParsing() { Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; $result = Router::parse('/controller/action/param1:value1:1/param2:value2:3/param:value'); $expected = array('pass' => array(), 'named' => array('param1' => 'value1:1', 'param2' => 'value2:3', 'param' => 'value'), 'controller' => 'controller', 'action' => 'action', 'plugin' => null); $this->assertEquals($expected, $result); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; $result = Router::connectNamed(false); $this->assertEquals(array(), array_keys($result['rules'])); $this->assertFalse($result['greedyNamed']); $result = Router::parse('/controller/action/param1:value1:1/param2:value2:3/param:value'); $expected = array('pass' => array('param1:value1:1', 'param2:value2:3', 'param:value'), 'named' => array(), 'controller' => 'controller', 'action' => 'action', 'plugin' => null); $this->assertEquals($expected, $result); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; $result = Router::connectNamed(true); $named = Router::namedConfig(); $this->assertEquals($named['default'], array_keys($result['rules'])); $this->assertTrue($result['greedyNamed']); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; Router::connectNamed(array('param1' => 'not-matching')); $result = Router::parse('/controller/action/param1:value1:1/param2:value2:3/param:value'); $expected = array('pass' => array('param1:value1:1'), 'named' => array('param2' => 'value2:3', 'param' => 'value'), 'controller' => 'controller', 'action' => 'action', 'plugin' => null); $this->assertEquals($expected, $result); $result = Router::parse('/foo/view/param1:value1:1/param2:value2:3/param:value'); $expected = array('pass' => array('param1:value1:1'), 'named' => array('param2' => 'value2:3', 'param' => 'value'), 'controller' => 'foo', 'action' => 'view', 'plugin' => null); $this->assertEquals($expected, $result); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; Router::connectNamed(array('param1' => '[\d]', 'param2' => '[a-z]', 'param3' => '[\d]')); $result = Router::parse('/controller/action/param1:1/param2:2/param3:3'); $expected = array('pass' => array('param2:2'), 'named' => array('param1' => '1', 'param3' => '3'), 'controller' => 'controller', 'action' => 'action', 'plugin' => null); $this->assertEquals($expected, $result); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; Router::connectNamed(array('param1' => '[\d]', 'param2' => true, 'param3' => '[\d]')); $result = Router::parse('/controller/action/param1:1/param2:2/param3:3'); $expected = array('pass' => array(), 'named' => array('param1' => '1', 'param2' => '2', 'param3' => '3'), 'controller' => 'controller', 'action' => 'action', 'plugin' => null); $this->assertEquals($expected, $result); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; Router::connectNamed(array('param1' => 'value[\d]+:[\d]+'), array('greedy' => false)); $result = Router::parse('/controller/action/param1:value1:1/param2:value2:3/param3:value'); $expected = array('pass' => array('param2:value2:3', 'param3:value'), 'named' => array('param1' => 'value1:1'), 'controller' => 'controller', 'action' => 'action', 'plugin' => null); $this->assertEquals($expected, $result); } /** * Test URL generation with legacy (1.2) style prefix routes. * * @return void * @see testUrlGenerationWithAutoPrefixes */ public function testUrlGenerationWithLegacyPrefixes() { Router::reload(); Router::connect('/protected/:controller/:action/*', array( 'prefix' => 'protected', 'protected' => true )); Router::parse('/'); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'images', 'action' => 'index', 'prefix' => null, 'admin' => false, 'url' => array('url' => 'images/index') ))->addPaths(array( 'base' => '', 'here' => '/images/index', 'webroot' => '/', )) ); $result = Router::url(array('protected' => true)); $expected = '/protected/images/index'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'images', 'action' => 'add')); $expected = '/images/add'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'images', 'action' => 'add', 'protected' => true)); $expected = '/protected/images/add'; $this->assertEquals($expected, $result); $result = Router::url(array('action' => 'edit', 1)); $expected = '/images/edit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('action' => 'edit', 1, 'protected' => true)); $expected = '/protected/images/edit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('action' => 'protected_edit', 1, 'protected' => true)); $expected = '/protected/images/edit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('action' => 'edit', 1, 'protected' => true)); $expected = '/protected/images/edit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'others', 'action' => 'edit', 1)); $expected = '/others/edit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'others', 'action' => 'edit', 1, 'protected' => true)); $expected = '/protected/others/edit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'others', 'action' => 'edit', 1, 'protected' => true, 'page' => 1)); $expected = '/protected/others/edit/1/page:1'; $this->assertEquals($expected, $result); Router::connectNamed(array('random')); $result = Router::url(array('controller' => 'others', 'action' => 'edit', 1, 'protected' => true, 'random' => 'my-value')); $expected = '/protected/others/edit/1/random:my-value'; $this->assertEquals($expected, $result); } /** * test newer style automatically generated prefix routes. * * @return void */ public function testUrlGenerationWithAutoPrefixes() { Configure::write('Routing.prefixes', array('protected')); Router::reload(); Router::parse('/'); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'images', 'action' => 'index', 'prefix' => null, 'protected' => false, 'url' => array('url' => 'images/index') ))->addPaths(array( 'base' => '', 'here' => '/images/index', 'webroot' => '/', )) ); $result = Router::url(array('controller' => 'images', 'action' => 'add')); $expected = '/images/add'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'images', 'action' => 'add', 'protected' => true)); $expected = '/protected/images/add'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'images', 'action' => 'add_protected_test', 'protected' => true)); $expected = '/protected/images/add_protected_test'; $this->assertEquals($expected, $result); $result = Router::url(array('action' => 'edit', 1)); $expected = '/images/edit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('action' => 'edit', 1, 'protected' => true)); $expected = '/protected/images/edit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('action' => 'protected_edit', 1, 'protected' => true)); $expected = '/protected/images/edit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('action' => 'protectededit', 1, 'protected' => true)); $expected = '/protected/images/protectededit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('action' => 'edit', 1, 'protected' => true)); $expected = '/protected/images/edit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'others', 'action' => 'edit', 1)); $expected = '/others/edit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'others', 'action' => 'edit', 1, 'protected' => true)); $expected = '/protected/others/edit/1'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'others', 'action' => 'edit', 1, 'protected' => true, 'page' => 1)); $expected = '/protected/others/edit/1/page:1'; $this->assertEquals($expected, $result); Router::connectNamed(array('random')); $result = Router::url(array('controller' => 'others', 'action' => 'edit', 1, 'protected' => true, 'random' => 'my-value')); $expected = '/protected/others/edit/1/random:my-value'; $this->assertEquals($expected, $result); } /** * test that auto-generated prefix routes persist * * @return void */ public function testAutoPrefixRoutePersistence() { Configure::write('Routing.prefixes', array('protected')); Router::reload(); Router::parse('/'); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'images', 'action' => 'index', 'prefix' => 'protected', 'protected' => true, 'url' => array('url' => 'protected/images/index') ))->addPaths(array( 'base' => '', 'here' => '/protected/images/index', 'webroot' => '/', )) ); $result = Router::url(array('controller' => 'images', 'action' => 'add')); $expected = '/protected/images/add'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'images', 'action' => 'add', 'protected' => false)); $expected = '/images/add'; $this->assertEquals($expected, $result); } /** * test that setting a prefix override the current one * * @return void */ public function testPrefixOverride() { Configure::write('Routing.prefixes', array('protected', 'admin')); Router::reload(); Router::parse('/'); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'images', 'action' => 'index', 'prefix' => 'protected', 'protected' => true, 'url' => array('url' => 'protected/images/index') ))->addPaths(array( 'base' => '', 'here' => '/protected/images/index', 'webroot' => '/', )) ); $result = Router::url(array('controller' => 'images', 'action' => 'add', 'admin' => true)); $expected = '/admin/images/add'; $this->assertEquals($expected, $result); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'images', 'action' => 'index', 'prefix' => 'admin', 'admin' => true, 'url' => array('url' => 'admin/images/index') ))->addPaths(array( 'base' => '', 'here' => '/admin/images/index', 'webroot' => '/', )) ); $result = Router::url(array('controller' => 'images', 'action' => 'add', 'protected' => true)); $expected = '/protected/images/add'; $this->assertEquals($expected, $result); } /** * Test that setting a prefix to false is ignored, as its generally user error. * * @return void */ public function testPrefixFalseIgnored() { Configure::write('Routing.prefixes', array('admin')); Router::reload(); Router::connect('/cache_css/*', array('admin' => false, 'controller' => 'asset_compress', 'action' => 'get')); $url = Router::url(array('controller' => 'asset_compress', 'action' => 'get', 'test')); $expected = '/cache_css/test'; $this->assertEquals($expected, $url); $url = Router::url(array('admin' => false, 'controller' => 'asset_compress', 'action' => 'get', 'test')); $expected = '/cache_css/test'; $this->assertEquals($expected, $url); $url = Router::url(array('admin' => true, 'controller' => 'asset_compress', 'action' => 'get', 'test')); $this->assertEquals('/admin/asset_compress/get/test', $url); } /** * testRemoveBase method * * @return void */ public function testRemoveBase() { $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'controller', 'action' => 'index', 'bare' => 0, 'url' => array('url' => 'protected/images/index') ))->addPaths(array( 'base' => '/base', 'here' => '/', 'webroot' => '/base/', )) ); $result = Router::url(array('controller' => 'my_controller', 'action' => 'my_action')); $expected = '/base/my_controller/my_action'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'my_controller', 'action' => 'my_action', 'base' => false)); $expected = '/my_controller/my_action'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'my_controller', 'action' => 'my_action', 'base' => true)); $expected = '/base/my_controller/my_action/base:1'; $this->assertEquals($expected, $result); } /** * testPagesUrlParsing method * * @return void */ public function testPagesUrlParsing() { Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home')); Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display')); $result = Router::parse('/'); $expected = array('pass' => array('home'), 'named' => array(), 'plugin' => null, 'controller' => 'pages', 'action' => 'display'); $this->assertEquals($expected, $result); $result = Router::parse('/pages/home/'); $expected = array('pass' => array('home'), 'named' => array(), 'plugin' => null, 'controller' => 'pages', 'action' => 'display'); $this->assertEquals($expected, $result); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home')); $result = Router::parse('/'); $expected = array('pass' => array('home'), 'named' => array(), 'plugin' => null, 'controller' => 'pages', 'action' => 'display'); $this->assertEquals($expected, $result); $result = Router::parse('/pages/display/home/event:value'); $expected = array('pass' => array('home'), 'named' => array('event' => 'value'), 'plugin' => null, 'controller' => 'pages', 'action' => 'display'); $this->assertEquals($expected, $result); $result = Router::parse('/pages/display/home/event:Val_u2'); $expected = array('pass' => array('home'), 'named' => array('event' => 'Val_u2'), 'plugin' => null, 'controller' => 'pages', 'action' => 'display'); $this->assertEquals($expected, $result); $result = Router::parse('/pages/display/home/event:val-ue'); $expected = array('pass' => array('home'), 'named' => array('event' => 'val-ue'), 'plugin' => null, 'controller' => 'pages', 'action' => 'display'); $this->assertEquals($expected, $result); Router::reload(); Router::connect('/', array('controller' => 'posts', 'action' => 'index')); Router::connect('/pages/*', array('controller' => 'pages', 'action' => 'display')); $result = Router::parse('/pages/contact/'); $expected = array('pass' => array('contact'), 'named' => array(), 'plugin' => null, 'controller' => 'pages', 'action' => 'display'); $this->assertEquals($expected, $result); } /** * test that requests with a trailing dot don't loose the do. * * @return void */ public function testParsingWithTrailingPeriod() { Router::reload(); Router::connect('/:controller/:action/*'); $result = Router::parse('/posts/view/something.'); $this->assertEquals('something.', $result['pass'][0], 'Period was chopped off %s'); $result = Router::parse('/posts/view/something. . .'); $this->assertEquals('something. . .', $result['pass'][0], 'Period was chopped off %s'); } /** * test that requests with a trailing dot don't loose the do. * * @return void */ public function testParsingWithTrailingPeriodAndParseExtensions() { Router::reload(); Router::connect('/:controller/:action/*'); Router::parseExtensions('json'); $result = Router::parse('/posts/view/something.'); $this->assertEquals('something.', $result['pass'][0], 'Period was chopped off %s'); $result = Router::parse('/posts/view/something. . .'); $this->assertEquals('something. . .', $result['pass'][0], 'Period was chopped off %s'); } /** * test that patterns work for :action * * @return void */ public function testParsingWithPatternOnAction() { Router::reload(); Router::connect( '/blog/:action/*', array('controller' => 'blog_posts'), array('action' => 'other|actions') ); $result = Router::parse('/blog/other'); $expected = array( 'plugin' => null, 'controller' => 'blog_posts', 'action' => 'other', 'pass' => array(), 'named' => array() ); $this->assertEquals($expected, $result); $result = Router::parse('/blog/foobar'); $this->assertSame(array(), $result); $result = Router::url(array('controller' => 'blog_posts', 'action' => 'foo')); $this->assertEquals('/blog_posts/foo', $result); $result = Router::url(array('controller' => 'blog_posts', 'action' => 'actions')); $this->assertEquals('/blog/actions', $result); } /** * testParsingWithPrefixes method * * @return void */ public function testParsingWithPrefixes() { $adminParams = array('prefix' => 'admin', 'admin' => true); Router::connect('/admin/:controller', $adminParams); Router::connect('/admin/:controller/:action', $adminParams); Router::connect('/admin/:controller/:action/*', $adminParams); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'controller', 'action' => 'index' ))->addPaths(array( 'base' => '/base', 'here' => '/', 'webroot' => '/base/', )) ); $result = Router::parse('/admin/posts/'); $expected = array('pass' => array(), 'named' => array(), 'prefix' => 'admin', 'plugin' => null, 'controller' => 'posts', 'action' => 'admin_index', 'admin' => true); $this->assertEquals($expected, $result); $result = Router::parse('/admin/posts'); $this->assertEquals($expected, $result); $result = Router::url(array('admin' => true, 'controller' => 'posts')); $expected = '/base/admin/posts'; $this->assertEquals($expected, $result); $result = Router::prefixes(); $expected = array('admin'); $this->assertEquals($expected, $result); Router::reload(); $prefixParams = array('prefix' => 'members', 'members' => true); Router::connect('/members/:controller', $prefixParams); Router::connect('/members/:controller/:action', $prefixParams); Router::connect('/members/:controller/:action/*', $prefixParams); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'controller', 'action' => 'index', 'bare' => 0 ))->addPaths(array( 'base' => '/base', 'here' => '/', 'webroot' => '/', )) ); $result = Router::parse('/members/posts/index'); $expected = array('pass' => array(), 'named' => array(), 'prefix' => 'members', 'plugin' => null, 'controller' => 'posts', 'action' => 'members_index', 'members' => true); $this->assertEquals($expected, $result); $result = Router::url(array('members' => true, 'controller' => 'posts', 'action' => 'index', 'page' => 2)); $expected = '/base/members/posts/index/page:2'; $this->assertEquals($expected, $result); $result = Router::url(array('members' => true, 'controller' => 'users', 'action' => 'add')); $expected = '/base/members/users/add'; $this->assertEquals($expected, $result); } /** * Tests URL generation with flags and prefixes in and out of context * * @return void */ public function testUrlWritingWithPrefixes() { Router::connect('/company/:controller/:action/*', array('prefix' => 'company', 'company' => true)); Router::connect('/login', array('controller' => 'users', 'action' => 'login')); $result = Router::url(array('controller' => 'users', 'action' => 'login', 'company' => true)); $expected = '/company/users/login'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'users', 'action' => 'company_login', 'company' => true)); $expected = '/company/users/login'; $this->assertEquals($expected, $result); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'users', 'action' => 'login', 'company' => true ))->addPaths(array( 'base' => '/', 'here' => '/', 'webroot' => '/base/', )) ); $result = Router::url(array('controller' => 'users', 'action' => 'login', 'company' => false)); $expected = '/login'; $this->assertEquals($expected, $result); } /** * test url generation with prefixes and custom routes * * @return void */ public function testUrlWritingWithPrefixesAndCustomRoutes() { Router::connect( '/admin/login', array('controller' => 'users', 'action' => 'login', 'prefix' => 'admin', 'admin' => true) ); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'posts', 'action' => 'index', 'admin' => true, 'prefix' => 'admin' ))->addPaths(array( 'base' => '/', 'here' => '/', 'webroot' => '/', )) ); $result = Router::url(array('controller' => 'users', 'action' => 'login', 'admin' => true)); $this->assertEquals('/admin/login', $result); $result = Router::url(array('controller' => 'users', 'action' => 'login')); $this->assertEquals('/admin/login', $result); $result = Router::url(array('controller' => 'users', 'action' => 'admin_login')); $this->assertEquals('/admin/login', $result); } /** * testPassedArgsOrder method * * @return void */ public function testPassedArgsOrder() { Router::connect('/test-passed/*', array('controller' => 'pages', 'action' => 'display', 'home')); Router::connect('/test2/*', array('controller' => 'pages', 'action' => 'display', 2)); Router::connect('/test/*', array('controller' => 'pages', 'action' => 'display', 1)); Router::parse('/'); $result = Router::url(array('controller' => 'pages', 'action' => 'display', 1, 'whatever')); $expected = '/test/whatever'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'pages', 'action' => 'display', 2, 'whatever')); $expected = '/test2/whatever'; $this->assertEquals($expected, $result); $result = Router::url(array('controller' => 'pages', 'action' => 'display', 'home', 'whatever')); $expected = '/test-passed/whatever'; $this->assertEquals($expected, $result); Configure::write('Routing.prefixes', array('admin')); Router::reload(); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'images', 'action' => 'index', 'url' => array('url' => 'protected/images/index') ))->addPaths(array( 'base' => '', 'here' => '/protected/images/index', 'webroot' => '/', )) ); Router::connect('/protected/:controller/:action/*', array( 'controller' => 'users', 'action' => 'index', 'prefix' => 'protected' )); Router::parse('/'); $result = Router::url(array('controller' => 'images', 'action' => 'add')); $expected = '/protected/images/add'; $this->assertEquals($expected, $result); $result = Router::prefixes(); $expected = array('admin', 'protected'); $this->assertEquals($expected, $result); } /** * testRegexRouteMatching method * * @return void */ public function testRegexRouteMatching() { Router::connect('/:locale/:controller/:action/*', array(), array('locale' => 'dan|eng')); $result = Router::parse('/eng/test/test_action'); $expected = array('pass' => array(), 'named' => array(), 'locale' => 'eng', 'controller' => 'test', 'action' => 'test_action', 'plugin' => null); $this->assertEquals($expected, $result); $result = Router::parse('/badness/test/test_action'); $this->assertSame(array(), $result); Router::reload(); Router::connect('/:locale/:controller/:action/*', array(), array('locale' => 'dan|eng')); $request = new CakeRequest(); Router::setRequestInfo( $request->addParams(array( 'plugin' => null, 'controller' => 'test', 'action' => 'index', 'url' => array('url' => 'test/test_action') ))->addPaths(array( 'base' => '', 'here' => '/test/test_action', 'webroot' => '/', )) ); $result = Router::url(array('action' => 'test_another_action')); $expected = '/test/test_another_action'; $this->assertEquals($expected, $result); $result = Router::url(array('action' => 'test_another_action', 'locale' => 'eng')); $expected = '/eng/test/test_another_action'; $this->assertEquals($expected, $result); $result = Router::url(array('action' => 'test_another_action', 'locale' => 'badness')); $expected = '/test/test_another_action/locale:badness'; $this->assertEquals($expected, $result); } /** * testStripPlugin * * @return void */ public function testStripPlugin() { $pluginName = 'forums'; $url = 'example.com/' . $pluginName . '/'; $expected = 'example.com'; $this->assertEquals($expected, Router::stripPlugin($url, $pluginName)); $this->assertEquals(Router::stripPlugin($url), $url); $this->assertEquals(Router::stripPlugin($url, null), $url); } /** * testCurrentRouteWhenNonExistentRoute * * @return void */ public function testCurrentRouteWhenNonExistentRoute() { $route = Router::currentRoute(); $this->assertFalse($route); } /** * testCurrentRoute * * This test needs some improvement and actual requestAction() usage * * @return void */ public function testCurrentRoute() { $url = array('controller' => 'pages', 'action' => 'display', 'government'); Router::connect('/government', $url); Router::parse('/government'); $route = Router::currentRoute(); $this->assertEquals(array_merge($url, array('plugin' => null)), $route->defaults); } /** * testRequestRoute * * @return void */ public function testRequestRoute() { $url = array('controller' => 'products', 'action' => 'display', 5); Router::connect('/government', $url); Router::parse('/government'); $route = Router::requestRoute(); $this->assertEquals(array_merge($url, array('plugin' => null)), $route->defaults); // test that the first route is matched Router::connect('/government', $url); Router::parse('/government'); $route = Router::requestRoute(); $this->assertEquals(array_merge($url, array('plugin' => null)), $route->defaults); // test that an unmatched route does not change the current route Router::connect('/actor', $url); Router::parse('/government'); $route = Router::requestRoute(); $this->assertEquals(array_merge($url, array('plugin' => null)), $route->defaults); } /** * testGetParams * * @return void */ public function testGetParams() { $paths = array('base' => '/', 'here' => '/products/display/5', 'webroot' => '/webroot'); $params = array('param1' => '1', 'param2' => '2'); Router::setRequestInfo(array($params, $paths)); $expected = array( 'plugin' => null, 'controller' => false, 'action' => false, 'named' => array(), 'pass' => array(), 'param1' => '1', 'param2' => '2', ); $this->assertEquals($expected, Router::getParams()); $this->assertEquals(false, Router::getParam('controller')); $this->assertEquals('1', Router::getParam('param1')); $this->assertEquals('2', Router::getParam('param2')); Router::reload(); $params = array('controller' => 'pages', 'action' => 'display'); Router::setRequestInfo(array($params, $paths)); $expected = array( 'plugin' => null, 'controller' => 'pages', 'action' => 'display', 'named' => array(), 'pass' => array(), ); $this->assertEquals($expected, Router::getParams()); $this->assertEquals($expected, Router::getParams(true)); } /** * test that connectDefaults() can disable default route connection * * @return void */ public function testDefaultsMethod() { Router::connect('/test/*', array('controller' => 'pages', 'action' => 'display', 2)); $result = Router::parse('/posts/edit/5'); $this->assertFalse(isset($result['controller'])); $this->assertFalse(isset($result['action'])); } /** * test that the required default routes are connected. * * @return void */ public function testConnectDefaultRoutes() { App::build(array( 'plugins' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS ) ), App::RESET); CakePlugin::load(array('TestPlugin', 'PluginJs')); Router::reload(); require CAKE . 'Config' . DS . 'routes.php'; $result = Router::url(array('plugin' => 'plugin_js', 'controller' => 'js_file', 'action' => 'index')); $this->assertEquals('/plugin_js/js_file', $result); $result = Router::parse('/plugin_js/js_file'); $expected = array( 'plugin' => 'plugin_js', 'controller' => 'js_file', 'action' => 'index', 'named' => array(), 'pass' => array() ); $this->assertEquals($expected, $result); $result = Router::url(array('plugin' => 'test_plugin', 'controller' => 'test_plugin', 'action' => 'index')); $this->assertEquals('/test_plugin', $result); $result = Router::parse('/test_plugin'); $expected = array( 'plugin' => 'test_plugin', 'controller' => 'test_plugin', 'action' => 'index', 'named' => array(), 'pass' => array() ); $this->assertEquals($expected, $result, 'Plugin shortcut route broken. %s'); } /** * test using a custom route class for route connection * * @return void */ public function testUsingCustomRouteClass() { $this->getMock('CakeRoute', array(), array(), 'MockConnectedRoute', false); $routes = Router::connect( '/:slug', array('controller' => 'posts', 'action' => 'view'), array('routeClass' => 'MockConnectedRoute', 'slug' => '[a-z_-]+') ); $this->assertInstanceOf('MockConnectedRoute', $routes[0], 'Incorrect class used. %s'); $expected = array('controller' => 'posts', 'action' => 'view', 'slug' => 'test'); $routes[0]->expects($this->any()) ->method('parse') ->will($this->returnValue($expected)); $result = Router::parse('/test'); $this->assertEquals($expected, $result); } /** * test using custom route class in PluginDot notation * * @return void */ public function testUsingCustomRouteClassPluginDotSyntax() { App::build(array( 'Plugin' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS ) )); CakePlugin::load('TestPlugin'); App::uses('TestRoute', 'TestPlugin.Routing/Route'); $routes = Router::connect( '/:slug', array('controller' => 'posts', 'action' => 'view'), array('routeClass' => 'TestPlugin.TestRoute', 'slug' => '[a-z_-]+') ); $this->assertInstanceOf('TestRoute', $routes[0]); CakePlugin::unload('TestPlugin'); } /** * test that route classes must extend CakeRoute * * @expectedException RouterException * @return void */ public function testCustomRouteException() { Router::connect('/:controller', array(), array('routeClass' => 'Object')); } /** * test reversing parameter arrays back into strings. * * Mark the router as initialized so it doesn't auto-load routes * * @return void */ public function testRouterReverse() { Router::$initialized = true; $params = array( 'controller' => 'posts', 'action' => 'view', 'pass' => array(1), 'named' => array(), 'url' => array(), 'autoRender' => 1, 'bare' => 1, 'return' => 1, 'requested' => 1, '_Token' => array('key' => 'sekret') ); $result = Router::reverse($params); $this->assertEquals('/posts/view/1', $result); $params = array( 'controller' => 'posts', 'action' => 'index', 'pass' => array(1), 'named' => array('page' => 1, 'sort' => 'Article.title', 'direction' => 'desc'), 'url' => array() ); $result = Router::reverse($params); $this->assertEquals('/posts/index/1/page:1/sort:Article.title/direction:desc', $result); Router::connect('/:lang/:controller/:action/*', array(), array('lang' => '[a-z]{3}')); $params = array( 'lang' => 'eng', 'controller' => 'posts', 'action' => 'view', 'pass' => array(1), 'named' => array(), 'url' => array('url' => 'eng/posts/view/1') ); $result = Router::reverse($params); $this->assertEquals('/eng/posts/view/1', $result); $params = array( 'lang' => 'eng', 'controller' => 'posts', 'action' => 'view', 'pass' => array(1), 'named' => array(), 'url' => array('url' => 'eng/posts/view/1', 'foo' => 'bar', 'baz' => 'quu'), 'paging' => array(), 'models' => array() ); $result = Router::reverse($params); $this->assertEquals('/eng/posts/view/1?foo=bar&baz=quu', $result); $request = new CakeRequest('/eng/posts/view/1'); $request->addParams(array( 'lang' => 'eng', 'controller' => 'posts', 'action' => 'view', 'pass' => array(1), 'named' => array(), )); $request->query = array('url' => 'eng/posts/view/1', 'test' => 'value'); $result = Router::reverse($request); $expected = '/eng/posts/view/1?test=value'; $this->assertEquals($expected, $result); $params = array( 'lang' => 'eng', 'controller' => 'posts', 'action' => 'view', 'pass' => array(1), 'named' => array(), 'url' => array('url' => 'eng/posts/view/1') ); $result = Router::reverse($params, true); $this->assertRegExp('/^http(s)?:\/\//', $result); } /** * Test that extensions work with Router::reverse() * * @return void */ public function testReverseWithExtension() { Router::parseExtensions('json'); $request = new CakeRequest('/posts/view/1.json'); $request->addParams(array( 'controller' => 'posts', 'action' => 'view', 'pass' => array(1), 'named' => array(), 'ext' => 'json', )); $request->query = array(); $result = Router::reverse($request); $expected = '/posts/view/1.json'; $this->assertEquals($expected, $result); } /** * test that setRequestInfo can accept arrays and turn that into a CakeRequest object. * * @return void */ public function testSetRequestInfoLegacy() { Router::setRequestInfo(array( array( 'plugin' => null, 'controller' => 'images', 'action' => 'index', 'url' => array('url' => 'protected/images/index') ), array( 'base' => '', 'here' => '/protected/images/index', 'webroot' => '/', ) )); $result = Router::getRequest(); $this->assertEquals('images', $result->controller); $this->assertEquals('index', $result->action); $this->assertEquals('', $result->base); $this->assertEquals('/protected/images/index', $result->here); $this->assertEquals('/', $result->webroot); } /** * Test that Router::url() uses the first request * * @return void */ public function testUrlWithRequestAction() { $firstRequest = new CakeRequest('/posts/index'); $firstRequest->addParams(array( 'plugin' => null, 'controller' => 'posts', 'action' => 'index' ))->addPaths(array('base' => '')); $secondRequest = new CakeRequest('/posts/index'); $secondRequest->addParams(array( 'requested' => 1, 'plugin' => null, 'controller' => 'comments', 'action' => 'listing' ))->addPaths(array('base' => '')); Router::setRequestInfo($firstRequest); Router::setRequestInfo($secondRequest); $result = Router::url(array('base' => false)); $this->assertEquals('/comments/listing', $result, 'with second requests, the last should win.'); Router::popRequest(); $result = Router::url(array('base' => false)); $this->assertEquals('/posts', $result, 'with second requests, the last should win.'); } /** * test that a route object returning a full URL is not modified. * * @return void */ public function testUrlFullUrlReturnFromRoute() { $url = 'http://example.com/posts/view/1'; $this->getMock('CakeRoute', array(), array('/'), 'MockReturnRoute'); $routes = Router::connect('/:controller/:action', array(), array('routeClass' => 'MockReturnRoute')); $routes[0]->expects($this->any())->method('match') ->will($this->returnValue($url)); $result = Router::url(array('controller' => 'posts', 'action' => 'view', 1)); $this->assertEquals($url, $result); } /** * test protocol in url * * @return void */ public function testUrlProtocol() { $url = 'http://example.com'; $this->assertEquals($url, Router::url($url)); $url = 'ed2k://example.com'; $this->assertEquals($url, Router::url($url)); $url = 'svn+ssh://example.com'; $this->assertEquals($url, Router::url($url)); $url = '://example.com'; $this->assertEquals($url, Router::url($url)); $url = '//example.com'; $this->assertEquals($url, Router::url($url)); $url = 'javascript:void(0)'; $this->assertEquals($url, Router::url($url)); $url = 'tel:012345-678'; $this->assertEquals($url, Router::url($url)); $url = 'sms:012345-678'; $this->assertEquals($url, Router::url($url)); $url = '#here'; $this->assertEquals($url, Router::url($url)); $url = '?param=0'; $this->assertEquals($url, Router::url($url)); $url = 'posts/index#here'; $expected = FULL_BASE_URL . '/posts/index#here'; $this->assertEquals($expected, Router::url($url, true)); } /** * Testing that patterns on the :action param work properly. * * @return void */ public function testPatternOnAction() { $route = new CakeRoute( '/blog/:action/*', array('controller' => 'blog_posts'), array('action' => 'other|actions') ); $result = $route->match(array('controller' => 'blog_posts', 'action' => 'foo')); $this->assertFalse($result); $result = $route->match(array('controller' => 'blog_posts', 'action' => 'actions')); $this->assertEquals('/blog/actions/', $result); $result = $route->parse('/blog/other'); $expected = array('controller' => 'blog_posts', 'action' => 'other', 'pass' => array(), 'named' => array()); $this->assertEquals($expected, $result); $result = $route->parse('/blog/foobar'); $this->assertFalse($result); } /** * Tests resourceMap as getter and setter. * * @return void */ public function testResourceMap() { $default = Router::resourceMap(); $expected = array( array('action' => 'index', 'method' => 'GET', 'id' => false), array('action' => 'view', 'method' => 'GET', 'id' => true), array('action' => 'add', 'method' => 'POST', 'id' => false), array('action' => 'edit', 'method' => 'PUT', 'id' => true), array('action' => 'delete', 'method' => 'DELETE', 'id' => true), array('action' => 'edit', 'method' => 'POST', 'id' => true) ); $this->assertEquals($expected, $default); $custom = array( array('action' => 'index', 'method' => 'GET', 'id' => false), array('action' => 'view', 'method' => 'GET', 'id' => true), array('action' => 'add', 'method' => 'POST', 'id' => false), array('action' => 'edit', 'method' => 'PUT', 'id' => true), array('action' => 'delete', 'method' => 'DELETE', 'id' => true), array('action' => 'update', 'method' => 'POST', 'id' => true) ); Router::resourceMap($custom); $this->assertEquals(Router::resourceMap(), $custom); Router::resourceMap($default); } /** * test setting redirect routes * * @return void */ public function testRouteRedirection() { Router::redirect('/blog', array('controller' => 'posts'), array('status' => 302)); $this->assertEquals(1, count(Router::$routes)); Router::$routes[0]->response = $this->getMock('CakeResponse', array('_sendHeader')); Router::$routes[0]->stop = false; $this->assertEquals(302, Router::$routes[0]->options['status']); Router::parse('/blog'); $header = Router::$routes[0]->response->header(); $this->assertEquals(Router::url('/posts', true), $header['Location']); $this->assertEquals(302, Router::$routes[0]->response->statusCode()); Router::$routes[0]->response = $this->getMock('CakeResponse', array('_sendHeader')); Router::parse('/not-a-match'); $this->assertEquals(array(), Router::$routes[0]->response->header()); } /** * Test setting the default route class * * @return void */ public function testDefaultRouteClass() { $this->getMock('CakeRoute', array(), array('/test'), 'TestDefaultRouteClass'); Router::defaultRouteClass('TestDefaultRouteClass'); $result = Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home')); $this->assertInstanceOf('TestDefaultRouteClass', $result[0]); } /** * Test getting the default route class * * @return void */ public function testDefaultRouteClassGetter() { $routeClass = 'TestDefaultRouteClass'; Router::defaultRouteClass($routeClass); $this->assertEquals($routeClass, Router::defaultRouteClass()); $this->assertEquals($routeClass, Router::defaultRouteClass(null)); } /** * Test that route classes must extend CakeRoute * * @expectedException RouterException * @return void */ public function testDefaultRouteException() { Router::defaultRouteClass(''); Router::connect('/:controller', array()); } /** * Test that route classes must extend CakeRoute * * @expectedException RouterException * @return void */ public function testSettingInvalidDefaultRouteException() { Router::defaultRouteClass('Object'); } /** * Test that class must exist * * @expectedException RouterException * @return void */ public function testSettingNonExistentDefaultRouteException() { Router::defaultRouteClass('NonExistentClass'); } /** * Tests generating well-formed querystrings * * @return void */ public function testQueryString() { $result = Router::queryString(array('var' => 'foo bar')); $expected = '?var=foo+bar'; $this->assertEquals($expected, $result); $result = Router::queryString(false, array('some' => 'param', 'foo' => 'bar')); $expected = '?some=param&foo=bar'; $this->assertEquals($expected, $result); $existing = array('apple' => 'red', 'pear' => 'green'); $result = Router::queryString($existing, array('some' => 'param', 'foo' => 'bar')); $expected = '?apple=red&pear=green&some=param&foo=bar'; $this->assertEquals($expected, $result); $existing = 'apple=red&pear=green'; $result = Router::queryString($existing, array('some' => 'param', 'foo' => 'bar')); $expected = '?apple=red&pear=green&some=param&foo=bar'; $this->assertEquals($expected, $result); $existing = '?apple=red&pear=green'; $result = Router::queryString($existing, array('some' => 'param', 'foo' => 'bar')); $expected = '?apple=red&pear=green&some=param&foo=bar'; $this->assertEquals($expected, $result); $result = Router::queryString('apple=red&pear=green'); $expected = '?apple=red&pear=green'; $this->assertEquals($expected, $result); $result = Router::queryString('foo=bar', array('php' => 'nut', 'jose' => 'zap'), true); $expected = '?foo=bar&php=nut&jose=zap'; $this->assertEquals($expected, $result); $result = Router::queryString('foo=bar&', array('php' => 'nut', 'jose' => 'zap'), true); $expected = '?foo=bar&php=nut&jose=zap'; $this->assertEquals($expected, $result); $result = Router::queryString('foo=bar&', array('php' => 'nut', 'jose' => 'zap')); $expected = '?foo=bar&php=nut&jose=zap'; $this->assertEquals($expected, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/TestSuite/000077500000000000000000000000001265552240500202765ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/TestSuite/CakeTestCaseTest.php000066400000000000000000000312601265552240500241500ustar00rootroot00000000000000Reporter = $this->getMock('CakeHtmlReporter'); } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Result); unset($this->Reporter); } /** * testAssertTags * * @return void */ public function testAssertTagsBasic() { $test = new AssertTagsTestCase('testAssertTagsQuotes'); $result = $test->run(); $this->assertEquals(0, $result->errorCount()); $this->assertTrue($result->wasSuccessful()); $this->assertEquals(0, $result->failureCount()); } /** * test assertTags works with single and double quotes * * @return void */ public function testAssertTagsQuoting() { $input = '
My link'; $pattern = array( 'a' => array('href' => '/test.html', 'class' => 'active'), 'My link', '/a' ); $this->assertTags($input, $pattern); $input = "My link"; $pattern = array( 'a' => array('href' => '/test.html', 'class' => 'active'), 'My link', '/a' ); $this->assertTags($input, $pattern); $input = "My link"; $pattern = array( 'a' => array('href' => 'preg:/.*\.html/', 'class' => 'active'), 'My link', '/a' ); $this->assertTags($input, $pattern); $input = "Text"; $pattern = array( 'assertTags($input, $pattern); $input = "Text"; $pattern = array( 'span' => array('class'), 'assertTags($input, $pattern); } /** * Test that assertTags runs quickly. * * @return void */ public function testAssertTagsRuntimeComplexity() { $pattern = array( 'div' => array( 'attr1' => 'val1', 'attr2' => 'val2', 'attr3' => 'val3', 'attr4' => 'val4', 'attr5' => 'val5', 'attr6' => 'val6', 'attr7' => 'val7', 'attr8' => 'val8', ), 'My div', '/div' ); $input = '
' . 'My div' . '
'; $this->assertTags($input, $pattern); } /** * testNumericValuesInExpectationForAssertTags * * @return void */ public function testNumericValuesInExpectationForAssertTags() { $test = new AssertTagsTestCase('testNumericValuesInExpectationForAssertTags'); $result = $test->run(); $this->assertEquals(0, $result->errorCount()); $this->assertTrue($result->wasSuccessful()); $this->assertEquals(0, $result->failureCount()); } /** * testBadAssertTags * * @return void */ public function testBadAssertTags() { $test = new AssertTagsTestCase('testBadAssertTags'); $result = $test->run(); $this->assertEquals(0, $result->errorCount()); $this->assertFalse($result->wasSuccessful()); $this->assertEquals(1, $result->failureCount()); $test = new AssertTagsTestCase('testBadAssertTags2'); $result = $test->run(); $this->assertEquals(0, $result->errorCount()); $this->assertFalse($result->wasSuccessful()); $this->assertEquals(1, $result->failureCount()); } /** * testLoadFixtures * * @return void */ public function testLoadFixtures() { $test = new FixturizedTestCase('testFixturePresent'); $manager = $this->getMock('CakeFixtureManager'); $manager->fixturize($test); $test->fixtureManager = $manager; $manager->expects($this->once())->method('load'); $manager->expects($this->once())->method('unload'); $result = $test->run(); $this->assertEquals(0, $result->errorCount()); $this->assertTrue($result->wasSuccessful()); $this->assertEquals(0, $result->failureCount()); } /** * testLoadFixturesOnDemand * * @return void */ public function testLoadFixturesOnDemand() { $test = new FixturizedTestCase('testFixtureLoadOnDemand'); $test->autoFixtures = false; $manager = $this->getMock('CakeFixtureManager'); $manager->fixturize($test); $test->fixtureManager = $manager; $manager->expects($this->once())->method('loadSingle'); $result = $test->run(); $this->assertEquals(0, $result->errorCount()); } /** * testLoadFixturesOnDemand * * @return void */ public function testUnoadFixturesAfterFailure() { $test = new FixturizedTestCase('testFixtureLoadOnDemand'); $test->autoFixtures = false; $manager = $this->getMock('CakeFixtureManager'); $manager->fixturize($test); $test->fixtureManager = $manager; $manager->expects($this->once())->method('loadSingle'); $result = $test->run(); $this->assertEquals(0, $result->errorCount()); } /** * testThrowException * * @return void */ public function testThrowException() { $test = new FixturizedTestCase('testThrowException'); $test->autoFixtures = false; $manager = $this->getMock('CakeFixtureManager'); $manager->fixturize($test); $test->fixtureManager = $manager; $manager->expects($this->once())->method('unload'); $result = $test->run(); $this->assertEquals(1, $result->errorCount()); } /** * testSkipIf * * @return void */ public function testSkipIf() { $test = new FixturizedTestCase('testSkipIfTrue'); $result = $test->run(); $this->assertEquals(1, $result->skippedCount()); $test = new FixturizedTestCase('testSkipIfFalse'); $result = $test->run(); $this->assertEquals(0, $result->skippedCount()); } /** * Test that CakeTestCase::setUp() backs up values. * * @return void */ public function testSetupBackUpValues() { $this->assertArrayHasKey('debug', $this->_configure); $this->assertArrayHasKey('Plugin', $this->_pathRestore); } /** * test assertTextNotEquals() * * @return void */ public function testAssertTextNotEquals() { $one = "\r\nOne\rTwooo"; $two = "\nOne\nTwo"; $this->assertTextNotEquals($one, $two); } /** * test assertTextEquals() * * @return void */ public function testAssertTextEquals() { $one = "\r\nOne\rTwo"; $two = "\nOne\nTwo"; $this->assertTextEquals($one, $two); } /** * test assertTextStartsWith() * * @return void */ public function testAssertTextStartsWith() { $stringDirty = "some\nstring\r\nwith\rdifferent\nline endings!"; $this->assertStringStartsWith("some\nstring", $stringDirty); $this->assertStringStartsNotWith("some\r\nstring\r\nwith", $stringDirty); $this->assertStringStartsNotWith("some\nstring\nwith", $stringDirty); $this->assertTextStartsWith("some\nstring\nwith", $stringDirty); $this->assertTextStartsWith("some\r\nstring\r\nwith", $stringDirty); } /** * test assertTextStartsNotWith() * * @return void */ public function testAssertTextStartsNotWith() { $stringDirty = "some\nstring\r\nwith\rdifferent\nline endings!"; $this->assertTextStartsNotWith("some\nstring\nwithout", $stringDirty); } /** * test assertTextEndsWith() * * @return void */ public function testAssertTextEndsWith() { $stringDirty = "some\nstring\r\nwith\rdifferent\nline endings!"; $this->assertTextEndsWith("string\nwith\r\ndifferent\rline endings!", $stringDirty); $this->assertTextEndsWith("string\r\nwith\ndifferent\nline endings!", $stringDirty); } /** * test assertTextEndsNotWith() * * @return void */ public function testAssertTextEndsNotWith() { $stringDirty = "some\nstring\r\nwith\rdifferent\nline endings!"; $this->assertStringEndsNotWith("different\nline endings", $stringDirty); $this->assertTextEndsNotWith("different\rline endings", $stringDirty); } /** * test assertTextContains() * * @return void */ public function testAssertTextContains() { $stringDirty = "some\nstring\r\nwith\rdifferent\nline endings!"; $this->assertContains("different", $stringDirty); $this->assertNotContains("different\rline", $stringDirty); $this->assertTextContains("different\rline", $stringDirty); } /** * test assertTextNotContains() * * @return void */ public function testAssertTextNotContains() { $stringDirty = "some\nstring\r\nwith\rdifferent\nline endings!"; $this->assertTextNotContains("different\rlines", $stringDirty); } /** * test getMockForModel() * * @return void */ public function testGetMockForModel() { App::build(array( 'Model' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS ) ), App::RESET); $Post = $this->getMockForModel('Post'); $this->assertEquals('test', $Post->useDbConfig); $this->assertInstanceOf('Post', $Post); $this->assertNull($Post->save(array())); $this->assertNull($Post->find('all')); $this->assertEquals('posts', $Post->useTable); $Post = $this->getMockForModel('Post', array('save')); $this->assertNull($Post->save(array())); $this->assertInternalType('array', $Post->find('all')); } /** * Test getMockForModel on secondary datasources. * * @return void */ public function testGetMockForModelSecondaryDatasource() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'Model/Datasource/Database' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS . 'Datasource' . DS . 'Database' . DS ) ), App::RESET); CakePlugin::load('TestPlugin'); ConnectionManager::create('test_secondary', array( 'datasource' => 'Database/TestLocalDriver' )); $post = $this->getMockForModel('SecondaryPost', array('save')); $this->assertEquals('test_secondary', $post->useDbConfig); ConnectionManager::drop('test_secondary'); } /** * test getMockForModel() with plugin models * * @return void */ public function testGetMockForModelWithPlugin() { App::build(array( 'Plugin' => array( CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS ) ), App::RESET); CakePlugin::load('TestPlugin'); $this->getMockForModel('TestPlugin.TestPluginAppModel'); $this->getMockForModel('TestPlugin.TestPluginComment'); $result = ClassRegistry::init('TestPlugin.TestPluginComment'); $this->assertInstanceOf('TestPluginComment', $result); $this->assertEquals('test', $result->useDbConfig); $TestPluginComment = $this->getMockForModel('TestPlugin.TestPluginComment', array('save')); $this->assertInstanceOf('TestPluginComment', $TestPluginComment); $TestPluginComment->expects($this->at(0)) ->method('save') ->will($this->returnValue(true)); $TestPluginComment->expects($this->at(1)) ->method('save') ->will($this->returnValue(false)); $this->assertTrue($TestPluginComment->save(array())); $this->assertFalse($TestPluginComment->save(array())); } /** * testGetMockForModelModel * * @return void */ public function testGetMockForModelModel() { $Mock = $this->getMockForModel('Model', array('save', 'setDataSource'), array('name' => 'Comment')); $result = ClassRegistry::init('Comment'); $this->assertInstanceOf('Model', $result); $Mock->expects($this->at(0)) ->method('save') ->will($this->returnValue(true)); $Mock->expects($this->at(1)) ->method('save') ->will($this->returnValue(false)); $this->assertTrue($Mock->save(array())); $this->assertFalse($Mock->save(array())); } /** * testGetMockForModelDoesNotExist * * @expectedException MissingModelException * @expectedExceptionMessage Model IDoNotExist could not be found * @return void */ public function testGetMockForModelDoesNotExist() { $this->getMockForModel('IDoNotExist'); } } cakephp-2.8.0/lib/Cake/Test/Case/TestSuite/CakeTestFixtureTest.php000066400000000000000000000363431265552240500247320ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.TestSuite * @since CakePHP(tm) v 1.2.0.4667 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('DboSource', 'Model/Datasource'); App::uses('Model', 'Model'); App::uses('CakeTestFixture', 'TestSuite/Fixture'); /** * CakeTestFixtureTestFixture class * * @package Cake.Test.Case.TestSuite */ class CakeTestFixtureTestFixture extends CakeTestFixture { /** * Name property * * @var string */ public $name = 'FixtureTest'; /** * Table property * * @var string */ public $table = 'fixture_tests'; /** * Fields array * * @var array */ public $fields = array( 'id' => array('type' => 'integer', 'key' => 'primary'), 'name' => array('type' => 'string', 'length' => '255'), 'created' => array('type' => 'datetime') ); /** * Records property * * @var array */ public $records = array( array('name' => 'Gandalf', 'created' => '2009-04-28 19:20:00'), array('name' => 'Captain Picard', 'created' => '2009-04-28 19:20:00'), array('name' => 'Chewbacca', 'created' => '2009-04-28 19:20:00') ); } /** * StringTestFixture class * * @package Cake.Test.Case.TestSuite */ class StringsTestFixture extends CakeTestFixture { /** * Name property * * @var string */ public $name = 'Strings'; /** * Table property * * @var string */ public $table = 'strings'; /** * Fields array * * @var array */ public $fields = array( 'id' => array('type' => 'integer', 'key' => 'primary'), 'name' => array('type' => 'string', 'length' => '255'), 'email' => array('type' => 'string', 'length' => '255'), 'age' => array('type' => 'integer', 'default' => 10) ); /** * Records property * * @var array */ public $records = array( array('name' => 'Mark Doe', 'email' => 'mark.doe@email.com'), array('name' => 'John Doe', 'email' => 'john.doe@email.com', 'age' => 20), array('email' => 'jane.doe@email.com', 'name' => 'Jane Doe', 'age' => 30) ); } /** * InvalidTestFixture class * * @package Cake.Test.Case.TestSuite */ class InvalidTestFixture extends CakeTestFixture { /** * Name property * * @var string */ public $name = 'Invalid'; /** * Table property * * @var string */ public $table = 'invalid'; /** * Fields array - missing "email" row * * @var array */ public $fields = array( 'id' => array('type' => 'integer', 'key' => 'primary'), 'name' => array('type' => 'string', 'length' => '255'), 'age' => array('type' => 'integer', 'default' => 10) ); /** * Records property * * @var array */ public $records = array( array('name' => 'Mark Doe', 'email' => 'mark.doe@email.com'), array('name' => 'John Doe', 'email' => 'john.doe@email.com', 'age' => 20), array('email' => 'jane.doe@email.com', 'name' => 'Jane Doe', 'age' => 30) ); } /** * CakeTestFixtureImportFixture class * * @package Cake.Test.Case.TestSuite */ class CakeTestFixtureImportFixture extends CakeTestFixture { /** * Name property * * @var string */ public $name = 'ImportFixture'; /** * Import property * * @var mixed */ public $import = array('table' => 'fixture_tests', 'connection' => 'fixture_test_suite'); } /** * CakeTestFixtureDefaultImportFixture class * * @package Cake.Test.Case.TestSuite */ class CakeTestFixtureDefaultImportFixture extends CakeTestFixture { /** * Name property * * @var string */ public $name = 'ImportFixture'; } /** * FixtureImportTestModel class * * @package Cake.Test.Case.TestSuite */ class FixtureImportTestModel extends Model { public $name = 'FixtureImport'; public $useTable = 'fixture_tests'; public $useDbConfig = 'test'; } class FixturePrefixTest extends Model { public $name = 'FixturePrefix'; public $useTable = '_tests'; public $tablePrefix = 'fixture'; public $useDbConfig = 'test'; } /** * Test case for CakeTestFixture * * @package Cake.Test.Case.TestSuite */ class CakeTestFixtureTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $methods = array_diff(get_class_methods('DboSource'), array('enabled')); $methods[] = 'connect'; $this->criticDb = $this->getMock('DboSource', $methods); $this->criticDb->fullDebug = true; $this->db = ConnectionManager::getDataSource('test'); $this->_backupConfig = $this->db->config; } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); unset($this->criticDb); $this->db->config = $this->_backupConfig; } /** * testInit * * @return void */ public function testInit() { $Fixture = new CakeTestFixtureTestFixture(); unset($Fixture->table); $Fixture->init(); $this->assertEquals('fixture_tests', $Fixture->table); $this->assertEquals('id', $Fixture->primaryKey); $Fixture = new CakeTestFixtureTestFixture(); $Fixture->primaryKey = 'my_random_key'; $Fixture->init(); $this->assertEquals('my_random_key', $Fixture->primaryKey); } /** * test that init() correctly sets the fixture table when the connection * or model have prefixes defined. * * @return void */ public function testInitDbPrefix() { $this->skipIf($this->db instanceof Sqlite, 'Cannot open 2 connections to Sqlite'); $db = ConnectionManager::getDataSource('test'); $Source = new CakeTestFixtureTestFixture(); $Source->drop($db); $Source->create($db); $Source->insert($db); $Fixture = new CakeTestFixtureTestFixture(); $expected = array('id', 'name', 'created'); $this->assertEquals($expected, array_keys($Fixture->fields)); $config = $db->config; $config['prefix'] = 'fixture_test_suite_'; ConnectionManager::create('fixture_test_suite', $config); $Fixture->fields = $Fixture->records = null; $Fixture->import = array('table' => 'fixture_tests', 'connection' => 'test', 'records' => true); $Fixture->init(); $this->assertEquals(count($Fixture->records), count($Source->records)); $Fixture->create(ConnectionManager::getDataSource('fixture_test_suite')); $Fixture = new CakeTestFixtureImportFixture(); $Fixture->fields = $Fixture->records = $Fixture->table = null; $Fixture->import = array('model' => 'FixtureImportTestModel', 'connection' => 'test'); $Fixture->init(); $this->assertEquals(array('id', 'name', 'created'), array_keys($Fixture->fields)); $this->assertEquals('fixture_tests', $Fixture->table); $keys = array_flip(ClassRegistry::keys()); $this->assertFalse(array_key_exists('fixtureimporttestmodel', $keys)); $Fixture->drop(ConnectionManager::getDataSource('fixture_test_suite')); $Source->drop($db); } /** * test that fixtures don't duplicate the test db prefix. * * @return void */ public function testInitDbPrefixDuplication() { $this->skipIf($this->db instanceof Sqlite, 'Cannot open 2 connections to Sqlite'); $db = ConnectionManager::getDataSource('test'); $backPrefix = $db->config['prefix']; $db->config['prefix'] = 'cake_fixture_test_'; ConnectionManager::create('fixture_test_suite', $db->config); $newDb = ConnectionManager::getDataSource('fixture_test_suite'); $newDb->config['prefix'] = 'cake_fixture_test_'; $Source = new CakeTestFixtureTestFixture(); $Source->create($db); $Source->insert($db); $Fixture = new CakeTestFixtureImportFixture(); $Fixture->fields = $Fixture->records = $Fixture->table = null; $Fixture->import = array('model' => 'FixtureImportTestModel', 'connection' => 'test'); $Fixture->init(); $this->assertEquals(array('id', 'name', 'created'), array_keys($Fixture->fields)); $this->assertEquals('fixture_tests', $Fixture->table); $Source->drop($db); $db->config['prefix'] = $backPrefix; } /** * test init with a model that has a tablePrefix declared. * * @return void */ public function testInitModelTablePrefix() { $this->skipIf($this->db instanceof Sqlite, 'Cannot open 2 connections to Sqlite'); $this->skipIf(!empty($this->db->config['prefix']), 'Cannot run this test, you have a database connection prefix.'); $Source = new CakeTestFixtureTestFixture(); $Source->create($this->db); $Source->insert($this->db); $Fixture = new CakeTestFixtureTestFixture(); unset($Fixture->table); $Fixture->fields = $Fixture->records = null; $Fixture->import = array('model' => 'FixturePrefixTest', 'connection' => 'test', 'records' => false); $Fixture->init(); $this->assertEquals('fixture_tests', $Fixture->table); $keys = array_flip(ClassRegistry::keys()); $this->assertFalse(array_key_exists('fixtureimporttestmodel', $keys)); $Source->drop($this->db); } /** * testImport * * @return void */ public function testImport() { $testSuiteDb = ConnectionManager::getDataSource('test'); $testSuiteConfig = $testSuiteDb->config; ConnectionManager::create('new_test_suite', array_merge($testSuiteConfig, array('prefix' => 'new_' . $testSuiteConfig['prefix']))); $newTestSuiteDb = ConnectionManager::getDataSource('new_test_suite'); $Source = new CakeTestFixtureTestFixture(); $Source->create($newTestSuiteDb); $Source->insert($newTestSuiteDb); $Fixture = new CakeTestFixtureDefaultImportFixture(); $Fixture->fields = $Fixture->records = null; $Fixture->import = array('model' => 'FixtureImportTestModel', 'connection' => 'new_test_suite'); $Fixture->init(); $this->assertEquals(array('id', 'name', 'created'), array_keys($Fixture->fields)); $keys = array_flip(ClassRegistry::keys()); $this->assertFalse(array_key_exists('fixtureimporttestmodel', $keys)); $Source->drop($newTestSuiteDb); } /** * test that importing with records works. Make sure to try with postgres as its * handling of aliases is a workaround at best. * * @return void */ public function testImportWithRecords() { $testSuiteDb = ConnectionManager::getDataSource('test'); $testSuiteConfig = $testSuiteDb->config; ConnectionManager::create('new_test_suite', array_merge($testSuiteConfig, array('prefix' => 'new_' . $testSuiteConfig['prefix']))); $newTestSuiteDb = ConnectionManager::getDataSource('new_test_suite'); $Source = new CakeTestFixtureTestFixture(); $Source->create($newTestSuiteDb); $Source->insert($newTestSuiteDb); $Fixture = new CakeTestFixtureDefaultImportFixture(); $Fixture->fields = $Fixture->records = null; $Fixture->import = array( 'model' => 'FixtureImportTestModel', 'connection' => 'new_test_suite', 'records' => true ); $Fixture->init(); $this->assertEquals(array('id', 'name', 'created'), array_keys($Fixture->fields)); $this->assertFalse(empty($Fixture->records[0]), 'No records loaded on importing fixture.'); $this->assertTrue(isset($Fixture->records[0]['name']), 'No name loaded for first record'); $Source->drop($newTestSuiteDb); } /** * test create method * * @return void */ public function testCreate() { $Fixture = new CakeTestFixtureTestFixture(); $this->criticDb->expects($this->atLeastOnce())->method('execute'); $this->criticDb->expects($this->atLeastOnce())->method('createSchema'); $return = $Fixture->create($this->criticDb); $this->assertTrue($this->criticDb->fullDebug); $this->assertTrue($return); unset($Fixture->fields); $return = $Fixture->create($this->criticDb); $this->assertFalse($return); } /** * test the insert method * * @return void */ public function testInsert() { $Fixture = new CakeTestFixtureTestFixture(); $this->criticDb->expects($this->atLeastOnce()) ->method('insertMulti') ->will($this->returnCallback(array($this, 'insertCallback'))); $return = $Fixture->insert($this->criticDb); $this->assertTrue(!empty($this->insertMulti)); $this->assertTrue($this->criticDb->fullDebug); $this->assertTrue($return); $this->assertEquals('fixture_tests', $this->insertMulti['table']); $this->assertEquals(array('name', 'created'), $this->insertMulti['fields']); $expected = array( array('Gandalf', '2009-04-28 19:20:00'), array('Captain Picard', '2009-04-28 19:20:00'), array('Chewbacca', '2009-04-28 19:20:00') ); $this->assertEquals($expected, $this->insertMulti['values']); } /** * Helper function to be used as callback and store the parameters of an insertMulti call * * @param string $table * @param string $fields * @param string $values * @return bool true */ public function insertCallback($table, $fields, $values) { $this->insertMulti['table'] = $table; $this->insertMulti['fields'] = $fields; $this->insertMulti['values'] = $values; $this->insertMulti['fields_values'] = array(); foreach ($values as $record) { $this->insertMulti['fields_values'][] = array_combine($fields, $record); } return true; } /** * test the insert method * * @return void */ public function testInsertStrings() { $Fixture = new StringsTestFixture(); $this->criticDb->expects($this->atLeastOnce()) ->method('insertMulti') ->will($this->returnCallback(array($this, 'insertCallback'))); $return = $Fixture->insert($this->criticDb); $this->assertTrue($this->criticDb->fullDebug); $this->assertTrue($return); $this->assertEquals('strings', $this->insertMulti['table']); $this->assertEquals(array('name', 'email', 'age'), array_values($this->insertMulti['fields'])); $expected = array( array('Mark Doe', 'mark.doe@email.com', null), array('John Doe', 'john.doe@email.com', 20), array('Jane Doe', 'jane.doe@email.com', 30), ); $this->assertEquals($expected, $this->insertMulti['values']); $expected = array( array( 'name' => 'Mark Doe', 'email' => 'mark.doe@email.com', 'age' => null ), array( 'name' => 'John Doe', 'email' => 'john.doe@email.com', 'age' => 20 ), array( 'name' => 'Jane Doe', 'email' => 'jane.doe@email.com', 'age' => 30 ), ); $this->assertEquals($expected, $this->insertMulti['fields_values']); } /** * test the insert method with invalid fixture * * @expectedException CakeException * @return void */ public function testInsertInvalid() { $Fixture = new InvalidTestFixture(); $Fixture->insert($this->criticDb); } /** * Test the drop method * * @return void */ public function testDrop() { $Fixture = new CakeTestFixtureTestFixture(); $this->criticDb->expects($this->at(1))->method('execute')->will($this->returnValue(true)); $this->criticDb->expects($this->at(3))->method('execute')->will($this->returnValue(false)); $this->criticDb->expects($this->exactly(2))->method('dropSchema'); $return = $Fixture->drop($this->criticDb); $this->assertTrue($this->criticDb->fullDebug); $this->assertTrue($return); $return = $Fixture->drop($this->criticDb); $this->assertTrue($return); unset($Fixture->fields); $return = $Fixture->drop($this->criticDb); $this->assertFalse($return); } /** * Test the truncate method. * * @return void */ public function testTruncate() { $Fixture = new CakeTestFixtureTestFixture(); $this->criticDb->expects($this->atLeastOnce())->method('truncate'); $Fixture->truncate($this->criticDb); $this->assertTrue($this->criticDb->fullDebug); } } cakephp-2.8.0/lib/Cake/Test/Case/TestSuite/CakeTestSuiteTest.php000066400000000000000000000057531265552240500243760ustar00rootroot00000000000000getMock('CakeTestSuite', array('addTestFile')); $suite ->expects($this->exactly($count)) ->method('addTestFile'); $suite->addTestDirectory($testFolder); } /** * testAddTestDirectoryRecursive * * @return void */ public function testAddTestDirectoryRecursive() { $testFolder = CORE_TEST_CASES . DS . 'Cache'; $count = count(glob($testFolder . DS . '*Test.php')); $count += count(glob($testFolder . DS . 'Engine' . DS . '*Test.php')); $suite = $this->getMock('CakeTestSuite', array('addTestFile')); $suite ->expects($this->exactly($count)) ->method('addTestFile'); $suite->addTestDirectoryRecursive($testFolder); } /** * testAddTestDirectoryRecursiveWithHidden * * @return void */ public function testAddTestDirectoryRecursiveWithHidden() { $this->skipIf(!is_writable(TMP), 'Cant addTestDirectoryRecursiveWithHidden unless the tmp folder is writable.'); $Folder = new Folder(TMP . 'MyTestFolder', true, 0777); mkdir($Folder->path . DS . '.svn', 0777, true); touch($Folder->path . DS . '.svn' . DS . 'InHiddenFolderTest.php'); touch($Folder->path . DS . 'NotHiddenTest.php'); touch($Folder->path . DS . '.HiddenTest.php'); $suite = $this->getMock('CakeTestSuite', array('addTestFile')); $suite ->expects($this->exactly(1)) ->method('addTestFile'); $suite->addTestDirectoryRecursive($Folder->pwd()); $Folder->delete(); } /** * testAddTestDirectoryRecursiveWithNonPhp * * @return void */ public function testAddTestDirectoryRecursiveWithNonPhp() { $this->skipIf(!is_writable(TMP), 'Cant addTestDirectoryRecursiveWithNonPhp unless the tmp folder is writable.'); $Folder = new Folder(TMP . 'MyTestFolder', true, 0777); touch($Folder->path . DS . 'BackupTest.php~'); touch($Folder->path . DS . 'SomeNotesTest.txt'); touch($Folder->path . DS . 'NotHiddenTest.php'); $suite = $this->getMock('CakeTestSuite', array('addTestFile')); $suite ->expects($this->exactly(1)) ->method('addTestFile'); $suite->addTestDirectoryRecursive($Folder->pwd()); $Folder->delete(); } } cakephp-2.8.0/lib/Cake/Test/Case/TestSuite/ControllerTestCaseTest.php000066400000000000000000000420761265552240500254370ustar00rootroot00000000000000 array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS), 'Controller' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Controller' . DS), 'Model' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Model' . DS), 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) ), App::RESET); CakePlugin::load(array('TestPlugin', 'TestPluginTwo')); $this->Case = $this->getMockForAbstractClass('ControllerTestCase'); Router::reload(); } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); CakePlugin::unload(); $this->Case->controller = null; } /** * Test that ControllerTestCase::generate() creates mock objects correctly * * @return void */ public function testGenerate() { if (defined('APP_CONTROLLER_EXISTS')) { $this->markTestSkipped('AppController exists, cannot run.'); } $Posts = $this->Case->generate('Posts'); $this->assertEquals('Posts', $Posts->name); $this->assertEquals('Post', $Posts->modelClass); $this->assertNull($Posts->response->send()); $Posts = $this->Case->generate('Posts', array( 'methods' => array( 'render' ) )); $this->assertNull($Posts->render('index')); $Posts = $this->Case->generate('Posts', array( 'models' => array('Post'), 'components' => array('RequestHandler') )); $this->assertInstanceOf('Post', $Posts->Post); $this->assertNull($Posts->Post->save(array())); $this->assertNull($Posts->Post->find('all')); $this->assertEquals('posts', $Posts->Post->useTable); $this->assertNull($Posts->RequestHandler->isAjax()); $Posts = $this->Case->generate('Posts', array( 'models' => array( 'Post' => true ) )); $this->assertNull($Posts->Post->save(array())); $this->assertNull($Posts->Post->find('all')); $Posts = $this->Case->generate('Posts', array( 'models' => array( 'Post' => array('save'), ) )); $this->assertNull($Posts->Post->save(array())); $this->assertInternalType('array', $Posts->Post->find('all')); $Posts = $this->Case->generate('Posts', array( 'models' => array('Post'), 'components' => array( 'RequestHandler' => array('isPut'), 'Email' => array('send'), 'Session' ) )); $Posts->RequestHandler->expects($this->once()) ->method('isPut') ->will($this->returnValue(true)); $this->assertTrue($Posts->RequestHandler->isPut()); $Posts->Auth->Session->expects($this->any()) ->method('write') ->will($this->returnValue('written!')); $this->assertEquals('written!', $Posts->Auth->Session->write('something')); } /** * testGenerateWithComponentConfig * * @return void */ public function testGenerateWithComponentConfig() { $Tests = $this->Case->generate('TestConfigs', array( )); $expected = array('some' => 'config'); $settings = array_intersect_key($Tests->RequestHandler->settings, array('some' => 'foo')); $this->assertSame($expected, $settings, 'A mocked component should have the same config as an unmocked component'); $Tests = $this->Case->generate('TestConfigs', array( 'components' => array( 'RequestHandler' => array('isPut') ) )); $expected = array('some' => 'config'); $settings = array_intersect_key($Tests->RequestHandler->settings, array('some' => 'foo')); $this->assertSame($expected, $settings, 'A mocked component should have the same config as an unmocked component'); } /** * Tests ControllerTestCase::generate() using classes from plugins * * @return void */ public function testGenerateWithPlugin() { $Tests = $this->Case->generate('TestPlugin.Tests', array( 'models' => array( 'TestPlugin.TestPluginComment' ), 'components' => array( 'TestPlugin.Plugins' ) )); $this->assertEquals('Tests', $Tests->name); $this->assertInstanceOf('PluginsComponent', $Tests->Plugins); $result = ClassRegistry::init('TestPlugin.TestPluginComment'); $this->assertInstanceOf('TestPluginComment', $result); $Tests = $this->Case->generate('ControllerTestCaseTest', array( 'models' => array( 'TestPlugin.TestPluginComment' => array('save') ) )); $this->assertInstanceOf('TestPluginComment', $Tests->TestPluginComment); $Tests->TestPluginComment->expects($this->at(0)) ->method('save') ->will($this->returnValue(true)); $Tests->TestPluginComment->expects($this->at(1)) ->method('save') ->will($this->returnValue(false)); $this->assertTrue($Tests->TestPluginComment->save(array())); $this->assertFalse($Tests->TestPluginComment->save(array())); } /** * Tests testAction * * @return void */ public function testTestAction() { $this->Case->generate('TestsApps'); $this->Case->testAction('/tests_apps/index'); $this->assertInternalType('array', $this->Case->controller->viewVars); $this->Case->testAction('/tests_apps/set_action'); $results = $this->Case->controller->viewVars; $expected = array( 'var' => 'string' ); $this->assertEquals($expected, $results); $result = $this->Case->controller->response->body(); $this->assertRegExp('/This is the TestsAppsController index view/', $result); $Controller = $this->Case->generate('TestsApps'); $this->Case->testAction('/tests_apps/redirect_to'); $results = $this->Case->headers; $expected = array( 'Location' => 'http://cakephp.org' ); $this->assertEquals($expected, $results); $this->assertSame(302, $Controller->response->statusCode()); } /** * Test array URLs with testAction() * * @return void */ public function testTestActionArrayUrls() { $this->Case->generate('TestsApps'); $this->Case->testAction(array('controller' => 'tests_apps', 'action' => 'index')); $this->assertInternalType('array', $this->Case->controller->viewVars); } /** * Test that file responses don't trigger errors. * * @return void */ public function testActionWithFile() { $Controller = $this->Case->generate('TestsApps'); $this->Case->testAction('/tests_apps/file'); $this->assertArrayHasKey('Content-Disposition', $Controller->response->header()); $this->assertArrayHasKey('Content-Length', $Controller->response->header()); } /** * Make sure testAction() can hit plugin controllers. * * @return void */ public function testTestActionWithPlugin() { $this->Case->generate('TestPlugin.Tests'); $this->Case->testAction('/test_plugin/tests/index'); $this->assertEquals('It is a variable', $this->Case->controller->viewVars['test_value']); } /** * Tests using loaded routes during tests * * @return void */ public function testUseRoutes() { Router::connect('/:controller/:action/*'); include CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'routes.php'; $controller = $this->Case->generate('TestsApps'); $controller->Components->load('RequestHandler'); $result = $this->Case->testAction('/tests_apps/index.json', array('return' => 'contents')); $result = json_decode($result, true); $expected = array('cakephp' => 'cool'); $this->assertEquals($expected, $result); include CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'routes.php'; $result = $this->Case->testAction('/some_alias'); $this->assertEquals(5, $result); } /** * Tests not using loaded routes during tests * * @expectedException MissingActionException * @return void */ public function testSkipRoutes() { Router::connect('/:controller/:action/*'); include CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS . 'routes.php'; $this->Case->loadRoutes = false; $this->Case->testAction('/tests_apps/missing_action.json', array('return' => 'view')); } /** * Tests backwards compatibility with setting the return type * * @return void */ public function testBCSetReturn() { $this->Case->autoMock = true; $result = $this->Case->testAction('/tests_apps/some_method'); $this->assertEquals(5, $result); $data = array('var' => 'set'); $result = $this->Case->testAction('/tests_apps_posts/post_var', array( 'data' => $data, 'return' => 'vars' )); $this->assertEquals($data, $result['data']); $result = $this->Case->testAction('/tests_apps/set_action', array( 'return' => 'view' )); $this->assertEquals('This is the TestsAppsController index view string', $result); $result = $this->Case->testAction('/tests_apps/set_action', array( 'return' => 'contents' )); $this->assertRegExp('/assertRegExp('/This is the TestsAppsController index view/', $result); $this->assertRegExp('/<\/html>/', $result); } /** * Tests sending POST data to testAction * * @return void */ public function testTestActionPostData() { $this->Case->autoMock = true; $data = array( 'Post' => array( 'name' => 'Some Post' ) ); $this->Case->testAction('/tests_apps_posts/post_var', array( 'data' => $data )); $this->assertEquals($this->Case->controller->viewVars['data'], $data); $this->assertEquals($this->Case->controller->data, $data); $this->Case->testAction('/tests_apps_posts/post_var/named:param', array( 'data' => $data )); $expected = array( 'named' => 'param' ); $this->assertEquals($expected, $this->Case->controller->request->named); $this->assertEquals($this->Case->controller->data, $data); $result = $this->Case->testAction('/tests_apps_posts/post_var', array( 'return' => 'vars', 'method' => 'post', 'data' => array( 'name' => 'is jonas', 'pork' => 'and beans', ) )); $this->assertEquals(array('name', 'pork'), array_keys($result['data'])); $result = $this->Case->testAction('/tests_apps_posts/add', array('return' => 'vars')); $this->assertTrue(array_key_exists('posts', $result)); $this->assertEquals(4, count($result['posts'])); $this->assertTrue($this->Case->controller->request->is('post')); } /** * Tests sending GET data to testAction * * @return void */ public function testTestActionGetData() { $this->Case->autoMock = true; $this->Case->testAction('/tests_apps_posts/url_var', array( 'method' => 'get', 'data' => array( 'some' => 'var', 'lackof' => 'creativity' ) )); $this->assertEquals('var', $this->Case->controller->request->query['some']); $this->assertEquals('creativity', $this->Case->controller->request->query['lackof']); $result = $this->Case->testAction('/tests_apps_posts/url_var/var1:value1/var2:val2', array( 'return' => 'vars', 'method' => 'get', )); $this->assertEquals(array('var1', 'var2'), array_keys($result['params']['named'])); $result = $this->Case->testAction('/tests_apps_posts/url_var/gogo/val2', array( 'return' => 'vars', 'method' => 'get', )); $this->assertEquals(array('gogo', 'val2'), $result['params']['pass']); $this->Case->testAction('/tests_apps_posts/url_var', array( 'return' => 'vars', 'method' => 'get', 'data' => array( 'red' => 'health', 'blue' => 'mana' ) )); $query = $this->Case->controller->request->query; $this->assertTrue(isset($query['red'])); $this->assertTrue(isset($query['blue'])); } /** * Test that REST actions with XML/JSON input work. * * @return void */ public function testTestActionJsonData() { $result = $this->Case->testAction('/tests_apps_posts/input_data', array( 'return' => 'vars', 'method' => 'post', 'data' => '{"key":"value","json":true}' )); $this->assertEquals('value', $result['data']['key']); $this->assertTrue($result['data']['json']); } /** * Tests autoMock ability * * @return void */ public function testAutoMock() { $this->Case->autoMock = true; $this->Case->testAction('/tests_apps/set_action'); $results = $this->Case->controller->viewVars; $expected = array( 'var' => 'string' ); $this->assertEquals($expected, $results); } /** * Test using testAction and not mocking * * @return void */ public function testNoMocking() { $result = $this->Case->testAction('/tests_apps/some_method'); $this->Case->assertEquals(5, $result); $data = array('var' => 'set'); $result = $this->Case->testAction('/tests_apps_posts/post_var', array( 'data' => $data, 'return' => 'vars' )); $this->assertEquals($data, $result['data']); $result = $this->Case->testAction('/tests_apps/set_action', array( 'return' => 'view' )); $this->assertEquals('This is the TestsAppsController index view string', $result); $result = $this->Case->testAction('/tests_apps/set_action', array( 'return' => 'contents' )); $this->assertRegExp('/assertRegExp('/This is the TestsAppsController index view/', $result); $this->assertRegExp('/<\/html>/', $result); } /** * Test that controllers don't get reused. * * @return void */ public function testNoControllerReuse() { $this->Case->autoMock = true; $result = $this->Case->testAction('/tests_apps/index', array( 'data' => array('var' => 'first call'), 'method' => 'get', 'return' => 'contents', )); $this->assertContains('assertContains('This is the TestsAppsController index view', $result); $this->assertContains('first call', $result); $this->assertContains('', $result); $result = $this->Case->testAction('/tests_apps/index', array( 'data' => array('var' => 'second call'), 'method' => 'get', 'return' => 'contents' )); $this->assertContains('second call', $result); $result = $this->Case->testAction('/tests_apps/index', array( 'data' => array('var' => 'third call'), 'method' => 'get', 'return' => 'contents' )); $this->assertContains('third call', $result); } /** * Test that multiple calls to redirect in the same test method don't cause issues. * * @return void */ public function testTestActionWithMultipleRedirect() { $this->Case->generate('TestsApps'); $options = array('method' => 'get'); $this->Case->testAction('/tests_apps/redirect_to', $options); $this->Case->testAction('/tests_apps/redirect_to', $options); } /** * Tests that Components storing response or request objects internally during construct * will always have a fresh reference to those object available * * @return void * @see https://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/2705-requesthandler-weird-behavior */ public function testComponentsSameRequestAndResponse() { $this->Case->generate('TestsApps'); $options = array('method' => 'get'); $this->Case->testAction('/tests_apps/index', $options); $this->assertSame($this->Case->controller->response, $this->Case->controller->RequestHandler->response); $this->assertSame($this->Case->controller->request, $this->Case->controller->RequestHandler->request); } /** * Test that testAction() doesn't destroy data in GET & POST * * @return void */ public function testRestoreGetPost() { $restored = array('new' => 'value'); $_GET = $restored; $_POST = $restored; $this->Case->generate('TestsApps'); $options = array('method' => 'get'); $this->Case->testAction('/tests_apps/index', $options); $this->assertEquals($restored, $_GET); $this->assertEquals($restored, $_POST); } } cakephp-2.8.0/lib/Cake/Test/Case/TestSuite/Fixture/000077500000000000000000000000001265552240500217245ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/TestSuite/Fixture/CakeFixtureManagerTest.php000066400000000000000000000054631265552240500270120ustar00rootroot00000000000000fixtureManager = new CakeFixtureManager(); } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); unset($this->fixtureManager); } /** * testLoadTruncatesTable * * @return void */ public function testLoadTruncatesTable() { $MockFixture = $this->getMock('UuidFixture', array('truncate')); $MockFixture ->expects($this->once()) ->method('truncate') ->will($this->returnValue(true)); $fixtureManager = $this->fixtureManager; $fixtureManagerReflection = new ReflectionClass($fixtureManager); $loadedProperty = $fixtureManagerReflection->getProperty('_loaded'); $loadedProperty->setAccessible(true); $loadedProperty->setValue($fixtureManager, array('core.uuid' => $MockFixture)); $TestCase = $this->getMock('CakeTestCase'); $TestCase->fixtures = array('core.uuid'); $TestCase->autoFixtures = true; $TestCase->dropTables = false; $fixtureManager->load($TestCase); } /** * testLoadSingleTruncatesTable * * @return void */ public function testLoadSingleTruncatesTable() { $MockFixture = $this->getMock('UuidFixture', array('truncate')); $MockFixture ->expects($this->once()) ->method('truncate') ->will($this->returnValue(true)); $fixtureManager = $this->fixtureManager; $fixtureManagerReflection = new ReflectionClass($fixtureManager); $fixtureMapProperty = $fixtureManagerReflection->getProperty('_fixtureMap'); $fixtureMapProperty->setAccessible(true); $fixtureMapProperty->setValue($fixtureManager, array('UuidFixture' => $MockFixture)); $dboMethods = array_diff(get_class_methods('DboSource'), array('enabled')); $dboMethods[] = 'connect'; $db = $this->getMock('DboSource', $dboMethods); $db->config['prefix'] = ''; $fixtureManager->loadSingle('Uuid', $db, false); } } cakephp-2.8.0/lib/Cake/Test/Case/TestSuite/HtmlCoverageReportTest.php000066400000000000000000000154511265552240500254310ustar00rootroot00000000000000 array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) ), App::RESET); CakePlugin::load(array('TestPlugin')); $reporter = new CakeBaseReporter(); $reporter->params = array('app' => false, 'plugin' => false, 'group' => false); $coverage = array(); $this->Coverage = new HtmlCoverageReport($coverage, $reporter); } /** * test getting the path filters. * * @return void */ public function testGetPathFilter() { $this->Coverage->appTest = false; $result = $this->Coverage->getPathFilter(); $this->assertEquals(CAKE, $result); $this->Coverage->appTest = true; $result = $this->Coverage->getPathFilter(); $this->assertEquals(ROOT . DS . APP_DIR . DS, $result); $this->Coverage->appTest = false; $this->Coverage->pluginTest = 'TestPlugin'; $result = $this->Coverage->getPathFilter(); $this->assertEquals(CakePlugin::path('TestPlugin'), $result); } /** * test filtering coverage data. * * @return void */ public function testFilterCoverageDataByPathRemovingElements() { $data = array( CAKE . 'dispatcher.php' => array( 10 => -1, 12 => 1 ), APP . 'app_model.php' => array( 50 => 1, 52 => -1 ) ); $this->Coverage->setCoverage($data); $result = $this->Coverage->filterCoverageDataByPath(CAKE); $this->assertTrue(isset($result[CAKE . 'dispatcher.php'])); $this->assertFalse(isset($result[APP . 'app_model.php'])); } /** * test generating HTML reports from file arrays. * * @return void */ public function testGenerateDiff() { $file = array( 'line 1', 'line 2', 'line 3', 'line 4', 'line 5', 'line 6', 'line 7', 'line 8', 'line 9', 'line 10', ); $coverage = array( 1 => array(array('id' => 'HtmlCoverageReportTest::testGenerateDiff')), 2 => -2, 3 => array(array('id' => 'HtmlCoverageReportTest::testGenerateDiff')), 4 => array(array('id' => 'HtmlCoverageReportTest::testGenerateDiff')), 5 => -1, 6 => array(array('id' => 'HtmlCoverageReportTest::testGenerateDiff')), 7 => array(array('id' => 'HtmlCoverageReportTest::testGenerateDiff')), 8 => array(array('id' => 'HtmlCoverageReportTest::testGenerateDiff')), 9 => -1, 10 => array(array('id' => 'HtmlCoverageReportTest::testGenerateDiff')) ); $result = $this->Coverage->generateDiff('myfile.php', $file, $coverage); $this->assertRegExp('/myfile\.php Code coverage\: \d+\.?\d*\%/', $result); $this->assertRegExp('/
assertRegExp('/
/', $result);
		foreach ($file as $i => $line) {
			$this->assertTrue(strpos($line, $result) !== 0, 'Content is missing ' . $i);
			$class = 'covered';
			if (in_array($i + 1, array(5, 9, 2))) {
				$class = 'uncovered';
			}
			if ($i + 1 === 2) {
				$class .= ' dead';
			}
			$this->assertTrue(strpos($class, $result) !== 0, 'Class name is wrong ' . $i);
		}
	}

/**
 * Test that coverage works with phpunit 3.6 as the data formats from coverage are totally different.
 *
 * @return void
 */
	public function testPhpunit36Compatibility() {
		$file = array(
			'line 1',
			'line 2',
			'line 3',
			'line 4',
			'line 5',
			'line 6',
			'line 7',
			'line 8',
			'line 9',
			'line 10',
		);
		$coverage = array(
			1 => array('HtmlCoverageReportTest::testGenerateDiff'),
			2 => null,
			3 => array('HtmlCoverageReportTest::testGenerateDiff'),
			4 => array('HtmlCoverageReportTest::testGenerateDiff'),
			5 => array(),
			6 => array('HtmlCoverageReportTest::testGenerateDiff'),
			7 => array('HtmlCoverageReportTest::testGenerateDiff'),
			8 => array('HtmlCoverageReportTest::testGenerateDiff'),
			9 => array(),
			10 => array('HtmlCoverageReportTest::testSomething', 'HtmlCoverageReportTest::testGenerateDiff')
		);

		$result = $this->Coverage->generateDiff('myfile.php', $file, $coverage);
		$this->assertRegExp('/myfile\.php Code coverage\: \d+\.?\d*\%/', $result);
		$this->assertRegExp('/
assertRegExp('/
/', $result);
		foreach ($file as $i => $line) {
			$this->assertTrue(strpos($line, $result) !== 0, 'Content is missing ' . $i);
			$class = 'covered';
			if (in_array($i + 1, array(5, 9, 2))) {
				$class = 'uncovered';
			}
			if ($i + 1 === 2) {
				$class .= ' dead';
			}
			$this->assertTrue(strpos($class, $result) !== 0, 'Class name is wrong ' . $i);
		}
	}

/**
 * test that covering methods show up as title attributes for lines.
 *
 * @return void
 */
	public function testCoveredLinesTitleAttributes() {
		$file = array(
			'line 1',
			'line 2',
			'line 3',
			'line 4',
			'line 5',
		);

		$coverage = array(
			1 => array(array('id' => 'HtmlCoverageReportTest::testAwesomeness')),
			2 => -2,
			3 => array(array('id' => 'HtmlCoverageReportTest::testCakeIsSuperior')),
			4 => array(array('id' => 'HtmlCoverageReportTest::testOther')),
			5 => -1
		);

		$result = $this->Coverage->generateDiff('myfile.php', $file, $coverage);

		$this->assertTrue(
			strpos($result, "title=\"Covered by:\nHtmlCoverageReportTest::testAwesomeness\n\">1") !== false,
			'Missing method coverage for line 1'
		);
		$this->assertTrue(
			strpos($result, "title=\"Covered by:\nHtmlCoverageReportTest::testCakeIsSuperior\n\">3") !== false,
			'Missing method coverage for line 3'
		);
		$this->assertTrue(
			strpos($result, "title=\"Covered by:\nHtmlCoverageReportTest::testOther\n\">4") !== false,
			'Missing method coverage for line 4'
		);
		$this->assertTrue(
			strpos($result, "title=\"\">5") !== false,
			'Coverage report is wrong for line 5'
		);
	}

/**
 * tearDown
 *
 * @return void
 */
	public function tearDown() {
		CakePlugin::unload();
		unset($this->Coverage);
		parent::tearDown();
	}
}
cakephp-2.8.0/lib/Cake/Test/Case/TestSuite/Stub/000077500000000000000000000000001265552240500212135ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/TestSuite/Stub/ConsoleOutputStubTest.php000066400000000000000000000027671265552240500262610ustar00rootroot00000000000000stub = new ConsoleOutputStub();
	}

/**
 * Test that stub can be used as an instance of ConsoleOutput
 *
 * @return void
 */
	public function testCanActAsConsoleOutput() {
		$this->assertInstanceOf("ConsoleOutput", $this->stub);
	}

/**
 * Test write method
 *
 * @return void
 */
	public function testWrite() {
		$this->stub->write(array("foo", "bar", "baz"));
		$this->assertEquals(array("foo", "bar", "baz"), $this->stub->messages());
	}

/**
 * Test overwrite method
 *
 * @return void
 */
	public function testOverwrite() {
		$this->stub->write(array("foo", "bar", "baz"));
		$this->stub->overwrite("bat");
		$this->assertEquals(array("foo", "bar", "baz", "", "bat"), $this->stub->messages());
	}
}cakephp-2.8.0/lib/Cake/Test/Case/Utility/000077500000000000000000000000001265552240500200105ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/Utility/CakeNumberTest.php000066400000000000000000000566021265552240500234060ustar00rootroot00000000000000
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 * @link          http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
 * @package       Cake.Test.Case.View.Helper
 * @since         CakePHP(tm) v 1.2.0.4206
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 */

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

		$value = 0.00001;
		$result = $this->Number->format($value, array('places' => 1));
		$expected = '$0.0';
		$this->assertEquals($expected, $result);

		$value = -0.00001;
		$result = $this->Number->format($value, array('places' => 1));
		$expected = '$0.0';
		$this->assertEquals($expected, $result);

		$value = 1.23;
		$options = array('decimals' => ',', 'thousands' => '.', 'before' => '', 'after' => ' โ‚ฌ');
		$result = $this->Number->format($value, $options);
		$expected = '1,23 โ‚ฌ';
		$this->assertEquals($expected, $result);
	}

/**
 * testFormatDelta method
 *
 * @return void
 */
	public function testFormatDelta() {
		$value = '100100100';

		$result = $this->Number->formatDelta($value);
		$expected = '+100,100,100.00';
		$this->assertEquals($expected, $result);

		$result = $this->Number->formatDelta($value, array('before' => '', 'after' => ''));
		$expected = '+100,100,100.00';
		$this->assertEquals($expected, $result);

		$result = $this->Number->formatDelta($value, array('before' => '[', 'after' => ']'));
		$expected = '[+100,100,100.00]';
		$this->assertEquals($expected, $result);

		$result = $this->Number->formatDelta(-$value, array('before' => '[', 'after' => ']'));
		$expected = '[-100,100,100.00]';
		$this->assertEquals($expected, $result);

		$result = $this->Number->formatDelta(-$value, array('before' => '[ ', 'after' => ' ]'));
		$expected = '[ -100,100,100.00 ]';
		$this->assertEquals($expected, $result);

		$value = 0;
		$result = $this->Number->formatDelta($value, array('places' => 1, 'before' => '[', 'after' => ']'));
		$expected = '[0.0]';
		$this->assertEquals($expected, $result);

		$value = 0.0001;
		$result = $this->Number->formatDelta($value, array('places' => 1, 'before' => '[', 'after' => ']'));
		$expected = '[0.0]';
		$this->assertEquals($expected, $result);

		$value = 9876.1234;
		$result = $this->Number->formatDelta($value, array('places' => 1, 'decimals' => ',', 'thousands' => '.'));
		$expected = '+9.876,1';
		$this->assertEquals($expected, $result);
	}

/**
 * testMultibyteFormat
 *
 * @return void
 */
	public function testMultibyteFormat() {
		$value = '5199100.0006';
		$result = $this->Number->format($value, array(
			'thousands' => ' ',
			'decimals' => '&',
			'places' => 3,
			'escape' => false,
			'before' => '',
		));
		$expected = '5 199 100&001';
		$this->assertEquals($expected, $result);

		$value = 1000.45;
		$result = $this->Number->format($value, array(
			'thousands' => ',,',
			'decimals' => '.a',
			'escape' => false,
		));
		$expected = '$1,,000.a45';
		$this->assertEquals($expected, $result);

		$value = 519919827593784.00;
		$this->Number->addFormat('RUR', array(
			'thousands' => 'รธโ‚ฌฦ’โ€กโ„ข',
			'decimals' => '(ยง.ยง)',
			'escape' => false,
			'wholeSymbol' => 'โ‚ฌ',
			'wholePosition' => 'after',
		));
		$result = $this->Number->currency($value, 'RUR');
		$expected = '519รธโ‚ฌฦ’โ€กโ„ข919รธโ‚ฌฦ’โ€กโ„ข827รธโ‚ฌฦ’โ€กโ„ข593รธโ‚ฌฦ’โ€กโ„ข784(ยง.ยง)00โ‚ฌ';
		$this->assertEquals($expected, $result);

		$value = '13371337.1337';
		$result = CakeNumber::format($value, array(
			'thousands' => '- |-| /-\ >< () |2 -',
			'decimals' => '- ยฃโ‚ฌโ‚ฌโ€  -',
			'before' => ''
		));
		$expected = '13- |-| /-\ >< () |2 -371- |-| /-\ >< () |2 -337- ยฃโ‚ฌโ‚ฌโ€  -13';
		$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 = 'โ‚ฌ100.100.100,00';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency($value, 'GBP');
		$expected = 'ยฃ100,100,100.00';
		$this->assertEquals($expected, $result);

		$options = array('thousands' => ' ', 'wholeSymbol' => 'EUR ', 'wholePosition' => 'before',
			'decimals' => ',', 'zero' => 'Gratuit');
		$result = $this->Number->currency($value, '', $options);
		$expected = 'EUR 100 100 100,00';
		$this->assertEquals($expected, $result);

		$options = array('after' => 'รธre', 'before' => 'Kr.', 'decimals' => ',', 'thousands' => '.');
		$result = $this->Number->currency(1000.45, null, $options);
		$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);

		$options = array('wholeSymbol' => '$', 'wholePosition' => 'after', 'fractionSymbol' => ' cents');
		$result = $this->Number->currency(0.2, null, $options);
		$expected = '20 cents';
		$this->assertEquals($expected, $result);

		$options = array('wholeSymbol' => '$', 'wholePosition' => 'after', 'fractionSymbol' => 'cents ',
			'fractionPosition' => 'before');
		$result = $this->Number->currency(0.2, null, $options);
		$expected = 'cents 20';
		$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 = 'โ‚ฌ0,20';
		$this->assertEquals($expected, $result);

		$options = array('wholeSymbol' => ' dollars', 'wholePosition' => 'after', 'fractionSymbol' => ' cents',
			'fractionPosition' => 'after');
		$result = $this->Number->currency(12, null, $options);
		$expected = '12.00 dollars';
		$this->assertEquals($expected, $result);

		$options = array('wholeSymbol' => ' dollars', 'wholePosition' => 'after', 'fractionSymbol' => ' cents',
			'fractionPosition' => 'after');
		$result = $this->Number->currency(0.12, null, $options);
		$expected = '12 cents';
		$this->assertEquals($expected, $result);

		$options = array('fractionSymbol' => false, 'fractionPosition' => 'before', 'wholeSymbol' => '$');
		$result = $this->Number->currency(0.5, null, $options);
		$expected = '$0.50';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency(0, 'GBP');
		$expected = 'ยฃ0.00';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency(0.00000, 'GBP');
		$expected = 'ยฃ0.00';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency('0.00000', 'GBP');
		$expected = 'ยฃ0.00';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency('-2.23300', 'JPY');
		$expected = '(ยฅ2.23)';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency('22.389', 'CAD');
		$expected = '$22.39';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency('4.111', 'AUD');
		$expected = '$4.11';
		$this->assertEquals($expected, $result);
	}

/**
 * Test currency format with places and fraction exponents.
 * Places should only matter for non fraction values and vice versa.
 *
 * @return void
 */
	public function testCurrencyWithFractionAndPlaces() {
		$result = $this->Number->currency('1.23', 'GBP', array('places' => 3));
		$expected = 'ยฃ1.230';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency('0.23', 'GBP', array('places' => 3));
		$expected = '23p';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency('0.001', 'GBP', array('places' => 3));
		$expected = '0p';
		$this->assertEquals($expected, $result);

		$this->Number->addFormat('BHD', array('before' => 'BD ', 'fractionSymbol' => ' fils',
			'fractionExponent' => 3));
		$result = $this->Number->currency('1.234', 'BHD', array('places' => 2));
		$expected = 'BD 1.23';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency('0.234', 'BHD', array('places' => 2));
		$expected = '234 fils';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency('0.001', 'BHD', array('places' => 2));
		$expected = '1 fils';
		$this->assertEquals($expected, $result);
	}

/**
 * Test that the default fraction handling does not cause issues.
 *
 * @return void
 */
	public function testCurrencyFractionSymbol() {
		$result = $this->Number->currency(0.2, '', array(
			'places' => 2,
			'decimal' => '.'
		));
		$this->assertEquals('0.2', $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);
	}

/**
 * Test default currency
 *
 * @return void
 */
	public function testDefaultCurrency() {
		$result = $this->Number->defaultCurrency();
		$this->assertEquals('USD', $result);
		$this->Number->addFormat('NOK', array('before' => 'Kr. '));

		$this->Number->defaultCurrency('NOK');
		$result = $this->Number->defaultCurrency();
		$this->assertEquals('NOK', $result);

		$result = $this->Number->currency(1000);
		$expected = 'Kr. 1,000.00';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency(2000);
		$expected = 'Kr. 2,000.00';
		$this->assertEquals($expected, $result);
		$this->Number->defaultCurrency('EUR');
		$result = $this->Number->currency(1000);
		$expected = 'โ‚ฌ1.000,00';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency(2000);
		$expected = 'โ‚ฌ2.000,00';
		$this->assertEquals($expected, $result);

		$this->Number->defaultCurrency('USD');
	}

/**
 * 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 = 'โ‚ฌ100.100.100,00';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency($value, 'GBP');
		$expected = 'ยฃ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 = '(โ‚ฌ100.100.100,00)';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency($value, 'GBP');
		$expected = '(ยฃ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 = '-โ‚ฌ100.100.100,00';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency($value, 'GBP', array('negative' => '-'));
		$expected = '-ยฃ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 = 'โ‚ฌ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 = '(โ‚ฌ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 = '-โ‚ฌ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 = 'โ‚ฌ0,00';
		$this->assertEquals($expected, $result);

		$result = $this->Number->currency($value, 'GBP');
		$expected = 'ยฃ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 = 'ยฃ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('before' => '£ ', 'escape' => true));
		$expected = '&#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('before' => '£', 'after' => false, 'escape' => false));
		$expected = '£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 = 'โ‚ฌ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);
	}

/**
 * test toReadableSize() with locales
 *
 * @return void
 */
	public function testReadableSizeLocalized() {
		$restore = setlocale(LC_NUMERIC, 0);

		$this->skipIf(setlocale(LC_NUMERIC, 'de_DE') === false, "The German locale isn't available.");

		$result = $this->Number->toReadableSize(1321205);
		$this->assertEquals('1,26 MB', $result);

		$result = $this->Number->toReadableSize(1024 * 1024 * 1024 * 512);
		$this->assertEquals('512,00 GB', $result);
		setlocale(LC_NUMERIC, $restore);
	}

/**
 * test precision() with locales
 *
 * @return void
 */
	public function testPrecisionLocalized() {
		$restore = setlocale(LC_NUMERIC, 0);

		$this->skipIf(setlocale(LC_NUMERIC, 'de_DE') === false, "The German locale isn't available.");

		$result = $this->Number->precision(1.234);
		$this->assertEquals('1,234', $result);
		setlocale(LC_NUMERIC, $restore);
	}

/**
 * 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);

		$result = $this->Number->toPercentage(45, 0, array('multiply' => false));
		$expected = '45%';
		$this->assertEquals($expected, $result);

		$result = $this->Number->toPercentage(45, 2, array('multiply' => false));
		$expected = '45.00%';
		$this->assertEquals($expected, $result);

		$result = $this->Number->toPercentage(0, 0, array('multiply' => false));
		$expected = '0%';
		$this->assertEquals($expected, $result);

		$result = $this->Number->toPercentage(0, 4, array('multiply' => false));
		$expected = '0.0000%';
		$this->assertEquals($expected, $result);

		$result = $this->Number->toPercentage(0.456, 0, array('multiply' => true));
		$expected = '46%';
		$this->assertEquals($expected, $result);

		$result = $this->Number->toPercentage(0.456, 2, array('multiply' => true));
		$expected = '45.60%';
		$this->assertEquals($expected, $result);
	}

/**
 * testFromReadableSize
 *
 * @dataProvider filesizes
 * @return void
 */
	public function testFromReadableSize($params, $expected) {
		$result = $this->Number->fromReadableSize($params['size'], $params['default']);
		$this->assertEquals($expected, $result);
	}

/**
 * testFromReadableSize
 *
 * @expectedException CakeException
 * @return void
 */
	public function testFromReadableSizeException() {
		$this->Number->fromReadableSize('bogus', false);
	}

/**
 * filesizes dataprovider
 *
 * @return array
 */
	public function filesizes() {
		return array(
			array(array('size' => '512B', 'default' => false), 512),
			array(array('size' => '1KB', 'default' => false), 1024),
			array(array('size' => '1.5KB', 'default' => false), 1536),
			array(array('size' => '1MB', 'default' => false), 1048576),
			array(array('size' => '1mb', 'default' => false), 1048576),
			array(array('size' => '1.5MB', 'default' => false), 1572864),
			array(array('size' => '1GB', 'default' => false), 1073741824),
			array(array('size' => '1.5GB', 'default' => false), 1610612736),
			array(array('size' => '1K', 'default' => false), 1024),
			array(array('size' => '1.5K', 'default' => false), 1536),
			array(array('size' => '1M', 'default' => false), 1048576),
			array(array('size' => '1m', 'default' => false), 1048576),
			array(array('size' => '1.5M', 'default' => false), 1572864),
			array(array('size' => '1G', 'default' => false), 1073741824),
			array(array('size' => '1.5G', 'default' => false), 1610612736),
			array(array('size' => '512', 'default' => 'Unknown type'), 512),
			array(array('size' => '2VB', 'default' => 'Unknown type'), 'Unknown type')
		);
	}

}
cakephp-2.8.0/lib/Cake/Test/Case/Utility/CakeTextTest.php000066400000000000000000000777751265552240500231200ustar00rootroot00000000000000Text = new CakeText();
	}

/**
 * Tear down object under test
 *
 * @return void
 */
	public function tearDown() {
		parent::tearDown();
		unset($this->Text);
	}

/**
 * testUuidGeneration method
 *
 * @return void
 * @covers ::uuid
 */
	public function testUuidGeneration() {
		$result = CakeText::uuid();
		$pattern = "/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/";
		$match = (bool)preg_match($pattern, $result);
		$this->assertTrue($match);
	}

/**
 * testMultipleUuidGeneration method
 *
 * @return void
 * @covers ::uuid
 */
	public function testMultipleUuidGeneration() {
		$check = array();
		$count = mt_rand(10, 1000);
		$pattern = "/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/";

		for ($i = 0; $i < $count; $i++) {
			$result = CakeText::uuid();
			$match = (bool)preg_match($pattern, $result);
			$this->assertTrue($match);
			$this->assertFalse(in_array($result, $check));
			$check[] = $result;
		}
	}

/**
 * testInsert method
 *
 * @return void
 * @covers ::insert
 */
	public function testInsert() {
		$string = 'some string';
		$expected = 'some string';
		$result = CakeText::insert($string, array());
		$this->assertEquals($expected, $result);

		$string = '2 + 2 = :sum. Cake is :adjective.';
		$expected = '2 + 2 = 4. Cake is yummy.';
		$result = CakeText::insert($string, array('sum' => '4', 'adjective' => 'yummy'));
		$this->assertEquals($expected, $result);

		$string = '2 + 2 = %sum. Cake is %adjective.';
		$result = CakeText::insert($string, array('sum' => '4', 'adjective' => 'yummy'), array('before' => '%'));
		$this->assertEquals($expected, $result);

		$string = '2 + 2 = 2sum2. Cake is 9adjective9.';
		$result = CakeText::insert($string, array('sum' => '4', 'adjective' => 'yummy'), array('format' => '/([\d])%s\\1/'));
		$this->assertEquals($expected, $result);

		$string = '2 + 2 = 12sum21. Cake is 23adjective45.';
		$expected = '2 + 2 = 4. Cake is 23adjective45.';
		$result = CakeText::insert($string, array('sum' => '4', 'adjective' => 'yummy'), array('format' => '/([\d])([\d])%s\\2\\1/'));
		$this->assertEquals($expected, $result);

		$string = ':web :web_site';
		$expected = 'www http';
		$result = CakeText::insert($string, array('web' => 'www', 'web_site' => 'http'));
		$this->assertEquals($expected, $result);

		$string = '2 + 2 = .';
		$expected = '2 + 2 =  '4', 'adjective' => 'yummy'), array('before' => '<', 'after' => '>'));
		$this->assertEquals($expected, $result);

		$string = '2 + 2 = \:sum. Cake is :adjective.';
		$expected = '2 + 2 = :sum. Cake is yummy.';
		$result = CakeText::insert($string, array('sum' => '4', 'adjective' => 'yummy'));
		$this->assertEquals($expected, $result);

		$string = '2 + 2 = !:sum. Cake is :adjective.';
		$result = CakeText::insert($string, array('sum' => '4', 'adjective' => 'yummy'), array('escape' => '!'));
		$this->assertEquals($expected, $result);

		$string = '2 + 2 = \%sum. Cake is %adjective.';
		$expected = '2 + 2 = %sum. Cake is yummy.';
		$result = CakeText::insert($string, array('sum' => '4', 'adjective' => 'yummy'), array('before' => '%'));
		$this->assertEquals($expected, $result);

		$string = ':a :b \:a :a';
		$expected = '1 2 :a 1';
		$result = CakeText::insert($string, array('a' => 1, 'b' => 2));
		$this->assertEquals($expected, $result);

		$string = ':a :b :c';
		$expected = '2 3';
		$result = CakeText::insert($string, array('b' => 2, 'c' => 3), array('clean' => true));
		$this->assertEquals($expected, $result);

		$string = ':a :b :c';
		$expected = '1 3';
		$result = CakeText::insert($string, array('a' => 1, 'c' => 3), array('clean' => true));
		$this->assertEquals($expected, $result);

		$string = ':a :b :c';
		$expected = '2 3';
		$result = CakeText::insert($string, array('b' => 2, 'c' => 3), array('clean' => true));
		$this->assertEquals($expected, $result);

		$string = ':a, :b and :c';
		$expected = '2 and 3';
		$result = CakeText::insert($string, array('b' => 2, 'c' => 3), array('clean' => true));
		$this->assertEquals($expected, $result);

		$string = '":a, :b and :c"';
		$expected = '"1, 2"';
		$result = CakeText::insert($string, array('a' => 1, 'b' => 2), array('clean' => true));
		$this->assertEquals($expected, $result);

		$string = '"${a}, ${b} and ${c}"';
		$expected = '"1, 2"';
		$result = CakeText::insert($string, array('a' => 1, 'b' => 2), array('before' => '${', 'after' => '}', 'clean' => true));
		$this->assertEquals($expected, $result);

		$string = ':alt';
		$expected = '';
		$result = CakeText::insert($string, array('src' => 'foo'), array('clean' => 'html'));

		$this->assertEquals($expected, $result);

		$string = '';
		$expected = '';
		$result = CakeText::insert($string, array('src' => 'foo'), array('clean' => 'html'));
		$this->assertEquals($expected, $result);

		$string = '';
		$expected = '';
		$result = CakeText::insert($string, array('src' => 'foo', 'extra' => 'bar'), array('clean' => 'html'));
		$this->assertEquals($expected, $result);

		$result = CakeText::insert("this is a ? string", "test");
		$expected = "this is a test string";
		$this->assertEquals($expected, $result);

		$result = CakeText::insert("this is a ? string with a ? ? ?", array('long', 'few?', 'params', 'you know'));
		$expected = "this is a long string with a few? params you know";
		$this->assertEquals($expected, $result);

		$result = CakeText::insert('update saved_urls set url = :url where id = :id', array('url' => 'http://www.testurl.com/param1:url/param2:id', 'id' => 1));
		$expected = "update saved_urls set url = http://www.testurl.com/param1:url/param2:id where id = 1";
		$this->assertEquals($expected, $result);

		$result = CakeText::insert('update saved_urls set url = :url where id = :id', array('id' => 1, 'url' => 'http://www.testurl.com/param1:url/param2:id'));
		$expected = "update saved_urls set url = http://www.testurl.com/param1:url/param2:id where id = 1";
		$this->assertEquals($expected, $result);

		$result = CakeText::insert(':me cake. :subject :verb fantastic.', array('me' => 'I :verb', 'subject' => 'cake', 'verb' => 'is'));
		$expected = "I :verb cake. cake is fantastic.";
		$this->assertEquals($expected, $result);

		$result = CakeText::insert(':I.am: :not.yet: passing.', array('I.am' => 'We are'), array('before' => ':', 'after' => ':', 'clean' => array('replacement' => ' of course', 'method' => 'text')));
		$expected = "We are of course passing.";
		$this->assertEquals($expected, $result);

		$result = CakeText::insert(
			':I.am: :not.yet: passing.',
			array('I.am' => 'We are'),
			array('before' => ':', 'after' => ':', 'clean' => true)
		);
		$expected = "We are passing.";
		$this->assertEquals($expected, $result);

		$result = CakeText::insert('?-pended result', array('Pre'));
		$expected = "Pre-pended result";
		$this->assertEquals($expected, $result);

		$string = 'switching :timeout / :timeout_count';
		$expected = 'switching 5 / 10';
		$result = CakeText::insert($string, array('timeout' => 5, 'timeout_count' => 10));
		$this->assertEquals($expected, $result);

		$string = 'switching :timeout / :timeout_count';
		$expected = 'switching 5 / 10';
		$result = CakeText::insert($string, array('timeout_count' => 10, 'timeout' => 5));
		$this->assertEquals($expected, $result);

		$string = 'switching :timeout_count by :timeout';
		$expected = 'switching 10 by 5';
		$result = CakeText::insert($string, array('timeout' => 5, 'timeout_count' => 10));
		$this->assertEquals($expected, $result);

		$string = 'switching :timeout_count by :timeout';
		$expected = 'switching 10 by 5';
		$result = CakeText::insert($string, array('timeout_count' => 10, 'timeout' => 5));
		$this->assertEquals($expected, $result);
	}

/**
 * test Clean Insert
 *
 * @return void
 * @covers ::cleanInsert
 */
	public function testCleanInsert() {
		$result = CakeText::cleanInsert(':incomplete', array(
			'clean' => true, 'before' => ':', 'after' => ''
		));
		$this->assertEquals('', $result);

		$result = CakeText::cleanInsert(':incomplete', array(
			'clean' => array('method' => 'text', 'replacement' => 'complete'),
			'before' => ':', 'after' => '')
		);
		$this->assertEquals('complete', $result);

		$result = CakeText::cleanInsert(':in.complete', array(
			'clean' => true, 'before' => ':', 'after' => ''
		));
		$this->assertEquals('', $result);

		$result = CakeText::cleanInsert(':in.complete and', array(
			'clean' => true, 'before' => ':', 'after' => '')
		);
		$this->assertEquals('', $result);

		$result = CakeText::cleanInsert(':in.complete or stuff', array(
			'clean' => true, 'before' => ':', 'after' => ''
		));
		$this->assertEquals('stuff', $result);

		$result = CakeText::cleanInsert(
			'

Text here

', array('clean' => 'html', 'before' => ':', 'after' => '') ); $this->assertEquals('

Text here

', $result); } /** * Tests that non-insertable variables (i.e. arrays) are skipped when used as values in * CakeText::insert(). * * @return void * @covers ::insert */ public function testAutoIgnoreBadInsertData() { $data = array('foo' => 'alpha', 'bar' => 'beta', 'fale' => array()); $result = CakeText::insert('(:foo > :bar || :fale!)', $data, array('clean' => 'text')); $this->assertEquals('(alpha > beta || !)', $result); } /** * testTokenize method * * @return void * @covers ::tokenize */ public function testTokenize() { $result = CakeText::tokenize('A,(short,boring test)'); $expected = array('A', '(short,boring test)'); $this->assertEquals($expected, $result); $result = CakeText::tokenize('A,(short,more interesting( test)'); $expected = array('A', '(short,more interesting( test)'); $this->assertEquals($expected, $result); $result = CakeText::tokenize('A,(short,very interesting( test))'); $expected = array('A', '(short,very interesting( test))'); $this->assertEquals($expected, $result); $result = CakeText::tokenize('"single tag"', ' ', '"', '"'); $expected = array('"single tag"'); $this->assertEquals($expected, $result); $result = CakeText::tokenize('tagA "single tag" tagB', ' ', '"', '"'); $expected = array('tagA', '"single tag"', 'tagB'); $this->assertEquals($expected, $result); // Ideographic width space. $result = CakeText::tokenize("tagA\xe3\x80\x80\"single\xe3\x80\x80tag\"\xe3\x80\x80tagB", "\xe3\x80\x80", '"', '"'); $expected = array('tagA', '"singleใ€€tag"', 'tagB'); $this->assertEquals($expected, $result); $result = CakeText::tokenize(''); $expected = array(); $this->assertEquals($expected, $result); } /** * testReplaceWithQuestionMarkInString method * * @return void * @covers ::insert */ public function testReplaceWithQuestionMarkInString() { $string = ':a, :b and :c?'; $expected = '2 and 3?'; $result = CakeText::insert($string, array('b' => 2, 'c' => 3), array('clean' => true)); $this->assertEquals($expected, $result); } /** * test that wordWrap() works the same as built-in wordwrap function * * @dataProvider wordWrapProvider * @return void * @covers ::wordWrap * @covers ::_wordWrap */ public function testWordWrap($text, $width, $break = "\n", $cut = false) { $result = CakeText::wordWrap($text, $width, $break, $cut); $expected = wordwrap($text, $width, $break, $cut); $this->assertTextEquals($expected, $result, 'Text not wrapped same as built-in function.'); } /** * data provider for testWordWrap method * * @return array */ public function wordWrapProvider() { return array( array( 'The quick brown fox jumped over the lazy dog.', 33 ), array( 'A very long woooooooooooord.', 8 ), array( 'A very long woooooooooooord. Right.', 8 ), ); } /** * test that wordWrap() properly handle unicode strings. * * @return void * @covers ::wordWrap * @covers ::_wordWrap */ public function testWordWrapUnicodeAware() { $text = 'ะะพ ะฒะธะผ ะพะผะฝะธัŽะผ ั„ะฐะบั‘ะปัŒะธัะธ ัะปั‹ะบั‚ั€ะฐะผ, ะผัŽะฝั‹ั€ั ะปัะณั‹ั€ั‹ ะฒะตะบะถ ั‹ั‚. ะ’ั‹ะปัŒั‘ั‚ ะบะฒัŽะฐะฝะดะพ ะฝัŽะผะบะฒัƒะฐะผ ั‚ั‹ ะบัŽะผ. ะ—ั‹ะด ััŽ ั€ั‹ะฑัŽะผ.'; $result = CakeText::wordWrap($text, 33, "\n", true); $expected = <<assertTextEquals($expected, $result, 'Text not wrapped.'); $text = 'ะะพ ะฒะธะผ ะพะผะฝะธัŽะผ ั„ะฐะบั‘ะปัŒะธัะธ ัะปั‹ะบั‚ั€ะฐะผ, ะผัŽะฝั‹ั€ั ะปัะณั‹ั€ั‹ ะฒะตะบะถ ั‹ั‚. ะ’ั‹ะปัŒั‘ั‚ ะบะฒัŽะฐะฝะดะพ ะฝัŽะผะบะฒัƒะฐะผ ั‚ั‹ ะบัŽะผ. ะ—ั‹ะด ััŽ ั€ั‹ะฑัŽะผ.'; $result = CakeText::wordWrap($text, 33, "\n"); $expected = <<assertTextEquals($expected, $result, 'Text not wrapped.'); } /** * test that wordWrap() properly handle newline characters. * * @return void * @covers ::wordWrap * @covers ::_wordWrap */ public function testWordWrapNewlineAware() { $text = 'This is a line that is almost the 55 chars long. This is a new sentence which is manually newlined, but is so long it needs two lines.'; $result = CakeText::wordWrap($text, 55); $expected = <<assertTextEquals($expected, $result, 'Text not wrapped.'); } /** * test wrap method. * * @return void * @covers ::wrap * @covers ::wordWrap * @covers ::_wordWrap */ public function testWrap() { $text = 'This is the song that never ends. This is the song that never ends. This is the song that never ends.'; $result = CakeText::wrap($text, 33); $expected = <<assertTextEquals($expected, $result, 'Text not wrapped.'); $result = CakeText::wrap($text, array('width' => 20, 'wordWrap' => false)); $expected = 'This is the song th' . "\n" . 'at never ends. This' . "\n" . ' is the song that n' . "\n" . 'ever ends. This is ' . "\n" . 'the song that never' . "\n" . ' ends.'; $this->assertTextEquals($expected, $result, 'Text not wrapped.'); $text = 'ะะพ ะฒะธะผ ะพะผะฝะธัŽะผ ั„ะฐะบั‘ะปัŒะธัะธ ัะปั‹ะบั‚ั€ะฐะผ, ะผัŽะฝั‹ั€ั ะปัะณั‹ั€ั‹ ะฒะตะบะถ ั‹ั‚. ะ’ั‹ะปัŒั‘ั‚ ะบะฒัŽะฐะฝะดะพ ะฝัŽะผะบะฒัƒะฐะผ ั‚ั‹ ะบัŽะผ. ะ—ั‹ะด ััŽ ั€ั‹ะฑัŽะผ.'; $result = CakeText::wrap($text, 33); $expected = <<assertTextEquals($expected, $result, 'Text not wrapped.'); } /** * test wrap() indenting * * @return void * @covers ::wrap * @covers ::wordWrap * @covers ::_wordWrap */ public function testWrapIndent() { $text = 'This is the song that never ends. This is the song that never ends. This is the song that never ends.'; $result = CakeText::wrap($text, array('width' => 33, 'indent' => "\t", 'indentAt' => 1)); $expected = <<assertTextEquals($expected, $result); } /** * testTruncate method * * @return void * @covers ::truncate */ public function testTruncate() { $text1 = 'The quick brown fox jumps over the lazy dog'; $text2 = 'Heizölrückstoßabdämpfung'; $text3 = '© 2005-2007, Cake Software Foundation, Inc.
written by Alexander Wegener'; $text4 = ' This image tag is not XHTML conform!

But the following image tag should be conform Me, myself and I
Great, or?'; $text5 = '01234567890'; $text6 = '

Extra dates have been announced for this year\'s tour.

Tickets for the new shows in

'; $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 = 'ะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $text10 = 'http://example.com/something/foo:bar'; $elipsis = "\xe2\x80\xa6"; $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), '© 2005-20...'); $this->assertSame($this->Text->truncate($text4, 15), ' This image ta' . $elipsis); $this->assertSame($this->Text->truncate($text4, 45, array('html' => true)), ' This image tag is not XHTML conform!

But the' . $elipsis . ''); $this->assertSame($this->Text->truncate($text4, 90, array('html' => true)), ' This image tag is not XHTML conform!

But the following image tag should be conform Me, myself and I
Great,' . $elipsis); $this->assertSame($this->Text->truncate($text5, 6, array('ellipsis' => '', 'html' => true)), '012345'); $this->assertSame($this->Text->truncate($text5, 20, array('ellipsis' => '', 'html' => true)), $text5); $this->assertSame($this->Text->truncate($text6, 57, array('exact' => false, 'html' => true)), "

Extra dates have been announced for this year's" . $elipsis . "

"); $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), 'ะะžะŸะ ะกะขะฃ...'); $this->assertSame($this->Text->truncate($text10, 30), 'http://example.com/somethin...'); $text = '

Iamatestwithnospacesandhtml

'; $result = $this->Text->truncate($text, 10, array( 'ellipsis' => '...', 'exact' => false, 'html' => true )); $expected = '

...

'; $this->assertEquals($expected, $result); $text = '

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.

Por quรฉ Steve era distinto.

http://www.elpais.com/articulo/primer/plano/ Steve/era/distinto/elpepueconeg/20111009elpneglse_4/Tes

Ya se ha publicado la biografรญa de Steve Jobs escrita por Walter Isaacson "Steve Jobs by Walter Isaacson", aquรญ os dejamos la direcciรณn de amazon donde podeรญs adquirirla.

http://www.amazon.com/Steve- Jobs-Walter-Isaacson/dp/1451648537

'; $result = $this->Text->truncate($text, 500, array( 'ellipsis' => '... ', 'exact' => false, 'html' => true )); $expected = '

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.

Por quรฉ Steve era distinto.

http://www.elpais.com/articulo/primer/plano/ Steve/era/distinto/elpepueconeg/20111009elpneglse_4/Tes

Ya se ha publicado la biografรญa de Steve Jobs escrita por Walter Isaacson "Steve Jobs by Walter Isaacson", aquรญ os dejamos la direcciรณn de amazon donde podeรญs adquirirla.

...

'; $this->assertEquals($expected, $result); // test deprecated `ending` (`ellipsis` taking precedence if both are defined) $result = $this->Text->truncate($text1, 31, array( 'ending' => '.', 'exact' => false, )); $expected = 'The quick brown fox jumps.'; $this->assertEquals($expected, $result); $result = $this->Text->truncate($text1, 31, array( 'ellipsis' => '..', 'ending' => '.', 'exact' => false, )); $expected = 'The quick brown fox jumps..'; $this->assertEquals($expected, $result); } /** * testTruncate method with non utf8 sites * * @return void * @covers ::truncate */ public function testTruncateLegacy() { Configure::write('App.encoding', 'ISO-8859-1'); $text = '© 2005-2007, Cake Software Foundation, Inc.
written by Alexander Wegener'; $result = $this->Text->truncate($text, 31, array( 'html' => true, 'exact' => false, )); $expected = '© 2005-2007, Cake Software...'; $this->assertEquals($expected, $result); $result = $this->Text->truncate($text, 31, array( 'html' => true, 'exact' => true, )); $expected = '© 2005-2007, Cake Software F...'; $this->assertEquals($expected, $result); } /** * testTail method * * @return void * @covers ::tail */ public function testTail() { $text1 = 'The quick brown fox jumps over the lazy dog'; $text2 = 'Heizölrückstoßabdämpfung'; $text3 = 'El moรฑo estรก en el lugar correcto. Eso fue lo que dijo la niรฑa, ยฟhabrรก dicho la verdad?'; $text4 = 'Vive la R' . chr(195) . chr(169) . 'publique de France'; $text5 = 'ะะžะŸะ ะกะขะฃะคะฅะฆะงะจะฉะชะซะฌะญะฎะฏะฐะฑะฒะณะดะตะถะทะธะนะบะปะผะฝะพะฟั€ัั‚ัƒั„ั…ั†ั‡ัˆั‰ัŠั‹ัŒ'; $result = $this->Text->tail($text1, 13); $this->assertEquals('...e lazy dog', $result); $result = $this->Text->tail($text1, 13, array('exact' => false)); $this->assertEquals('...lazy dog', $result); $result = $this->Text->tail($text1, 100); $this->assertEquals('The quick brown fox jumps over the lazy dog', $result); $result = $this->Text->tail($text2, 10); $this->assertEquals('...;mpfung', $result); $result = $this->Text->tail($text2, 10, array('exact' => false)); $this->assertEquals('...', $result); $result = $this->Text->tail($text3, 255); $this->assertEquals($text3, $result); $result = $this->Text->tail($text3, 21); $this->assertEquals('...รก dicho la verdad?', $result); $result = $this->Text->tail($text4, 25); $this->assertEquals('...a R' . chr(195) . chr(169) . 'publique de France', $result); $result = $this->Text->tail($text5, 10); $this->assertEquals('...ั†ั‡ัˆั‰ัŠั‹ัŒ', $result); $result = $this->Text->tail($text5, 6, array('ellipsis' => '')); $this->assertEquals('ั‡ัˆั‰ัŠั‹ัŒ', $result); } /** * testHighlight method * * @return void * @covers ::highlight */ public function testHighlight() { $text = 'This is a test text'; $phrases = array('This', 'text'); $result = $this->Text->highlight($text, $phrases, array('format' => '\1')); $expected = 'This is a test text'; $this->assertEquals($expected, $result); $phrases = array('is', 'text'); $result = $this->Text->highlight($text, $phrases, array('format' => '\1', 'regex' => "|\b%s\b|iu")); $expected = 'This is a test text'; $this->assertEquals($expected, $result); $text = 'This is a test text'; $phrases = null; $result = $this->Text->highlight($text, $phrases, array('format' => '\1')); $this->assertEquals($text, $result); $text = 'This is a (test) text'; $phrases = '(test'; $result = $this->Text->highlight($text, $phrases, array('format' => '\1')); $this->assertEquals('This is a (test) text', $result); $text = 'Ich saรŸ in einem Cafรฉ am รœbergang'; $expected = 'Ich saรŸ in einem Cafรฉ am รœbergang'; $phrases = array('saรŸ', 'cafรฉ', 'รผbergang'); $result = $this->Text->highlight($text, $phrases, array('format' => '\1')); $this->assertEquals($expected, $result); } /** * testHighlightHtml method * * @return void * @covers ::highlight */ public function testHighlightHtml() { $text1 = '

strongbow isn’t real cider

'; $text2 = '

strongbow isn’t real cider

'; $text3 = 'What a strong mouse!'; $text4 = 'What a strong mouse: What a strong mouse!'; $options = array('format' => '\1', 'html' => true); $expected = '

strongbow isn’t real cider

'; $this->assertEquals($expected, $this->Text->highlight($text1, 'strong', $options)); $expected = '

strongbow isn’t real cider

'; $this->assertEquals($expected, $this->Text->highlight($text2, 'strong', $options)); $this->assertEquals($this->Text->highlight($text3, 'strong', $options), $text3); $this->assertEquals($this->Text->highlight($text3, array('strong', 'what'), $options), $text3); $expected = 'What a strong mouse: What a strong mouse!'; $this->assertEquals($expected, $this->Text->highlight($text4, array('strong', 'what'), $options)); } /** * testHighlightMulti method * * @return void * @covers ::highlight */ public function testHighlightMulti() { $text = 'This is a test text'; $phrases = array('This', 'text'); $result = $this->Text->highlight($text, $phrases, array('format' => array('\1', '\1'))); $expected = 'This is a test text'; $this->assertEquals($expected, $result); } /** * testStripLinks method * * @return void * @covers ::stripLinks */ 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 test text'; $expected = 'This is a test text'; $result = $this->Text->stripLinks($text); $this->assertEquals($expected, $result); $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 test and some other text'; $expected = 'This is a test and some other text'; $result = $this->Text->stripLinks($text); $this->assertEquals($expected, $result); } /** * testHighlightCaseInsensitivity method * * @return void * @covers ::highlight */ public function testHighlightCaseInsensitivity() { $text = 'This is a Test text'; $expected = 'This is a Test text'; $result = $this->Text->highlight($text, 'test', array('format' => '\1')); $this->assertEquals($expected, $result); $result = $this->Text->highlight($text, array('test'), array('format' => '\1')); $this->assertEquals($expected, $result); } /** * testExcerpt method * * @return void * @covers ::excerpt */ 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 * @covers ::excerpt */ 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 * @covers ::toList */ public function testListGeneration() { $result = $this->Text->toList(array()); $this->assertEquals('', $result); $result = $this->Text->toList(array('One')); $this->assertEquals('One', $result); $result = $this->Text->toList(array('Larry', 'Curly', 'Moe')); $this->assertEquals('Larry, Curly and Moe', $result); $result = $this->Text->toList(array('Dusty', 'Lucky', 'Ned'), 'y'); $this->assertEquals('Dusty, Lucky y Ned', $result); $result = $this->Text->toList(array(1 => 'Dusty', 2 => 'Lucky', 3 => 'Ned'), 'y'); $this->assertEquals('Dusty, Lucky y Ned', $result); $result = $this->Text->toList(array(1 => 'Dusty', 2 => 'Lucky', 3 => 'Ned'), 'and', ' + '); $this->assertEquals('Dusty + Lucky and Ned', $result); $result = $this->Text->toList(array('name1' => 'Dusty', 'name2' => 'Lucky')); $this->assertEquals('Dusty and Lucky', $result); $result = $this->Text->toList(array('test_0' => 'banana', 'test_1' => 'apple', 'test_2' => 'lemon')); $this->assertEquals('banana, apple and lemon', $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Utility/CakeTimeTest.php000066400000000000000000001150661265552240500230540ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.View.Helper * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('CakeTime', 'Utility'); /** * CakeTimeTest class * * @package Cake.Test.Case.View.Helper */ class CakeTimeTest extends CakeTestCase { /** * Default system timezone identifier * * @var string */ protected $_systemTimezoneIdentifier = null; /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->Time = new CakeTime(); $this->_systemTimezoneIdentifier = date_default_timezone_get(); Configure::write('Config.language', 'eng'); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Time); $this->_restoreSystemTimezone(); } /** * Restored the original system timezone * * @param string $timezoneIdentifier Timezone string * @return void */ protected function _restoreSystemTimezone() { date_default_timezone_set($this->_systemTimezoneIdentifier); } /** * testToQuarter method * * @return void */ public function testToQuarter() { $result = $this->Time->toQuarter('2007-12-25'); $this->assertSame(4, $result); $result = $this->Time->toQuarter('2007-9-25'); $this->assertSame(3, $result); $result = $this->Time->toQuarter('2007-3-25'); $this->assertSame(1, $result); $result = $this->Time->toQuarter('2007-3-25', true); $this->assertEquals(array('2007-01-01', '2007-03-31'), $result); $result = $this->Time->toQuarter('2007-5-25', true); $this->assertEquals(array('2007-04-01', '2007-06-30'), $result); $result = $this->Time->toQuarter('2007-8-25', true); $this->assertEquals(array('2007-07-01', '2007-09-30'), $result); $result = $this->Time->toQuarter('2007-12-25', true); $this->assertEquals(array('2007-10-01', '2007-12-31'), $result); } /** * provider for timeAgoInWords() tests * * @return array */ public static function timeAgoProvider() { return array( array('-12 seconds', '12 seconds ago'), array('-12 minutes', '12 minutes ago'), array('-2 hours', '2 hours ago'), array('-1 day', '1 day ago'), array('-2 days', '2 days ago'), array('-2 days -3 hours', '2 days, 3 hours ago'), array('-1 week', '1 week ago'), array('-2 weeks -2 days', '2 weeks, 2 days ago'), array('+1 week', 'in 1 week'), array('+1 week 1 day', 'in 1 week, 1 day'), array('+2 weeks 2 day', 'in 2 weeks, 2 days'), array('2007-9-24', 'on 24/9/07'), array('now', 'just now'), ); } /** * testTimeAgoInWords method * * @dataProvider timeAgoProvider * @return void */ public function testTimeAgoInWords($input, $expected) { $result = $this->Time->timeAgoInWords($input); $this->assertEquals($expected, $result); } /** * provider for timeAgo with an end date. * * @return void */ public function timeAgoEndProvider() { return array( array( '+4 months +2 weeks +3 days', 'in 4 months, 2 weeks, 3 days', '8 years' ), array( '+4 months +2 weeks +1 day', 'in 4 months, 2 weeks, 1 day', '8 years' ), array( '+3 months +2 weeks', 'in 3 months, 2 weeks', '8 years' ), array( '+3 months +2 weeks +1 day', 'in 3 months, 2 weeks, 1 day', '8 years' ), array( '+1 months +1 week +1 day', 'in 1 month, 1 week, 1 day', '8 years' ), array( '+2 months +2 days', 'in 2 months, 2 days', 'on ' . date('j/n/y', strtotime('+2 months +2 days')) ), array( '+2 months +12 days', 'in 2 months, 1 week, 5 days', '3 months' ), ); } /** * test the end option for timeAgoInWords * * @dataProvider timeAgoEndProvider * @return void */ public function testTimeAgoInWordsEnd($input, $expected, $end) { $result = $this->Time->timeAgoInWords( $input, array('end' => $end) ); $this->assertEquals($expected, $result); } /** * test the custom string options for timeAgoInWords * * @return void */ public function testTimeAgoInWordsCustomStrings() { $result = $this->Time->timeAgoInWords( strtotime('-8 years -4 months -2 weeks -3 days'), array('relativeString' => 'at least %s ago', 'accuracy' => array('year' => 'year'), 'end' => '+10 years') ); $expected = 'at least 8 years ago'; $this->assertEquals($expected, $result); $result = $this->Time->timeAgoInWords( strtotime('+8 years +4 months +2 weeks +3 days'), array('relativeStringFuture' => 'not in the next %s', 'accuracy' => array('year' => 'year'), 'end' => '+10 years') ); $expected = 'not in the next 8 years'; $this->assertEquals($expected, $result); $result = $this->Time->timeAgoInWords( strtotime('+4 months +2 weeks +3 days'), array('absoluteString' => 'exactly on %s', 'accuracy' => array('year' => 'year'), 'end' => '+2 months') ); $expected = 'exactly on ' . date('j/n/y', strtotime('+4 months +2 weeks +3 days')); $this->assertEquals($expected, $result); } /** * Test the accuracy option for timeAgoInWords() * * @return void */ public function testTimeAgoInWordsAccuracy() { $result = $this->Time->timeAgoInWords( strtotime('+8 years +4 months +2 weeks +3 days'), array('accuracy' => array('year' => 'year'), 'end' => '+10 years') ); $expected = 'in 8 years'; $this->assertEquals($expected, $result); $result = $this->Time->timeAgoInWords( strtotime('+8 years +4 months +2 weeks +3 days'), array('accuracy' => array('year' => 'month'), 'end' => '+10 years') ); $expected = 'in 8 years, 4 months'; $this->assertEquals($expected, $result); $result = $this->Time->timeAgoInWords( strtotime('+8 years +4 months +2 weeks +3 days'), array('accuracy' => array('year' => 'week'), 'end' => '+10 years') ); $expected = 'in 8 years, 4 months, 2 weeks'; $this->assertEquals($expected, $result); $result = $this->Time->timeAgoInWords( strtotime('+8 years +4 months +2 weeks +3 days'), array('accuracy' => array('year' => 'day'), 'end' => '+10 years') ); $expected = 'in 8 years, 4 months, 2 weeks, 3 days'; $this->assertEquals($expected, $result); $result = $this->Time->timeAgoInWords( strtotime('+1 years +5 weeks'), array('accuracy' => array('year' => 'year'), 'end' => '+10 years') ); $expected = 'in 1 year'; $this->assertEquals($expected, $result); $result = $this->Time->timeAgoInWords( strtotime('+58 minutes'), array('accuracy' => 'hour') ); $expected = 'in about an hour'; $this->assertEquals($expected, $result); $result = $this->Time->timeAgoInWords( strtotime('+23 hours'), array('accuracy' => 'day') ); $expected = 'in about a day'; $this->assertEquals($expected, $result); } /** * Test the format option of timeAgoInWords() with date() and strftime compatible strings * * @return void */ public function testTimeAgoInWordsWithFormat() { $result = $this->Time->timeAgoInWords('2007-9-25', 'Y-m-d'); $this->assertEquals('on 2007-09-25', $result); $result = $this->Time->timeAgoInWords('2007-9-25', '%x'); $this->assertEquals('on ' . strftime('%x', strtotime('2007-9-25')), $result); $result = $this->Time->timeAgoInWords( strtotime('+2 weeks +2 days'), 'Y-m-d' ); $this->assertRegExp('/^in 2 weeks, [1|2] day(s)?$/', $result); $result = $this->Time->timeAgoInWords( strtotime('+2 weeks +2 days'), '%x' ); $this->assertRegExp('/^in 2 weeks, [1|2] day(s)?$/', $result); $result = $this->Time->timeAgoInWords( strtotime('+2 months +2 days'), array('end' => '1 month', 'format' => 'Y-m-d') ); $this->assertEquals('on ' . date('Y-m-d', strtotime('+2 months +2 days')), $result); $result = $this->Time->timeAgoInWords( strtotime('+2 months +2 days'), array('end' => '1 month', 'format' => '%x') ); $this->assertEquals('on ' . strftime('%x', strtotime('+2 months +2 days')), $result); } /** * test timeAgoInWords() with negative values. * * @return void */ public function testTimeAgoInWordsNegativeValues() { $result = $this->Time->timeAgoInWords( strtotime('-2 months -2 days'), array('end' => '3 month') ); $this->assertEquals('2 months, 2 days ago', $result); $result = $this->Time->timeAgoInWords( strtotime('-2 months -2 days'), array('end' => '3 month') ); $this->assertEquals('2 months, 2 days ago', $result); $result = $this->Time->timeAgoInWords( strtotime('-2 months -2 days'), array('end' => '1 month', 'format' => 'Y-m-d') ); $this->assertEquals('on ' . date('Y-m-d', strtotime('-2 months -2 days')), $result); $result = $this->Time->timeAgoInWords( strtotime('-2 years -5 months -2 days'), array('end' => '3 years') ); $this->assertEquals('2 years, 5 months, 2 days ago', $result); $result = $this->Time->timeAgoInWords( strtotime('-2 weeks -2 days'), 'Y-m-d' ); $this->assertEquals('2 weeks, 2 days ago', $result); $time = strtotime('-3 years -12 months'); $result = $this->Time->timeAgoInWords($time); $expected = 'on ' . date('j/n/y', $time); $this->assertEquals($expected, $result); $result = $this->Time->timeAgoInWords( strtotime('-1 month -1 week -6 days'), array('end' => '1 year', 'accuracy' => array('month' => 'month')) ); $this->assertEquals('1 month ago', $result); $timestamp = strtotime('-1 years -2 weeks -3 days'); $result = $this->Time->timeAgoInWords( $timestamp, array('accuracy' => array('year' => 'year')) ); $expected = 'on ' . date('j/n/y', $timestamp); $this->assertEquals($expected, $result); $result = $this->Time->timeAgoInWords( strtotime('-13 months -5 days'), array('end' => '2 years') ); $this->assertEquals('1 year, 1 month, 5 days ago', $result); $result = $this->Time->timeAgoInWords( strtotime('-58 minutes'), array('accuracy' => 'hour') ); $this->assertEquals('about an hour ago', $result); $result = $this->Time->timeAgoInWords( strtotime('-23 hours'), array('accuracy' => 'day') ); $this->assertEquals('about a day ago', $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)); $this->assertEquals('%Y-%d-%m', $this->Time->niceFormat); CakeTime::$niceFormat = '%Y-%d-%m %H:%M'; $this->assertEquals(date('Y-d-m H:i', $time), $this->Time->nice($time)); $this->assertEquals('%Y-%d-%m %H:%M', $this->Time->niceFormat); date_default_timezone_set('UTC'); $result = $this->Time->nice(null, 'America/New_York'); $expected = $this->Time->nice(time(), 'America/New_York'); $this->assertEquals(substr($expected, 0, -1), substr($result, 0, -1)); $this->_restoreSystemTimezone(); } /** * testNiceShort method * * @return void */ public function testNiceShort() { $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)); $time = time() + DAY; $this->assertEquals('Tomorrow, ' . date('H:i', $time), $this->Time->niceShort($time)); $time = strtotime('+6 days'); $this->assertEquals('On ' . date('l F d, H:i', $time), $this->Time->niceShort($time)); $time = strtotime('-6 days'); $this->assertEquals(date('l F d, H:i', $time), $this->Time->niceShort($time)); date_default_timezone_set('Europe/London'); $result = $this->Time->niceShort('2005-01-15 10:00:00', new DateTimeZone('Europe/Brussels')); $this->assertEquals('Jan 15th 2005, 11:00', $result); date_default_timezone_set('UTC'); $result = $this->Time->niceShort(null, 'America/New_York'); $expected = $this->Time->niceShort(time(), 'America/New_York'); $this->assertEquals($expected, $result); $this->_restoreSystemTimezone(); } /** * 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)); } /** * testToServer method * * @return void */ public function testToServer() { date_default_timezone_set('Europe/Paris'); $time = time(); $this->assertEquals(date('Y-m-d H:i:s', $time), $this->Time->toServer($time)); date_default_timezone_set('America/New_York'); $time = time(); date_default_timezone_set('Europe/Paris'); $result = $this->Time->toServer($time, 'America/New_York'); $this->assertEquals(date('Y-m-d H:i:s', $time), $result); date_default_timezone_set('Europe/Paris'); $time = '2005-10-25 10:00:00'; $result = $this->Time->toServer($time); $date = new DateTime($time, new DateTimeZone('UTC')); $date->setTimezone(new DateTimeZone(date_default_timezone_get())); $expected = $date->format('Y-m-d H:i:s'); $this->assertEquals($expected, $result); $time = '2002-01-01 05:15:30'; $result = $this->Time->toServer($time, 'America/New_York'); $date = new DateTime($time, new DateTimeZone('America/New_York')); $date->setTimezone(new DateTimeZone(date_default_timezone_get())); $expected = $date->format('Y-m-d H:i:s'); $this->assertEquals($expected, $result); $time = '2010-01-28T15:00:00+10:00'; $result = $this->Time->toServer($time, 'America/New_York'); $date = new DateTime($time); $date->setTimezone(new DateTimeZone(date_default_timezone_get())); $expected = $date->format('Y-m-d H:i:s'); $this->assertEquals($expected, $result); $date = new DateTime(null, new DateTimeZone('America/New_York')); $result = $this->Time->toServer($date, 'Pacific/Tahiti'); $date->setTimezone(new DateTimeZone(date_default_timezone_get())); $expected = $date->format('Y-m-d H:i:s'); $this->assertEquals($expected, $result); $this->_restoreSystemTimezone(); $time = time(); $result = $this->Time->toServer($time, null, 'l jS \of F Y h:i:s A'); $expected = date('l jS \of F Y h:i:s A', $time); $this->assertEquals($expected, $result); $this->assertFalse($this->Time->toServer(time(), new Object())); date_default_timezone_set('UTC'); $serverTime = new DateTime('2012-12-11 14:15:20'); $timezones = array('Europe/London', 'Europe/Brussels', 'UTC', 'America/Denver', 'America/Caracas', 'Asia/Kathmandu'); foreach ($timezones as $timezone) { $result = $this->Time->toServer($serverTime->format('Y-m-d H:i:s'), $timezone, 'U'); $tz = new DateTimeZone($timezone); $this->assertEquals($serverTime->format('U'), $result + $tz->getOffset($serverTime)); } date_default_timezone_set('UTC'); $date = new DateTime('now', new DateTimeZone('America/New_York')); $result = $this->Time->toServer($date, null, 'Y-m-d H:i:s'); $date->setTimezone($this->Time->timezone()); $expected = $date->format('Y-m-d H:i:s'); $this->assertEquals($expected, $result); $this->_restoreSystemTimezone(); } /** * 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() { $date = '2012-08-12 12:12:45'; $time = strtotime($date); $this->assertEquals(date('r', $time), $this->Time->toRss($time)); $timezones = array('Europe/London', 'Europe/Brussels', 'UTC', 'America/Denver', 'America/Caracas', 'Asia/Kathmandu'); foreach ($timezones as $timezone) { $yourTimezone = new DateTimeZone($timezone); $yourTime = new DateTime($date, $yourTimezone); $userOffset = $yourTimezone->getOffset($yourTime) / HOUR; $time = $yourTime->format('U'); $this->assertEquals($yourTime->format('r'), $this->Time->toRss($time, $userOffset), "Failed on $timezone"); $this->assertEquals($yourTime->format('r'), $this->Time->toRss($time, $timezone), "Failed on $timezone"); } } /** * testFormat method * * @return void */ public function testFormat() { $format = 'D-M-Y'; $tz = date_default_timezone_get(); $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)); $this->assertEquals(date($format, $val), $this->Time->format($format, $val, false, $tz)); } $result = $this->Time->format('Y-m-d', null, 'never'); $this->assertEquals('never', $result); $result = $this->Time->format('Y-m-d', ''); $this->assertSame('', $result); $result = $this->Time->format('Y-m-d', false); $this->assertSame('', $result); $result = $this->Time->format('2012-01-13', '%d-%m-%Y', 'invalid'); $this->assertEquals('13-01-2012', $result); $result = $this->Time->format('nonsense', '%d-%m-%Y', 'invalid', 'UTC'); $this->assertEquals('invalid', $result); $result = $this->Time->format('0000-00-00', '%d-%m-%Y', 'invalid'); $this->assertEquals('invalid', $result); } /** * 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); } /** * testIsFuture method * * @return void */ public function testIsFuture() { $this->assertTrue($this->Time->isFuture('+1 month')); $this->assertTrue($this->Time->isFuture('+1 days')); $this->assertTrue($this->Time->isFuture('+1 minute')); $this->assertTrue($this->Time->isFuture('+1 second')); $this->assertFalse($this->Time->isFuture('-1 second')); $this->assertFalse($this->Time->isFuture('-1 day')); $this->assertFalse($this->Time->isFuture('-1 week')); $this->assertFalse($this->Time->isFuture('-1 month')); } /** * testIsPast method * * @return void */ public function testIsPast() { $this->assertFalse($this->Time->isPast('+1 month')); $this->assertFalse($this->Time->isPast('+1 days')); $this->assertFalse($this->Time->isPast('+1 minute')); $this->assertFalse($this->Time->isPast('+1 second')); $this->assertTrue($this->Time->isPast('-1 second')); $this->assertTrue($this->Time->isPast('-1 day')); $this->assertTrue($this->Time->isPast('-1 week')); $this->assertTrue($this->Time->isPast('-1 month')); } /** * 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')); } /** * testWasWithinLast method * * @return void */ public function testIsWithinNext() { $this->assertFalse($this->Time->isWithinNext('1 day', '-1 day')); $this->assertFalse($this->Time->isWithinNext('1 week', '-1 week')); $this->assertFalse($this->Time->isWithinNext('1 year', '-1 year')); $this->assertFalse($this->Time->isWithinNext('1 second', '-1 second')); $this->assertFalse($this->Time->isWithinNext('1 minute', '-1 minute')); $this->assertFalse($this->Time->isWithinNext('1 year', '-1 year')); $this->assertFalse($this->Time->isWithinNext('1 month', '-1 month')); $this->assertFalse($this->Time->isWithinNext('1 day', '-1 day')); $this->assertFalse($this->Time->isWithinNext('1 week', '-1 day')); $this->assertFalse($this->Time->isWithinNext('2 week', '-1 week')); $this->assertFalse($this->Time->isWithinNext('1 second', '-1 year')); $this->assertFalse($this->Time->isWithinNext('10 minutes', '-1 second')); $this->assertFalse($this->Time->isWithinNext('23 minutes', '-1 minute')); $this->assertFalse($this->Time->isWithinNext('0 year', '-1 year')); $this->assertFalse($this->Time->isWithinNext('13 month', '-1 month')); $this->assertFalse($this->Time->isWithinNext('2 days', '-1 day')); $this->assertFalse($this->Time->isWithinNext('1 week', '-2 weeks')); $this->assertFalse($this->Time->isWithinNext('1 second', '-2 seconds')); $this->assertFalse($this->Time->isWithinNext('1 day', '-2 days')); $this->assertFalse($this->Time->isWithinNext('1 hour', '-2 hours')); $this->assertFalse($this->Time->isWithinNext('1 month', '-2 months')); $this->assertFalse($this->Time->isWithinNext('1 year', '-2 years')); $this->assertFalse($this->Time->isWithinNext('1 day', '-2 weeks')); $this->assertFalse($this->Time->isWithinNext('1 day', '-2 days')); $this->assertFalse($this->Time->isWithinNext('0 days', '-2 days')); $this->assertFalse($this->Time->isWithinNext('1 hour', '-20 seconds')); $this->assertFalse($this->Time->isWithinNext('1 year', '-60 minutes -30 seconds')); $this->assertFalse($this->Time->isWithinNext('3 years', '-2 months')); $this->assertFalse($this->Time->isWithinNext('5 months', '-4 months')); $this->assertFalse($this->Time->isWithinNext('5 ', '-3 days')); $this->assertFalse($this->Time->isWithinNext('1 ', '-1 hour')); $this->assertFalse($this->Time->isWithinNext('1 ', '-1 minute')); $this->assertFalse($this->Time->isWithinNext('1 ', '-23 hours -59 minutes -59 seconds')); $this->assertTrue($this->Time->isWithinNext('7 days', '6 days, 23 hours, 59 minutes, 59 seconds')); $this->assertFalse($this->Time->isWithinNext('7 days', '6 days, 23 hours, 59 minutes, 61 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->assertWithinMargin($expected, $result, 1); $result = $this->Time->fromString(time(), $timezoneServer->getName()); $this->assertWithinMargin($expected, $result, 1); $result = $this->Time->fromString(time(), $timezoneServer); $this->assertWithinMargin($expected, $result, 1); Configure::write('Config.timezone', $timezoneServer->getName()); $result = $this->Time->fromString(time()); $this->assertWithinMargin($expected, $result, 1); Configure::delete('Config.timezone'); } /** * 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->assertWithinMargin($expected, $result, 1); $timezone = date('Z', time()); $result = $this->Time->fromString('+1 hour', $timezone); $expected = $this->Time->convert(strtotime('+1 hour'), $timezone); $this->assertWithinMargin($expected, $result, 1); $timezone = date_default_timezone_get(); $result = $this->Time->fromString('+1 hour', $timezone); $expected = $this->Time->convert(strtotime('+1 hour'), $timezone); $this->assertWithinMargin($expected, $result, 1); date_default_timezone_set('UTC'); $date = new DateTime('now', new DateTimeZone('Europe/London')); $this->Time->fromString($date); $this->assertEquals('Europe/London', $date->getTimeZone()->getName()); $this->_restoreSystemTimezone(); } /** * test fromString() with a DateTime object as the dateString * * @return void */ public function testFromStringWithDateTime() { date_default_timezone_set('UTC'); $date = new DateTime('+1 hour', new DateTimeZone('America/New_York')); $result = $this->Time->fromString($date, 'UTC'); $date->setTimezone(new DateTimeZone('UTC')); $expected = $date->format('U') + $date->getOffset(); $this->assertWithinMargin($expected, $result, 1); date_default_timezone_set('Australia/Melbourne'); $date = new DateTime('+1 hour', new DateTimeZone('America/New_York')); $result = $this->Time->fromString($date, 'Asia/Kuwait'); $date->setTimezone(new DateTimeZone('Asia/Kuwait')); $expected = $date->format('U') + $date->getOffset(); $this->assertWithinMargin($expected, $result, 1); $this->_restoreSystemTimezone(); } /** * Test that datetimes in the default timezone are not modified. * * @return void */ public function testFromStringWithDateTimeNoConversion() { Configure::write('Config.timezone', date_default_timezone_get()); $date = new DateTime('2013-04-09'); $result = $this->Time->fromString($date); $this->assertEquals($result, $date->format('U')); } /** * test converting time specifiers using a time definition localfe file * * @return void */ public function testConvertSpecifiers() { App::build(array( 'Locale' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Locale' . DS) ), App::RESET); 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( 'Locale' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Locale' . DS) ), App::RESET); 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 ' . utf8_encode(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 ' . utf8_encode(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 second 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')); } /** * testListTimezones * * @return void */ public function testListTimezones() { $return = CakeTime::listTimezones(); $this->assertTrue(isset($return['Asia']['Asia/Bangkok'])); $this->assertEquals('Bangkok', $return['Asia']['Asia/Bangkok']); $this->assertTrue(isset($return['America']['America/Argentina/Buenos_Aires'])); $this->assertEquals('Argentina/Buenos_Aires', $return['America']['America/Argentina/Buenos_Aires']); $this->assertTrue(isset($return['UTC']['UTC'])); $this->assertFalse(isset($return['Cuba'])); $this->assertFalse(isset($return['US'])); $return = CakeTime::listTimezones('#^Asia/#'); $this->assertTrue(isset($return['Asia']['Asia/Bangkok'])); $this->assertFalse(isset($return['Pacific'])); $return = CakeTime::listTimezones(null, null, array('abbr' => true)); $this->assertTrue(isset($return['Asia']['Asia/Jakarta'])); $this->assertEquals('Jakarta - WIB', $return['Asia']['Asia/Jakarta']); $this->assertEquals('Regina - CST', $return['America']['America/Regina']); $return = CakeTime::listTimezones(null, null, array( 'abbr' => true, 'before' => ' (', 'after' => ')', )); $this->assertEquals('Jayapura (WIT)', $return['Asia']['Asia/Jayapura']); $this->assertEquals('Regina (CST)', $return['America']['America/Regina']); $return = CakeTime::listTimezones('#^(America|Pacific)/#', null, false); $this->assertTrue(isset($return['America/Argentina/Buenos_Aires'])); $this->assertTrue(isset($return['Pacific/Tahiti'])); if (!$this->skipIf(version_compare(PHP_VERSION, '5.3.0', '<'))) { $return = CakeTime::listTimezones(DateTimeZone::ASIA); $this->assertTrue(isset($return['Asia']['Asia/Bangkok'])); $this->assertFalse(isset($return['Pacific'])); $return = CakeTime::listTimezones(DateTimeZone::PER_COUNTRY, 'US', false); $this->assertTrue(isset($return['Pacific/Honolulu'])); $this->assertFalse(isset($return['Asia/Bangkok'])); } } /** * Tests that using CakeTime::format() with the correct sytax actually converts * from one timezone to the other correctly * * @return void */ public function testCorrectTimezoneConversion() { date_default_timezone_set('UTC'); $date = '2012-01-01 10:00:00'; $converted = CakeTime::format($date, '%Y-%m-%d %H:%M', '', 'Europe/Copenhagen'); $expected = new DateTime($date); $expected->setTimezone(new DateTimeZone('Europe/Copenhagen')); $this->assertEquals($expected->format('Y-m-d H:i'), $converted); } } cakephp-2.8.0/lib/Cake/Test/Case/Utility/ClassRegistryTest.php000066400000000000000000000205511265552240500241620ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Utility * @since CakePHP(tm) v 1.2.0.5432 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('ClassRegistry', 'Utility'); /** * ClassRegisterModel class * * @package Cake.Test.Case.Utility */ class ClassRegisterModel extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; } /** * RegisterArticle class * * @package Cake.Test.Case.Utility */ class RegisterArticle extends ClassRegisterModel { } /** * RegisterArticleFeatured class * * @package Cake.Test.Case.Utility */ class RegisterArticleFeatured extends ClassRegisterModel { } /** * RegisterArticleTag class * * @package Cake.Test.Case.Utility */ class RegisterArticleTag extends ClassRegisterModel { } /** * RegistryPluginAppModel class * * @package Cake.Test.Case.Utility */ class RegistryPluginAppModel extends ClassRegisterModel { /** * tablePrefix property * * @var string */ public $tablePrefix = 'something_'; } /** * TestRegistryPluginModel class * * @package Cake.Test.Case.Utility */ class TestRegistryPluginModel extends RegistryPluginAppModel { } /** * RegisterCategory class * * @package Cake.Test.Case.Utility */ class RegisterCategory extends ClassRegisterModel { } /** * RegisterPrefixedDs class * * @package Cake.Test.Case.Utility */ class RegisterPrefixedDs extends ClassRegisterModel { /** * useDbConfig property * * @var string */ public $useDbConfig = 'doesnotexist'; } /** * Abstract class for testing ClassRegistry. */ abstract class ClassRegistryAbstractModel extends ClassRegisterModel { public abstract function doSomething(); } /** * Interface for testing ClassRegistry */ interface ClassRegistryInterfaceTest { public function doSomething(); } /** * ClassRegistryTest class * * @package Cake.Test.Case.Utility */ class ClassRegistryTest extends CakeTestCase { /** * testAddModel method * * @return void */ public function testAddModel() { $Tag = ClassRegistry::init('RegisterArticleTag'); $this->assertInstanceOf('RegisterArticleTag', $Tag); $TagCopy = ClassRegistry::isKeySet('RegisterArticleTag'); $this->assertTrue($TagCopy); $Tag->name = 'SomeNewName'; $TagCopy = ClassRegistry::getObject('RegisterArticleTag'); $this->assertInstanceOf('RegisterArticleTag', $TagCopy); $this->assertSame($Tag, $TagCopy); $NewTag = ClassRegistry::init(array('class' => 'RegisterArticleTag', 'alias' => 'NewTag')); $this->assertInstanceOf('RegisterArticleTag', $Tag); $NewTagCopy = ClassRegistry::init(array('class' => 'RegisterArticleTag', 'alias' => 'NewTag')); $this->assertNotSame($Tag, $NewTag); $this->assertSame($NewTag, $NewTagCopy); $NewTag->name = 'SomeOtherName'; $this->assertNotSame($Tag, $NewTag); $this->assertSame($NewTag, $NewTagCopy); $Tag->name = 'SomeOtherName'; $this->assertNotSame($Tag, $NewTag); $this->assertTrue($TagCopy->name === 'SomeOtherName'); $User = ClassRegistry::init(array('class' => 'RegisterUser', 'alias' => 'User', 'table' => false)); $this->assertInstanceOf('AppModel', $User); $UserCopy = ClassRegistry::init(array('class' => 'RegisterUser', 'alias' => 'User', 'table' => false)); $this->assertInstanceOf('AppModel', $UserCopy); $this->assertEquals($User, $UserCopy); $Category = ClassRegistry::init(array('class' => 'RegisterCategory')); $this->assertInstanceOf('RegisterCategory', $Category); $ParentCategory = ClassRegistry::init(array('class' => 'RegisterCategory', 'alias' => 'ParentCategory')); $this->assertInstanceOf('RegisterCategory', $ParentCategory); $this->assertNotSame($Category, $ParentCategory); $this->assertNotEquals($Category->alias, $ParentCategory->alias); $this->assertEquals('RegisterCategory', $Category->alias); $this->assertEquals('ParentCategory', $ParentCategory->alias); } /** * testClassRegistryFlush method * * @return void */ public function testClassRegistryFlush() { ClassRegistry::init('RegisterArticleTag'); $ArticleTag = ClassRegistry::getObject('RegisterArticleTag'); $this->assertInstanceOf('RegisterArticleTag', $ArticleTag); ClassRegistry::flush(); $NoArticleTag = ClassRegistry::isKeySet('RegisterArticleTag'); $this->assertFalse($NoArticleTag); $this->assertInstanceOf('RegisterArticleTag', $ArticleTag); } /** * testAddMultipleModels method * * @return void */ public function testAddMultipleModels() { $Article = ClassRegistry::isKeySet('Article'); $this->assertFalse($Article); $Featured = ClassRegistry::isKeySet('Featured'); $this->assertFalse($Featured); $Tag = ClassRegistry::isKeySet('Tag'); $this->assertFalse($Tag); $models = array(array('class' => 'RegisterArticle', 'alias' => 'Article'), array('class' => 'RegisterArticleFeatured', 'alias' => 'Featured'), array('class' => 'RegisterArticleTag', 'alias' => 'Tag')); $added = ClassRegistry::init($models); $this->assertTrue($added); $Article = ClassRegistry::isKeySet('Article'); $this->assertTrue($Article); $Featured = ClassRegistry::isKeySet('Featured'); $this->assertTrue($Featured); $Tag = ClassRegistry::isKeySet('Tag'); $this->assertTrue($Tag); $Article = ClassRegistry::getObject('Article'); $this->assertInstanceOf('RegisterArticle', $Article); $Featured = ClassRegistry::getObject('Featured'); $this->assertInstanceOf('RegisterArticleFeatured', $Featured); $Tag = ClassRegistry::getObject('Tag'); $this->assertInstanceOf('RegisterArticleTag', $Tag); } /** * testPluginAppModel method * * @return void */ public function testPluginAppModel() { $TestRegistryPluginModel = ClassRegistry::isKeySet('TestRegistryPluginModel'); $this->assertFalse($TestRegistryPluginModel); //Faking a plugin CakePlugin::load('RegistryPlugin', array('path' => '/fake/path')); $TestRegistryPluginModel = ClassRegistry::init('RegistryPlugin.TestRegistryPluginModel'); $this->assertInstanceOf('TestRegistryPluginModel', $TestRegistryPluginModel); $this->assertEquals('something_', $TestRegistryPluginModel->tablePrefix); $PluginUser = ClassRegistry::init(array('class' => 'RegistryPlugin.RegisterUser', 'alias' => 'RegistryPluginUser', 'table' => false)); $this->assertInstanceOf('RegistryPluginAppModel', $PluginUser); $PluginUserCopy = ClassRegistry::getObject('RegistryPluginUser'); $this->assertInstanceOf('RegistryPluginAppModel', $PluginUserCopy); $this->assertSame($PluginUser, $PluginUserCopy); CakePlugin::unload(); } /** * Tests prefixed datasource names for test purposes * * @return void */ public function testPrefixedTestDatasource() { ClassRegistry::config(array('testing' => true)); $Model = ClassRegistry::init('RegisterPrefixedDs'); $this->assertEquals('test', $Model->useDbConfig); ClassRegistry::removeObject('RegisterPrefixedDs'); $testConfig = ConnectionManager::getDataSource('test')->config; ConnectionManager::create('test_doesnotexist', $testConfig); $Model = ClassRegistry::init('RegisterArticle'); $this->assertEquals('test', $Model->useDbConfig); $Model = ClassRegistry::init('RegisterPrefixedDs'); $this->assertEquals('test_doesnotexist', $Model->useDbConfig); } /** * Tests that passing the string parameter to init() will return false if the model does not exists * * @return void */ public function testInitStrict() { $this->assertFalse(ClassRegistry::init('NonExistent', true)); } /** * Test that you cannot init() an abstract class. An exception will be raised. * * @expectedException CakeException * @return void */ public function testInitAbstractClass() { ClassRegistry::init('ClassRegistryAbstractModel'); } /** * Test that you cannot init() an abstract class. A exception will be raised. * * @expectedException CakeException * @return void */ public function testInitInterface() { ClassRegistry::init('ClassRegistryInterfaceTest'); } } cakephp-2.8.0/lib/Cake/Test/Case/Utility/DebuggerTest.php000066400000000000000000000361431265552240500231140ustar00rootroot00000000000000_restoreError) { restore_error_handler(); } } /** * testDocRef method * * @return void */ public function testDocRef() { ini_set('docref_root', ''); $this->assertEquals(ini_get('docref_root'), ''); new Debugger(); $this->assertEquals(ini_get('docref_root'), 'http://php.net/'); } /** * test Excerpt writing * * @return void */ public function testExcerpt() { $result = Debugger::excerpt(__FILE__, __LINE__, 2); $this->assertTrue(is_array($result)); $this->assertEquals(5, count($result)); $this->assertRegExp('/function(.+)testExcerpt/', $result[1]); $result = Debugger::excerpt(__FILE__, 2, 2); $this->assertTrue(is_array($result)); $this->assertEquals(4, count($result)); $pattern = '/.*?.*?<\?php/'; $this->assertRegExp($pattern, $result[0]); $result = Debugger::excerpt(__FILE__, 11, 2); $this->assertEquals(5, count($result)); $pattern = '/\*<\/span>/'; $this->assertRegExp($pattern, $result[0]); $return = Debugger::excerpt('[internal]', 2, 2); $this->assertTrue(empty($return)); } /** * testOutput method * * @return void */ public function testOutput() { set_error_handler('Debugger::showError'); $this->_restoreError = true; $result = Debugger::output(false); $this->assertEquals('', $result); $out .= ''; $result = Debugger::output(true); $this->assertEquals('Notice', $result[0]['error']); $this->assertRegExp('/Undefined variable\:\s+out/', $result[0]['description']); $this->assertRegExp('/DebuggerTest::testOutput/i', $result[0]['trace']); ob_start(); Debugger::output('txt'); $other .= ''; $result = ob_get_clean(); $this->assertRegExp('/Undefined variable:\s+other/', $result); $this->assertRegExp('/Context:/', $result); $this->assertRegExp('/DebuggerTest::testOutput/i', $result); ob_start(); Debugger::output('html'); $wrong .= ''; $result = ob_get_clean(); $this->assertRegExp('/
.+<\/pre>/', $result);
		$this->assertRegExp('/Notice<\/b>/', $result);
		$this->assertRegExp('/variable:\s+wrong/', $result);

		ob_start();
		Debugger::output('js');
		$buzz .= '';
		$result = explode('', ob_get_clean());
		$this->assertTags($result[0], array(
			'pre' => array('class' => 'cake-error'),
			'a' => array(
				'href' => "javascript:void(0);",
				'onclick' => "preg:/document\.getElementById\('cakeErr[a-z0-9]+\-trace'\)\.style\.display = " .
					"\(document\.getElementById\('cakeErr[a-z0-9]+\-trace'\)\.style\.display == 'none'" .
					" \? '' \: 'none'\);/"
			),
			'b' => array(), 'Notice', '/b', ' (8)',
		));

		$this->assertRegExp('/Undefined variable:\s+buzz/', $result[1]);
		$this->assertRegExp('/]+>Code/', $result[1]);
		$this->assertRegExp('/]+>Context/', $result[2]);
		$this->assertContains('$wrong = ''', $result[3], 'Context should be HTML escaped.');
	}

/**
 * Tests that changes in output formats using Debugger::output() change the templates used.
 *
 * @return void
 */
	public function testChangeOutputFormats() {
		set_error_handler('Debugger::showError');
		$this->_restoreError = true;

		Debugger::output('js', array(
			'traceLine' => '{:reference} - {:path}, line {:line}'
		));
		$result = Debugger::trace();
		$this->assertRegExp('/' . preg_quote('txmt://open?url=file://', '/') . '(\/|[A-Z]:\\\\)' . '/', $result);

		Debugger::output('xml', array(
			'error' => '{:code}{:file}{:line}' .
				'{:description}',
			'context' => "{:context}",
			'trace' => "{:trace}",
		));
		Debugger::output('xml');

		ob_start();
		$foo .= '';
		$result = ob_get_clean();

		$data = array(
			'error' => array(),
			'code' => array(), '8', '/code',
			'file' => array(), 'preg:/[^<]+/', '/file',
			'line' => array(), '' . ((int)__LINE__ - 7), '/line',
			'preg:/Undefined variable:\s+foo/',
			'/error'
		);
		$this->assertTags($result, $data, true);
	}

/**
 * Test that outputAs works.
 *
 * @return void
 */
	public function testOutputAs() {
		Debugger::outputAs('html');
		$this->assertEquals('html', Debugger::outputAs());
	}

/**
 * Test that choosing a non-existent format causes an exception
 *
 * @expectedException CakeException
 * @return void
 */
	public function testOutputAsException() {
		Debugger::outputAs('Invalid junk');
	}

/**
 * Tests that changes in output formats using Debugger::output() change the templates used.
 *
 * @return void
 */
	public function testAddFormat() {
		set_error_handler('Debugger::showError');
		$this->_restoreError = true;

		Debugger::addFormat('js', array(
			'traceLine' => '{:reference} - {:path}, line {:line}'
		));
		Debugger::outputAs('js');

		$result = Debugger::trace();
		$this->assertRegExp('/' . preg_quote('txmt://open?url=file://', '/') . '(\/|[A-Z]:\\\\)' . '/', $result);

		Debugger::addFormat('xml', array(
			'error' => '{:code}{:file}{:line}' .
				'{:description}',
		));
		Debugger::outputAs('xml');

		ob_start();
		$foo .= '';
		$result = ob_get_clean();

		$data = array(
			'assertTags($result, $data, true);
	}

/**
 * Test adding a format that is handled by a callback.
 *
 * @return void
 */
	public function testAddFormatCallback() {
		set_error_handler('Debugger::showError');
		$this->_restoreError = true;

		Debugger::addFormat('callback', array('callback' => array($this, 'customFormat')));
		Debugger::outputAs('callback');

		ob_start();
		$foo .= '';
		$result = ob_get_clean();
		$this->assertContains('Notice: I eated an error', $result);
		$this->assertContains('DebuggerTest.php', $result);
	}

/**
 * Test method for testing addFormat with callbacks.
 *
 * @return void
 */
	public function customFormat($error, $strings) {
		return $error['error'] . ': I eated an error ' . $error['file'];
	}

/**
 * testTrimPath method
 *
 * @return void
 */
	public function testTrimPath() {
		$this->assertEquals('APP' . DS, Debugger::trimPath(APP));
		$this->assertEquals('CORE', Debugger::trimPath(CAKE_CORE_INCLUDE_PATH));
		$this->assertEquals('ROOT', Debugger::trimPath(ROOT));
		$this->assertEquals('CORE' . DS . 'Cake' . DS, Debugger::trimPath(CAKE));
		$this->assertEquals('Some/Other/Path', Debugger::trimPath('Some/Other/Path'));
	}

/**
 * testExportVar method
 *
 * @return void
 */
	public function testExportVar() {
		App::uses('Controller', 'Controller');
		$Controller = new Controller();
		$Controller->helpers = array('Html', 'Form');
		$View = new View($Controller);
		$View->int = 2;
		$View->float = 1.333;

		$result = Debugger::exportVar($View);
		$expected = << object(HelperCollection) {}
	Blocks => object(ViewBlock) {}
	plugin => null
	name => ''
	passedArgs => array()
	helpers => array(
		(int) 0 => 'Html',
		(int) 1 => 'Form'
	)
	viewPath => ''
	viewVars => array()
	view => null
	layout => 'default'
	layoutPath => null
	autoLayout => true
	ext => '.ctp'
	subDir => null
	theme => null
	cacheAction => false
	validationErrors => array()
	hasRendered => false
	uuids => array()
	request => object(CakeRequest) {}
	response => object(CakeResponse) {}
	elementCache => 'default'
	elementCacheSettings => array()
	Html => object(HtmlHelper) {}
	Form => object(FormHelper) {}
	int => (int) 2
	float => (float) 1.333

TEXT;
		if (version_compare(PHP_VERSION, '5.3.0') >= 0) {
			$expected .= << array(
		(int) 0 => 'viewVars',
		(int) 1 => 'autoLayout',
		(int) 2 => 'ext',
		(int) 3 => 'helpers',
		(int) 4 => 'view',
		(int) 5 => 'layout',
		(int) 6 => 'name',
		(int) 7 => 'theme',
		(int) 8 => 'layoutPath',
		(int) 9 => 'viewPath',
		(int) 10 => 'request',
		(int) 11 => 'plugin',
		(int) 12 => 'passedArgs',
		(int) 13 => 'cacheAction'
	)
	[protected] _scripts => array()
	[protected] _paths => array()
	[protected] _pathsForPlugin => array()
	[protected] _parents => array()
	[protected] _current => null
	[protected] _currentType => ''
	[protected] _stack => array()
	[protected] _eventManager => object(CakeEventManager) {}
	[protected] _eventManagerConfigured => false

TEXT;
		}
		$expected .= <<assertTextEquals($expected, $result);

		$data = array(
			1 => 'Index one',
			5 => 'Index five'
		);
		$result = Debugger::exportVar($data);
		$expected = << 'Index one',
	(int) 5 => 'Index five'
)
TEXT;
		$this->assertTextEquals($expected, $result);

		$data = array(
			'key' => array(
				'value'
			)
		);
		$result = Debugger::exportVar($data, 1);
		$expected = << array(
		[maximum depth reached]
	)
)
TEXT;
		$this->assertTextEquals($expected, $result);

		$data = false;
		$result = Debugger::exportVar($data);
		$expected = <<assertTextEquals($expected, $result);

		$file = fopen('php://output', 'w');
		fclose($file);
		$result = Debugger::exportVar($file);
		$this->assertTextEquals('unknown', $result);
	}

/**
 * Test exporting various kinds of false.
 *
 * @return void
 */
	public function testExportVarZero() {
		$data = array(
			'nothing' => '',
			'null' => null,
			'false' => false,
			'szero' => '0',
			'zero' => 0
		);
		$result = Debugger::exportVar($data);
		$expected = << '',
	'null' => null,
	'false' => false,
	'szero' => '0',
	'zero' => (int) 0
)
TEXT;
		$this->assertTextEquals($expected, $result);
	}

/**
 * testLog method
 *
 * @return void
 */
	public function testLog() {
		if (file_exists(LOGS . 'debug.log')) {
			unlink(LOGS . 'debug.log');
		}
		CakeLog::config('file', array('engine' => 'File', 'path' => TMP . 'logs' . DS));

		Debugger::log('cool');
		$result = file_get_contents(LOGS . 'debug.log');
		$this->assertContains('DebuggerTest::testLog', $result);
		$this->assertContains("'cool'", $result);

		unlink(LOGS . 'debug.log');

		Debugger::log(array('whatever', 'here'));
		$result = file_get_contents(LOGS . 'debug.log');
		$this->assertContains('DebuggerTest::testLog', $result);
		$this->assertContains('[main]', $result);
		$this->assertContains('array', $result);
		$this->assertContains("'whatever',", $result);
		$this->assertContains("'here'", $result);
	}

/**
 * test log() depth
 *
 * @return void
 */
	public function testLogDepth() {
		if (file_exists(LOGS . 'debug.log')) {
			unlink(LOGS . 'debug.log');
		}
		CakeLog::config('file', array('engine' => 'File', 'path' => TMP . 'logs' . DS));

		$val = array(
			'test' => array('key' => 'val')
		);
		Debugger::log($val, LOG_DEBUG, 0);
		$result = file_get_contents(LOGS . 'debug.log');
		$this->assertContains('DebuggerTest::testLog', $result);
		$this->assertNotContains("/'val'/", $result);

		unlink(LOGS . 'debug.log');
	}

/**
 * testDump method
 *
 * @return void
 */
	public function testDump() {
		$var = array('People' => array(
			array(
				'name' => 'joeseph',
				'coat' => 'technicolor',
				'hair_color' => 'brown'
			),
			array(
				'name' => 'Shaft',
				'coat' => 'black',
				'hair' => 'black'
			)
		));
		ob_start();
		Debugger::dump($var);
		$result = ob_get_clean();

		$open = PHP_SAPI === 'cli' ? "\n" : '
';
		$close = PHP_SAPI === 'cli' ? "\n" : '
'; $expected = << array( (int) 0 => array( 'name' => 'joeseph', 'coat' => 'technicolor', 'hair_color' => 'brown' ), (int) 1 => array( 'name' => 'Shaft', 'coat' => 'black', 'hair' => 'black' ) ) ){$close} TEXT; $this->assertTextEquals($expected, $result); ob_start(); Debugger::dump($var, 1); $result = ob_get_clean(); $open = PHP_SAPI === 'cli' ? "\n" : '
';
		$close = PHP_SAPI === 'cli' ? "\n" : '
'; $expected = << array( [maximum depth reached] ) ){$close} TEXT; $this->assertTextEquals($expected, $result); } /** * test getInstance. * * @return void */ public function testGetInstance() { $result = Debugger::getInstance(); $this->assertInstanceOf('Debugger', $result); $result = Debugger::getInstance('DebuggerTestCaseDebugger'); $this->assertInstanceOf('DebuggerTestCaseDebugger', $result); $result = Debugger::getInstance(); $this->assertInstanceOf('DebuggerTestCaseDebugger', $result); $result = Debugger::getInstance('Debugger'); $this->assertInstanceOf('Debugger', $result); } /** * testNoDbCredentials * * If a connection error occurs, the config variable is passed through exportVar * *** our database login credentials such that they are never visible * * @return void */ public function testNoDbCredentials() { $config = array( 'datasource' => 'mysql', 'persistent' => false, 'host' => 'void.cakephp.org', 'login' => 'cakephp-user', 'password' => 'cakephp-password', 'database' => 'cakephp-database', 'prefix' => '' ); $output = Debugger::exportVar($config); $expectedArray = array( 'datasource' => 'mysql', 'persistent' => false, 'host' => '*****', 'login' => '*****', 'password' => '*****', 'database' => '*****', 'prefix' => '' ); $expected = Debugger::exportVar($expectedArray); $this->assertEquals($expected, $output); } /** * Test that exportVar() doesn't loop through recursive structures. * * @return void */ public function testExportVarRecursion() { $output = Debugger::exportVar($GLOBALS); $this->assertContains("'GLOBALS' => [recursion]", $output); } /** * test trace exclude * * @return void */ public function testTraceExclude() { $result = Debugger::trace(); $this->assertRegExp('/^DebuggerTest::testTraceExclude/', $result); $result = Debugger::trace(array( 'exclude' => array('DebuggerTest::testTraceExclude') )); $this->assertNotRegExp('/^DebuggerTest::testTraceExclude/', $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Utility/FileTest.php000066400000000000000000000375261265552240500222550ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Utility * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('File', 'Utility'); App::uses('Folder', 'Utility'); /** * FileTest class * * @package Cake.Test.Case.Utility * @coversDefaultClass File */ class FileTest extends CakeTestCase { /** * File property * * @var mixed */ public $File = null; /** * setup the test case * * @return void */ public function setUp() { parent::setUp(); $file = __FILE__; $this->File = new File($file); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); $this->File->close(); unset($this->File); $Folder = new Folder(); $Folder->delete(TMP . 'tests' . DS . 'permissions'); } /** * testBasic method * * @return void * @covers ::__construct * @covers ::info * @covers ::ext * @covers ::name * @covers ::md5 * @covers ::size * @covers ::owner * @covers ::group * @covers ::Folder */ public function testBasic() { $file = CAKE . DS . 'LICENSE.txt'; $this->File = new File($file, false); $result = $this->File->name; $expecting = basename($file); $this->assertEquals($expecting, $result); $result = $this->File->info(); $expecting = array( 'dirname' => dirname($file), 'basename' => basename($file), 'extension' => 'txt', 'filename' => 'LICENSE', 'filesize' => filesize($file), 'mime' => 'text/plain' ); if (!function_exists('finfo_open') && (!function_exists('mime_content_type') || function_exists('mime_content_type') && mime_content_type($this->File->pwd()) === false) ) { $expecting['mime'] = false; } $this->assertEquals($expecting, $result); $result = $this->File->ext(); $expecting = 'txt'; $this->assertEquals($expecting, $result); $result = $this->File->name(); $expecting = 'LICENSE'; $this->assertEquals($expecting, $result); $result = $this->File->md5(); $expecting = md5_file($file); $this->assertEquals($expecting, $result); $result = $this->File->md5(true); $expecting = md5_file($file); $this->assertEquals($expecting, $result); $result = $this->File->size(); $expecting = filesize($file); $this->assertEquals($expecting, $result); $result = $this->File->owner(); $expecting = fileowner($file); $this->assertEquals($expecting, $result); $result = $this->File->group(); $expecting = filegroup($file); $this->assertEquals($expecting, $result); $result = $this->File->Folder(); $this->assertInstanceOf('Folder', $result); } /** * testPermission method * * @return void * @covers ::perms */ public function testPermission() { $this->skipIf(DIRECTORY_SEPARATOR === '\\', 'File permissions tests not supported on Windows.'); $dir = TMP . 'tests' . DS . 'permissions' . DS; $old = umask(); umask(0002); $file = $dir . 'permission_' . uniqid(); $expecting = decoct(0664 & ~umask()); $File = new File($file, true); $result = $File->perms(); $this->assertEquals($expecting, $result); $File->delete(); umask(0022); $file = $dir . 'permission_' . uniqid(); $expecting = decoct(0644 & ~umask()); $File = new File($file, true); $result = $File->perms(); $this->assertEquals($expecting, $result); $File->delete(); umask(0422); $file = $dir . 'permission_' . uniqid(); $expecting = decoct(0244 & ~umask()); $File = new File($file, true); $result = $File->perms(); $this->assertEquals($expecting, $result); $File->delete(); umask(0444); $file = $dir . 'permission_' . uniqid(); $expecting = decoct(0222 & ~umask()); $File = new File($file, true); $result = $File->perms(); $this->assertEquals($expecting, $result); $File->delete(); umask($old); } /** * testRead method * * @return void * @covers ::read */ public function testRead() { $file = __FILE__; $this->File = new File($file); $result = $this->File->read(); $expecting = file_get_contents(__FILE__); $this->assertEquals($expecting, $result); $this->assertTrue(!is_resource($this->File->handle)); $this->File->lock = true; $result = $this->File->read(); $expecting = file_get_contents(__FILE__); $this->assertEquals(trim($expecting), $result); $this->File->lock = null; $data = $expecting; $expecting = substr($data, 0, 3); $result = $this->File->read(3); $this->assertEquals($expecting, $result); $this->assertTrue(is_resource($this->File->handle)); $expecting = substr($data, 3, 3); $result = $this->File->read(3); $this->assertEquals($expecting, $result); } /** * testOffset method * * @return void * @covers ::offset */ public function testOffset() { $this->File->close(); $result = $this->File->offset(); $this->assertFalse($result); $this->assertFalse(is_resource($this->File->handle)); $success = $this->File->offset(0); $this->assertTrue($success); $this->assertTrue(is_resource($this->File->handle)); $result = $this->File->offset(); $expected = 0; $this->assertSame($expected, $result); $data = file_get_contents(__FILE__); $success = $this->File->offset(5); $expected = substr($data, 5, 3); $result = $this->File->read(3); $this->assertTrue($success); $this->assertEquals($expected, $result); $result = $this->File->offset(); $expected = 5 + 3; $this->assertSame($expected, $result); } /** * testOpen method * * @return void * @covers ::open */ public function testOpen() { $this->File->handle = null; $r = $this->File->open(); $this->assertTrue(is_resource($this->File->handle)); $this->assertTrue($r); $handle = $this->File->handle; $r = $this->File->open(); $this->assertTrue($r); $this->assertTrue($handle === $this->File->handle); $this->assertTrue(is_resource($this->File->handle)); $r = $this->File->open('r', true); $this->assertTrue($r); $this->assertFalse($handle === $this->File->handle); $this->assertTrue(is_resource($this->File->handle)); } /** * testClose method * * @return void * @covers ::close */ public function testClose() { $this->File->handle = null; $this->assertFalse(is_resource($this->File->handle)); $this->assertTrue($this->File->close()); $this->assertFalse(is_resource($this->File->handle)); $this->File->handle = fopen(__FILE__, 'r'); $this->assertTrue(is_resource($this->File->handle)); $this->assertTrue($this->File->close()); $this->assertFalse(is_resource($this->File->handle)); } /** * testCreate method * * @return void * @covers ::create * @covers ::exists * @covers ::clearStatCache */ public function testCreate() { $tmpFile = TMP . 'tests' . DS . 'cakephp.file.test.tmp'; $File = new File($tmpFile, true, 0777); $this->assertTrue($File->exists()); } /** * Tests the exists() method. * * @return void */ public function testExists() { $tmpFile = TMP . 'tests/cakephp.file.test.tmp'; $file = new File($tmpFile, true, 0777); $this->assertTrue($file->exists(), 'absolute path should exist'); $file = new File('file://' . $tmpFile, false); $this->assertTrue($file->exists(), 'file:// should exist.'); $file = new File('/something/bad', false); $this->assertFalse($file->exists(), 'missing file should not exist.'); } /** * testOpeningNonExistentFileCreatesIt method * * @return void * @covers ::open * @covers ::create */ public function testOpeningNonExistentFileCreatesIt() { $someFile = new File(TMP . 'some_file.txt', false); $this->assertTrue($someFile->open()); $this->assertEquals('', $someFile->read()); $someFile->close(); $someFile->delete(); } /** * testPrepare method * * @return void * @covers ::prepare */ public function testPrepare() { $string = "some\nvery\ncool\r\nteststring here\n\n\nfor\r\r\n\n\r\n\nhere"; if (DS === '\\') { $expected = "some\r\nvery\r\ncool\r\nteststring here\r\n\r\n\r\n"; $expected .= "for\r\n\r\n\r\n\r\n\r\nhere"; } else { $expected = "some\nvery\ncool\nteststring here\n\n\nfor\n\n\n\n\nhere"; } $this->assertSame($expected, File::prepare($string)); $expected = "some\r\nvery\r\ncool\r\nteststring here\r\n\r\n\r\n"; $expected .= "for\r\n\r\n\r\n\r\n\r\nhere"; $this->assertSame($expected, File::prepare($string, true)); } /** * testReadable method * * @return void * @covers ::readable */ public function testReadable() { $someFile = new File(TMP . 'some_file.txt', false); $this->assertTrue($someFile->open()); $this->assertTrue($someFile->readable()); $someFile->close(); $someFile->delete(); } /** * testWritable method * * @return void * @covers ::writable */ public function testWritable() { $someFile = new File(TMP . 'some_file.txt', false); $this->assertTrue($someFile->open()); $this->assertTrue($someFile->writable()); $someFile->close(); $someFile->delete(); } /** * testExecutable method * * @return void * @covers ::executable */ public function testExecutable() { $someFile = new File(TMP . 'some_file.txt', false); $this->assertTrue($someFile->open()); $this->assertFalse($someFile->executable()); $someFile->close(); $someFile->delete(); } /** * testLastAccess method * * @return void * @covers ::lastAccess */ public function testLastAccess() { $someFile = new File(TMP . 'some_file.txt', false); $this->assertFalse($someFile->lastAccess()); $this->assertTrue($someFile->open()); $this->assertWithinMargin($someFile->lastAccess(), time(), 2); $someFile->close(); $someFile->delete(); } /** * testLastChange method * * @return void * @covers ::lastChange */ public function testLastChange() { $someFile = new File(TMP . 'some_file.txt', false); $this->assertFalse($someFile->lastChange()); $this->assertTrue($someFile->open('r+')); $this->assertWithinMargin($someFile->lastChange(), time(), 2); $someFile->write('something'); $this->assertWithinMargin($someFile->lastChange(), time(), 2); $someFile->close(); $someFile->delete(); } /** * testWrite method * * @return void * @covers ::write */ public function testWrite() { if (!$tmpFile = $this->_getTmpFile()) { return false; } if (file_exists($tmpFile)) { unlink($tmpFile); } $TmpFile = new File($tmpFile); $this->assertFalse(file_exists($tmpFile)); $this->assertFalse(is_resource($TmpFile->handle)); $testData = array('CakePHP\'s', ' test suite', ' was here ...', ''); foreach ($testData as $data) { $r = $TmpFile->write($data); $this->assertTrue($r); $this->assertTrue(file_exists($tmpFile)); $this->assertEquals($data, file_get_contents($tmpFile)); $this->assertTrue(is_resource($TmpFile->handle)); $TmpFile->close(); } unlink($tmpFile); } /** * testAppend method * * @return void * @covers ::append */ public function testAppend() { if (!$tmpFile = $this->_getTmpFile()) { return false; } if (file_exists($tmpFile)) { unlink($tmpFile); } $TmpFile = new File($tmpFile); $this->assertFalse(file_exists($tmpFile)); $fragments = array('CakePHP\'s', ' test suite', ' was here ...'); $data = null; $size = 0; foreach ($fragments as $fragment) { $r = $TmpFile->append($fragment); $this->assertTrue($r); $this->assertTrue(file_exists($tmpFile)); $data = $data . $fragment; $this->assertEquals($data, file_get_contents($tmpFile)); $newSize = $TmpFile->size(); $this->assertTrue($newSize > $size); $size = $newSize; $TmpFile->close(); } $TmpFile->append(''); $this->assertEquals($data, file_get_contents($tmpFile)); $TmpFile->close(); } /** * testDelete method * * @return void * @covers ::delete */ public function testDelete() { if (!$tmpFile = $this->_getTmpFile()) { return false; } if (!file_exists($tmpFile)) { touch($tmpFile); } $TmpFile = new File($tmpFile); $this->assertTrue(file_exists($tmpFile)); $result = $TmpFile->delete(); $this->assertTrue($result); $this->assertFalse(file_exists($tmpFile)); $TmpFile = new File('/this/does/not/exist'); $result = $TmpFile->delete(); $this->assertFalse($result); } /** * Windows has issues unlinking files if there are * active filehandles open. * * @return void * @covers ::delete */ public function testDeleteAfterRead() { if (!$tmpFile = $this->_getTmpFile()) { return false; } if (!file_exists($tmpFile)) { touch($tmpFile); } $File = new File($tmpFile); $File->read(); $this->assertTrue($File->delete()); } /** * testCopy method * * @return void * @covers ::copy */ public function testCopy() { $dest = TMP . 'tests' . DS . 'cakephp.file.test.tmp'; $file = __FILE__; $this->File = new File($file); $result = $this->File->copy($dest); $this->assertTrue($result); $result = $this->File->copy($dest, true); $this->assertTrue($result); $result = $this->File->copy($dest, false); $this->assertFalse($result); $this->File->close(); unlink($dest); $TmpFile = new File('/this/does/not/exist'); $result = $TmpFile->copy($dest); $this->assertFalse($result); $TmpFile->close(); } /** * Test mime() * * @return void * @covers ::mime */ public function testMime() { $this->skipIf(!function_exists('finfo_open') && !function_exists('mime_content_type'), 'Not able to read mime type'); $path = CAKE . 'Test' . DS . 'test_app' . DS . 'webroot' . DS . 'img' . DS . 'cake.power.gif'; $file = new File($path); $expected = 'image/gif'; if (function_exists('mime_content_type') && mime_content_type($file->pwd()) === false) { $expected = false; } $this->assertEquals($expected, $file->mime()); } /** * getTmpFile method * * @param bool $paintSkip * @return void */ protected function _getTmpFile($paintSkip = true) { $tmpFile = TMP . 'tests' . DS . 'cakephp.file.test.tmp'; if (is_writable(dirname($tmpFile)) && (!file_exists($tmpFile) || is_writable($tmpFile))) { return $tmpFile; } if ($paintSkip) { $trace = debug_backtrace(); $caller = $trace[0]['function']; $shortPath = dirname($tmpFile); $message = __d('cake_dev', '[FileTest] Skipping %s because "%s" not writeable!', $caller, $shortPath); $this->markTestSkipped($message); } return false; } /** * testReplaceText method * * @return void * @covers ::replaceText */ public function testReplaceText() { $TestFile = new File(dirname(__FILE__) . '/../../test_app/Vendor/welcome.php'); $TmpFile = new File(TMP . 'tests' . DS . 'cakephp.file.test.tmp'); // Copy the test file to the temporary location $TestFile->copy($TmpFile->path, true); // Replace the contents of the tempory file $result = $TmpFile->replaceText('welcome.php', 'welcome.tmp'); $this->assertTrue($result); // Double check $expected = 'This is the welcome.tmp file in vendors directory'; $contents = $TmpFile->read(); $this->assertContains($expected, $contents); $search = array('This is the', 'welcome.php file', 'in tmp directory'); $replace = array('This should be a', 'welcome.tmp file', 'in the Lib directory'); // Replace the contents of the tempory file $result = $TmpFile->replaceText($search, $replace); $this->assertTrue($result); // Double check $expected = 'This should be a welcome.tmp file in vendors directory'; $contents = $TmpFile->read(); $this->assertContains($expected, $contents); $TmpFile->delete(); } /** * Tests that no path is being set for passed file paths that * do not exist. * * @return void * @covers ::pwd */ public function testNoPartialPathBeingSetForNonExistentPath() { $tmpFile = new File('/non/existent/file'); $this->assertNull($tmpFile->pwd()); $this->assertNull($tmpFile->path); } } cakephp-2.8.0/lib/Cake/Test/Case/Utility/FolderTest.php000066400000000000000000001066071265552240500226060ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Utility * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Folder', 'Utility'); App::uses('File', 'Utility'); /** * FolderTest class * * @package Cake.Test.Case.Utility */ class FolderTest extends CakeTestCase { protected static $_tmp = array(); /** * Save the directory names in TMP and make sure default directories exist * * @return void */ public static function setUpBeforeClass() { $dirs = array('cache', 'logs', 'sessions', 'tests'); foreach ($dirs as $dir) { new Folder(TMP . $dir, true); } foreach (scandir(TMP) as $file) { if (is_dir(TMP . $file) && !in_array($file, array('.', '..'))) { static::$_tmp[] = $file; } } } /** * setUp clearstatcache() to flush file descriptors. * * @return void */ public function setUp() { parent::setUp(); clearstatcache(); } /** * Restore the TMP directory to its original state. * * @return void */ public function tearDown() { $exclude = array_merge(static::$_tmp, array('.', '..')); foreach (scandir(TMP) as $dir) { if (is_dir(TMP . $dir) && !in_array($dir, $exclude)) { $iterator = new RecursiveDirectoryIterator(TMP . $dir); foreach (new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::CHILD_FIRST) as $file) { if ($file->isFile() || $file->isLink()) { unlink($file->getPathname()); } elseif ($file->isDir() && !in_array($file->getFilename(), array('.', '..'))) { rmdir($file->getPathname()); } } rmdir(TMP . $dir); } } parent::tearDown(); } /** * testBasic method * * @return void */ public function testBasic() { $path = dirname(__FILE__); $Folder = new Folder($path); $result = $Folder->pwd(); $this->assertEquals($path, $result); $result = Folder::addPathElement($path, 'test'); $expected = $path . DS . 'test'; $this->assertEquals($expected, $result); $result = $Folder->cd(ROOT); $expected = ROOT; $this->assertEquals($expected, $result); $result = $Folder->cd(ROOT . DS . 'non-existent'); $this->assertFalse($result); } /** * testInPath method * * @return void */ public function testInPath() { $path = dirname(dirname(__FILE__)); $inside = dirname($path) . DS; $Folder = new Folder($path); $result = $Folder->pwd(); $this->assertEquals($path, $result); $result = Folder::isSlashTerm($inside); $this->assertTrue($result); $result = $Folder->realpath('Test/'); $this->assertEquals($path . DS . 'Test' . DS, $result); $result = $Folder->inPath('Test' . DS); $this->assertTrue($result); $result = $Folder->inPath(DS . 'non-existing' . $inside); $this->assertFalse($result); $result = $Folder->inPath($path . DS . 'Model', true); $this->assertTrue($result); } /** * test creation of single and multiple paths. * * @return void */ public function testCreation() { $Folder = new Folder(TMP . 'tests'); $result = $Folder->create(TMP . 'tests' . DS . 'first' . DS . 'second' . DS . 'third'); $this->assertTrue($result); rmdir(TMP . 'tests' . DS . 'first' . DS . 'second' . DS . 'third'); rmdir(TMP . 'tests' . DS . 'first' . DS . 'second'); rmdir(TMP . 'tests' . DS . 'first'); $Folder = new Folder(TMP . 'tests'); $result = $Folder->create(TMP . 'tests' . DS . 'first'); $this->assertTrue($result); rmdir(TMP . 'tests' . DS . 'first'); } /** * test that creation of folders with trailing ds works * * @return void */ public function testCreateWithTrailingDs() { $Folder = new Folder(TMP); $path = TMP . 'tests' . DS . 'trailing' . DS . 'dir' . DS; $result = $Folder->create($path); $this->assertTrue($result); $this->assertTrue(is_dir($path), 'Folder was not made'); $Folder = new Folder(TMP . 'tests' . DS . 'trailing'); $this->assertTrue($Folder->delete()); } /** * Test that relative paths to create() are added to cwd. * * @return void */ public function testCreateRelative() { $folder = new Folder(TMP); $path = TMP . 'tests' . DS . 'relative-test'; $result = $folder->create('tests' . DS . 'relative-test'); $this->assertTrue($result, 'should create'); $this->assertTrue(is_dir($path), 'Folder was not made'); $folder = new Folder($path); $folder->delete(); } /** * test recursive directory create failure. * * @return void */ public function testRecursiveCreateFailure() { $this->skipIf(DIRECTORY_SEPARATOR === '\\', 'Cant perform operations using permissions on Windows.'); $path = TMP . 'tests' . DS . 'one'; mkdir($path); chmod($path, '0444'); try { $Folder = new Folder($path); $result = $Folder->create($path . DS . 'two' . DS . 'three'); $this->assertFalse($result); } catch (PHPUnit_Framework_Error $e) { $this->assertTrue(true); } chmod($path, '0777'); rmdir($path); } /** * testOperations method * * @return void */ public function testOperations() { $path = CAKE . 'Console' . DS . 'Templates' . DS . 'skel'; $Folder = new Folder($path); $result = is_dir($Folder->pwd()); $this->assertTrue($result); $new = TMP . 'test_folder_new'; $result = $Folder->create($new); $this->assertTrue($result); $copy = TMP . 'test_folder_copy'; $result = $Folder->copy($copy); $this->assertTrue($result); $copy = TMP . 'test_folder_copy'; $result = $Folder->copy($copy); $this->assertTrue($result); $copy = TMP . 'test_folder_copy'; $result = $Folder->chmod($copy, 0755, false); $this->assertTrue($result); $result = $Folder->cd($copy); $this->assertTrue((bool)$result); $mv = TMP . 'test_folder_mv'; $result = $Folder->move($mv); $this->assertTrue($result); $mv = TMP . 'test_folder_mv_2'; $result = $Folder->move($mv); $this->assertTrue($result); $result = $Folder->delete($new); $this->assertTrue($result); $result = $Folder->delete($mv); $this->assertTrue($result); $result = $Folder->delete($mv); $this->assertTrue($result); $new = APP . 'index.php'; $result = $Folder->create($new); $this->assertFalse($result); $expected = $new . ' is a file'; $result = $Folder->errors(); $this->assertEquals($expected, $result[0]); $new = TMP . 'test_folder_new'; $result = $Folder->create($new); $this->assertTrue($result); $result = $Folder->cd($new); $this->assertTrue((bool)$result); $result = $Folder->delete(); $this->assertTrue($result); $Folder = new Folder('non-existent'); $result = $Folder->pwd(); $this->assertNull($result); } /** * testChmod method * * @return void */ public function testChmod() { $this->skipIf(DIRECTORY_SEPARATOR === '\\', 'Folder permissions tests not supported on Windows.'); $path = TMP; $Folder = new Folder($path); $subdir = 'test_folder_new'; $new = TMP . $subdir; $this->assertTrue($Folder->create($new)); $this->assertTrue($Folder->create($new . DS . 'test1')); $this->assertTrue($Folder->create($new . DS . 'test2')); $filePath = $new . DS . 'test1.php'; $File = new File($filePath); $this->assertTrue($File->create()); $filePath = $new . DS . 'skip_me.php'; $File = new File($filePath); $this->assertTrue($File->create()); $this->assertTrue($Folder->chmod($new, 0755, true)); $perms = substr(sprintf('%o', fileperms($new . DS . 'test2')), -4); $this->assertEquals('0755', $perms); $this->assertTrue($Folder->chmod($new, 0744, true, array('skip_me.php', 'test2'))); $perms = substr(sprintf('%o', fileperms($new . DS . 'test2')), -4); $this->assertEquals('0755', $perms); $perms = substr(sprintf('%o', fileperms($new . DS . 'test1')), -4); $this->assertEquals('0744', $perms); $Folder->delete($new); } /** * testRealPathForWebroot method * * @return void */ public function testRealPathForWebroot() { $Folder = new Folder('files/'); $this->assertEquals(realpath('files/'), $Folder->path); } /** * testZeroAsDirectory method * * @return void */ public function testZeroAsDirectory() { $Folder = new Folder(TMP); $new = TMP . '0'; $this->assertTrue($Folder->create($new)); $result = $Folder->read(true, true); $expected = array('0', 'cache', 'logs', 'sessions', 'tests'); $this->assertEquals($expected, $result[0]); $result = $Folder->read(true, array('logs')); $expected = array('0', 'cache', 'sessions', 'tests'); $this->assertEquals($expected, $result[0]); $result = $Folder->delete($new); $this->assertTrue($result); } /** * test Adding path elements to a path * * @return void */ public function testAddPathElement() { $expected = DS . 'some' . DS . 'dir' . DS . 'another_path'; $result = Folder::addPathElement(DS . 'some' . DS . 'dir', 'another_path'); $this->assertEquals($expected, $result); $result = Folder::addPathElement(DS . 'some' . DS . 'dir' . DS, 'another_path'); $this->assertEquals($expected, $result); $result = Folder::addPathElement(DS . 'some' . DS . 'dir', array('another_path')); $this->assertEquals($expected, $result); $result = Folder::addPathElement(DS . 'some' . DS . 'dir' . DS, array('another_path')); $this->assertEquals($expected, $result); $expected = DS . 'some' . DS . 'dir' . DS . 'another_path' . DS . 'and' . DS . 'another'; $result = Folder::addPathElement(DS . 'some' . DS . 'dir', array('another_path', 'and', 'another')); $this->assertEquals($expected, $result); } /** * testFolderRead method * * @return void */ public function testFolderRead() { $Folder = new Folder(TMP); $expected = array('cache', 'logs', 'sessions', 'tests'); $result = $Folder->read(true, true); $this->assertEquals($expected, $result[0]); $Folder->path = TMP . 'non-existent'; $expected = array(array(), array()); $result = $Folder->read(true, true); $this->assertEquals($expected, $result); } /** * testFolderReadWithHiddenFiles method * * @return void */ public function testFolderReadWithHiddenFiles() { $this->skipIf(!is_writable(TMP), 'Cant test Folder::read with hidden files unless the tmp folder is writable.'); $Folder = new Folder(TMP . 'folder_tree_hidden', true, 0777); mkdir($Folder->path . DS . '.svn'); mkdir($Folder->path . DS . 'some_folder'); touch($Folder->path . DS . 'not_hidden.txt'); touch($Folder->path . DS . '.hidden.txt'); $expected = array( array('some_folder'), array('not_hidden.txt'), ); $result = $Folder->read(true, true); $this->assertEquals($expected, $result); $expected = array( array( '.svn', 'some_folder' ), array( '.hidden.txt', 'not_hidden.txt' ), ); $result = $Folder->read(true); $this->assertEquals($expected, $result); } /** * testFolderTree method * * @return void */ public function testFolderTree() { $Folder = new Folder(); $expected = array( array( CAKE . 'Config', CAKE . 'Config' . DS . 'unicode', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' ), array( CAKE . 'Config' . DS . 'config.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '0080_00ff.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '0100_017f.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '0180_024F.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '0250_02af.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '0370_03ff.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '0400_04ff.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '0500_052f.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '0530_058f.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '1e00_1eff.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '1f00_1fff.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '2100_214f.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '2150_218f.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '2460_24ff.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '2c00_2c5f.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '2c60_2c7f.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . '2c80_2cff.php', CAKE . 'Config' . DS . 'unicode' . DS . 'casefolding' . DS . 'ff00_ffef.php' ) ); $result = $Folder->tree(CAKE . 'Config', false); $this->assertSame(array(), array_diff($expected[0], $result[0])); $this->assertSame(array(), array_diff($result[0], $expected[0])); $result = $Folder->tree(CAKE . 'Config', false, 'dir'); $this->assertSame(array(), array_diff($expected[0], $result)); $this->assertSame(array(), array_diff($expected[0], $result)); $result = $Folder->tree(CAKE . 'Config', false, 'files'); $this->assertSame(array(), array_diff($expected[1], $result)); $this->assertSame(array(), array_diff($expected[1], $result)); } /** * testFolderTreeWithHiddenFiles method * * @return void */ public function testFolderTreeWithHiddenFiles() { $this->skipIf(!is_writable(TMP), 'Can\'t test Folder::tree with hidden files unless the tmp folder is writable.'); $Folder = new Folder(TMP . 'folder_tree_hidden', true, 0777); mkdir($Folder->path . DS . '.svn', 0777, true); touch($Folder->path . DS . '.svn' . DS . 'InHiddenFolder.php'); mkdir($Folder->path . DS . '.svn' . DS . 'inhiddenfolder'); touch($Folder->path . DS . '.svn' . DS . 'inhiddenfolder' . DS . 'NestedInHiddenFolder.php'); touch($Folder->path . DS . 'not_hidden.txt'); touch($Folder->path . DS . '.hidden.txt'); mkdir($Folder->path . DS . 'visible_folder' . DS . '.git', 0777, true); $expected = array( array( $Folder->path, $Folder->path . DS . 'visible_folder', ), array( $Folder->path . DS . 'not_hidden.txt', ), ); $result = $Folder->tree(null, true); $this->assertEquals($expected, $result); $result = $Folder->tree(null, array('.')); $this->assertEquals($expected, $result); $expected = array( array( $Folder->path, $Folder->path . DS . 'visible_folder', $Folder->path . DS . 'visible_folder' . DS . '.git', $Folder->path . DS . '.svn', $Folder->path . DS . '.svn' . DS . 'inhiddenfolder', ), array( $Folder->path . DS . 'not_hidden.txt', $Folder->path . DS . '.hidden.txt', $Folder->path . DS . '.svn' . DS . 'inhiddenfolder' . DS . 'NestedInHiddenFolder.php', $Folder->path . DS . '.svn' . DS . 'InHiddenFolder.php', ), ); $result = $Folder->tree(null, false); sort($result[0]); sort($expected[0]); sort($result[1]); sort($expected[1]); $this->assertEquals($expected, $result); $Folder->delete(); } /** * testWindowsPath method * * @return void */ public function testWindowsPath() { $this->assertFalse(Folder::isWindowsPath('0:\\cake\\is\\awesome')); $this->assertTrue(Folder::isWindowsPath('C:\\cake\\is\\awesome')); $this->assertTrue(Folder::isWindowsPath('d:\\cake\\is\\awesome')); $this->assertTrue(Folder::isWindowsPath('\\\\vmware-host\\Shared Folders\\file')); } /** * testIsAbsolute method * * @return void */ public function testIsAbsolute() { $this->assertFalse(Folder::isAbsolute('path/to/file')); $this->assertFalse(Folder::isAbsolute('cake/')); $this->assertFalse(Folder::isAbsolute('path\\to\\file')); $this->assertFalse(Folder::isAbsolute('0:\\path\\to\\file')); $this->assertFalse(Folder::isAbsolute('\\path/to/file')); $this->assertFalse(Folder::isAbsolute('\\path\\to\\file')); $this->assertFalse(Folder::isAbsolute('notRegisteredStreamWrapper://example')); $this->assertFalse(Folder::isAbsolute('://example')); $this->assertTrue(Folder::isAbsolute('/usr/local')); $this->assertTrue(Folder::isAbsolute('//path/to/file')); $this->assertTrue(Folder::isAbsolute('C:\\cake')); $this->assertTrue(Folder::isAbsolute('C:\\path\\to\\file')); $this->assertTrue(Folder::isAbsolute('d:\\path\\to\\file')); $this->assertTrue(Folder::isAbsolute('\\\\vmware-host\\Shared Folders\\file')); $this->assertTrue(Folder::isAbsolute('http://www.example.com')); } /** * testIsSlashTerm method * * @return void */ public function testIsSlashTerm() { $this->assertFalse(Folder::isSlashTerm('cake')); $this->assertTrue(Folder::isSlashTerm('C:\\cake\\')); $this->assertTrue(Folder::isSlashTerm('/usr/local/')); } /** * testStatic method * * @return void */ public function testSlashTerm() { $result = Folder::slashTerm('/path/to/file'); $this->assertEquals('/path/to/file/', $result); } /** * testNormalizePath method * * @return void */ public function testNormalizePath() { $path = '/path/to/file'; $result = Folder::normalizePath($path); $this->assertEquals('/', $result); $path = '\\path\\\to\\\file'; $result = Folder::normalizePath($path); $this->assertEquals('/', $result); $path = 'C:\\path\\to\\file'; $result = Folder::normalizePath($path); $this->assertEquals('\\', $result); } /** * correctSlashFor method * * @return void */ public function testCorrectSlashFor() { $path = '/path/to/file'; $result = Folder::correctSlashFor($path); $this->assertEquals('/', $result); $path = '\\path\\to\\file'; $result = Folder::correctSlashFor($path); $this->assertEquals('/', $result); $path = 'C:\\path\to\\file'; $result = Folder::correctSlashFor($path); $this->assertEquals('\\', $result); } /** * testInCakePath method * * @return void */ public function testInCakePath() { $Folder = new Folder(); $Folder->cd(ROOT); $path = 'C:\\path\\to\\file'; $result = $Folder->inCakePath($path); $this->assertFalse($result); $path = ROOT; $Folder->cd(ROOT); $result = $Folder->inCakePath($path); $this->assertFalse($result); $path = DS . 'lib' . DS . 'Cake' . DS . 'Config'; $Folder->cd(ROOT . DS . 'lib' . DS . 'Cake' . DS . 'Config'); $result = $Folder->inCakePath($path); $this->assertTrue($result); } /** * testFind method * * @return void */ public function testFind() { $Folder = new Folder(); $Folder->cd(CAKE . 'Config'); $result = $Folder->find(); $expected = array('config.php'); $this->assertSame(array_diff($expected, $result), array()); $this->assertSame(array_diff($expected, $result), array()); $result = $Folder->find('.*', true); $expected = array('cacert.pem', 'config.php', 'routes.php'); $this->assertSame($expected, $result); $result = $Folder->find('.*\.php'); $expected = array('config.php'); $this->assertSame(array_diff($expected, $result), array()); $this->assertSame(array_diff($expected, $result), array()); $result = $Folder->find('.*\.php', true); $expected = array('config.php', 'routes.php'); $this->assertSame($expected, $result); $result = $Folder->find('.*ig\.php'); $expected = array('config.php'); $this->assertSame($expected, $result); $result = $Folder->find('config\.php'); $expected = array('config.php'); $this->assertSame($expected, $result); $Folder->cd(TMP); $File = new File($Folder->pwd() . DS . 'paths.php', true); $Folder->create($Folder->pwd() . DS . 'testme'); $Folder->cd('testme'); $result = $Folder->find('paths\.php'); $expected = array(); $this->assertSame($expected, $result); $Folder->cd($Folder->pwd() . '/..'); $result = $Folder->find('paths\.php'); $expected = array('paths.php'); $this->assertSame($expected, $result); $Folder->cd(TMP); $Folder->delete($Folder->pwd() . DS . 'testme'); $File->delete(); } /** * testFindRecursive method * * @return void */ public function testFindRecursive() { $Folder = new Folder(); $Folder->cd(CAKE); $result = $Folder->findRecursive('(config|paths)\.php'); $expected = array( CAKE . 'Config' . DS . 'config.php' ); $this->assertSame(array_diff($expected, $result), array()); $this->assertSame(array_diff($expected, $result), array()); $result = $Folder->findRecursive('(config|paths)\.php', true); $expected = array( CAKE . 'Config' . DS . 'config.php' ); $this->assertSame($expected, $result); $Folder->cd(TMP); $Folder->create($Folder->pwd() . DS . 'testme'); $Folder->cd('testme'); $File = new File($Folder->pwd() . DS . 'paths.php'); $File->create(); $Folder->cd(TMP . 'sessions'); $result = $Folder->findRecursive('paths\.php'); $expected = array(); $this->assertSame($expected, $result); $Folder->cd(TMP . 'testme'); $File = new File($Folder->pwd() . DS . 'my.php'); $File->create(); $Folder->cd($Folder->pwd() . '/../..'); $result = $Folder->findRecursive('(paths|my)\.php'); $expected = array( TMP . 'testme' . DS . 'my.php', TMP . 'testme' . DS . 'paths.php' ); $this->assertSame(array_diff($expected, $result), array()); $this->assertSame(array_diff($expected, $result), array()); $result = $Folder->findRecursive('(paths|my)\.php', true); $expected = array( TMP . 'testme' . DS . 'my.php', TMP . 'testme' . DS . 'paths.php' ); $this->assertSame($expected, $result); $Folder->cd(CAKE . 'Config'); $Folder->cd(TMP); $Folder->delete($Folder->pwd() . DS . 'testme'); $File->delete(); } /** * testConstructWithNonExistentPath method * * @return void */ public function testConstructWithNonExistentPath() { $Folder = new Folder(TMP . 'config_non_existent', true); $this->assertTrue(is_dir(TMP . 'config_non_existent')); $Folder->cd(TMP); $Folder->delete($Folder->pwd() . 'config_non_existent'); } /** * testDirSize method * * @return void */ public function testDirSize() { $Folder = new Folder(TMP . 'config_non_existent', true); $this->assertEquals(0, $Folder->dirSize()); $File = new File($Folder->pwd() . DS . 'my.php', true, 0777); $File->create(); $File->write('something here'); $File->close(); $this->assertEquals(14, $Folder->dirSize()); $Folder->cd(TMP); $Folder->delete($Folder->pwd() . 'config_non_existent'); } /** * test that errors and messages can be resetted * * @return void */ public function testReset() { $path = TMP . 'folder_delete_test'; mkdir($path); $folder = $path . DS . 'sub'; mkdir($folder); $file = $folder . DS . 'file'; touch($file); chmod($folder, 0555); chmod($file, 0444); $Folder = new Folder($folder); $return = $Folder->delete(); $this->assertFalse($return); $messages = $Folder->messages(); $errors = $Folder->errors(); $expected = array( $file . ' NOT removed', $folder . ' NOT removed', ); sort($expected); sort($errors); $this->assertEmpty($messages); $this->assertEquals($expected, $errors); chmod($file, 0644); chmod($folder, 0755); $return = $Folder->delete(); $this->assertTrue($return); $messages = $Folder->messages(); $errors = $Folder->errors(); $expected = array( $file . ' removed', $folder . ' removed', ); sort($expected); sort($messages); $this->assertEmpty($errors); $this->assertEquals($expected, $messages); } /** * testDelete method * * @return void */ public function testDelete() { $path = TMP . 'folder_delete_test'; mkdir($path); touch($path . DS . 'file_1'); mkdir($path . DS . 'level_1_1'); touch($path . DS . 'level_1_1' . DS . 'file_1_1'); mkdir($path . DS . 'level_1_1' . DS . 'level_2_1'); touch($path . DS . 'level_1_1' . DS . 'level_2_1' . DS . 'file_2_1'); touch($path . DS . 'level_1_1' . DS . 'level_2_1' . DS . 'file_2_2'); mkdir($path . DS . 'level_1_1' . DS . 'level_2_2'); $Folder = new Folder($path, true); $return = $Folder->delete(); $this->assertTrue($return); $messages = $Folder->messages(); $errors = $Folder->errors(); $this->assertEquals(array(), $errors); $expected = array( $path . DS . 'file_1 removed', $path . DS . 'level_1_1' . DS . 'file_1_1 removed', $path . DS . 'level_1_1' . DS . 'level_2_1' . DS . 'file_2_1 removed', $path . DS . 'level_1_1' . DS . 'level_2_1' . DS . 'file_2_2 removed', $path . DS . 'level_1_1' . DS . 'level_2_1 removed', $path . DS . 'level_1_1' . DS . 'level_2_2 removed', $path . DS . 'level_1_1 removed', $path . ' removed' ); sort($expected); sort($messages); $this->assertEquals($expected, $messages); } /** * testCopy method * * Verify that subdirectories existing in both destination and source directory * are merged recursively. * * @return void */ public function testCopy() { extract($this->_setupFilesystem()); $Folder = new Folder($folderOne); $result = $Folder->copy($folderThree); $this->assertTrue($result); $this->assertTrue(file_exists($folderThree . DS . 'file1.php')); $this->assertTrue(file_exists($folderThree . DS . 'folderA' . DS . 'fileA.php')); $Folder = new Folder($folderTwo); $result = $Folder->copy($folderThree); $this->assertTrue($result); $this->assertTrue(file_exists($folderThree . DS . 'file1.php')); $this->assertTrue(file_exists($folderThree . DS . 'file2.php')); $this->assertTrue(file_exists($folderThree . DS . 'folderA' . DS . 'fileA.php')); $this->assertTrue(file_exists($folderThree . DS . 'folderB' . DS . 'fileB.php')); $Folder = new Folder($path); $Folder->delete(); } /** * testCopyWithMerge method * * Verify that subdirectories existing in both destination and source directory * are merged recursively. * * @return void */ public function testCopyWithMerge() { extract($this->_setupFilesystem()); $Folder = new Folder($folderOne); $result = $Folder->copy($folderThree); $this->assertTrue($result); $this->assertTrue(file_exists($folderThree . DS . 'file1.php')); $this->assertTrue(file_exists($folderThree . DS . 'folderA' . DS . 'fileA.php')); $Folder = new Folder($folderTwo); $result = $Folder->copy(array('to' => $folderThree, 'scheme' => Folder::MERGE)); $this->assertTrue($result); $this->assertTrue(file_exists($folderThree . DS . 'file1.php')); $this->assertTrue(file_exists($folderThree . DS . 'file2.php')); $this->assertTrue(file_exists($folderThree . DS . 'folderA' . DS . 'fileA.php')); $this->assertTrue(file_exists($folderThree . DS . 'folderB' . DS . 'fileB.php')); $Folder = new Folder($path); $Folder->delete(); } /** * testCopyWithSkip method * * Verify that directories and files are copied recursively * even if the destination directory already exists. * Subdirectories existing in both destination and source directory * are skipped and not merged or overwritten. * * @return void */ public function testCopyWithSkip() { extract($this->_setupFilesystem()); $Folder = new Folder($folderOne); $result = $Folder->copy(array('to' => $folderTwo, 'scheme' => Folder::SKIP)); $this->assertTrue($result); $this->assertTrue(file_exists($folderTwo . DS . 'file1.php')); $this->assertTrue(file_exists($folderTwo . DS . 'folderA' . DS . 'fileA.php')); $Folder = new Folder($folderTwo); $Folder->delete(); $Folder = new Folder($folderOne); $result = $Folder->copy(array('to' => $folderTwo, 'scheme' => Folder::SKIP)); $this->assertTrue($result); $this->assertTrue(file_exists($folderTwo . DS . 'file1.php')); $this->assertTrue(file_exists($folderTwo . DS . 'folderA' . DS . 'fileA.php')); $Folder = new Folder($folderTwo); $Folder->delete(); new Folder($folderTwo, true); new Folder($folderTwo . DS . 'folderB', true); file_put_contents($folderTwo . DS . 'file2.php', 'touched'); file_put_contents($folderTwo . DS . 'folderB' . DS . 'fileB.php', 'untouched'); $Folder = new Folder($folderTwo); $result = $Folder->copy(array('to' => $folderThree, 'scheme' => Folder::SKIP)); $this->assertTrue($result); $this->assertTrue(file_exists($folderThree . DS . 'file2.php')); $this->assertEquals('touched', file_get_contents($folderThree . DS . 'file2.php')); $this->assertEquals('untouched', file_get_contents($folderThree . DS . 'folderB' . DS . 'fileB.php')); $Folder = new Folder($path); $Folder->delete(); } /** * Test that SKIP mode skips files too. * * @return void */ public function testCopyWithSkipFileSkipped() { $path = TMP . 'folder_test'; $folderOne = $path . DS . 'folder1'; $folderTwo = $path . DS . 'folder2'; new Folder($path, true); new Folder($folderOne, true); new Folder($folderTwo, true); file_put_contents($folderOne . DS . 'fileA.txt', 'Folder One File'); file_put_contents($folderTwo . DS . 'fileA.txt', 'Folder Two File'); $Folder = new Folder($folderOne); $result = $Folder->copy(array('to' => $folderTwo, 'scheme' => Folder::SKIP)); $this->assertTrue($result); $this->assertEquals('Folder Two File', file_get_contents($folderTwo . DS . 'fileA.txt')); } /** * testCopyWithOverwrite * * Verify that subdirectories existing in both destination and source directory * are overwritten/replaced recursively. * * @return void */ public function testCopyWithOverwrite() { extract($this->_setupFilesystem()); $Folder = new Folder($folderOne); $Folder->copy(array('to' => $folderThree, 'scheme' => Folder::OVERWRITE)); $this->assertTrue(file_exists($folderThree . DS . 'file1.php')); $this->assertTrue(file_exists($folderThree . DS . 'folderA' . DS . 'fileA.php')); $Folder = new Folder($folderTwo); $result = $Folder->copy(array('to' => $folderThree, 'scheme' => Folder::OVERWRITE)); $this->assertTrue($result); $this->assertTrue(file_exists($folderThree . DS . 'folderA' . DS . 'fileA.php')); $Folder = new Folder($folderOne); unlink($fileOneA); $result = $Folder->copy(array('to' => $folderThree, 'scheme' => Folder::OVERWRITE)); $this->assertTrue($result); $this->assertTrue(file_exists($folderThree . DS . 'file1.php')); $this->assertTrue(file_exists($folderThree . DS . 'file2.php')); $this->assertTrue(!file_exists($folderThree . DS . 'folderA' . DS . 'fileA.php')); $this->assertTrue(file_exists($folderThree . DS . 'folderB' . DS . 'fileB.php')); $Folder = new Folder($path); $Folder->delete(); } /** * Setup filesystem for copy tests * $path: folder_test/ * - folder1/file1.php * - folder1/folderA/fileA.php * - folder2/file2.php * - folder2/folderB/fileB.php * - folder3/ * * @return array Filenames to extract in the test methods */ protected function _setupFilesystem() { $path = TMP . 'folder_test'; $folderOne = $path . DS . 'folder1'; $folderOneA = $folderOne . DS . 'folderA'; $folderTwo = $path . DS . 'folder2'; $folderTwoB = $folderTwo . DS . 'folderB'; $folderThree = $path . DS . 'folder3'; $fileOne = $folderOne . DS . 'file1.php'; $fileTwo = $folderTwo . DS . 'file2.php'; $fileOneA = $folderOneA . DS . 'fileA.php'; $fileTwoB = $folderTwoB . DS . 'fileB.php'; new Folder($path, true); new Folder($folderOne, true); new Folder($folderOneA, true); new Folder($folderTwo, true); new Folder($folderTwoB, true); new Folder($folderThree, true); touch($fileOne); touch($fileTwo); touch($fileOneA); touch($fileTwoB); return compact( 'path', 'folderOne', 'folderOneA', 'folderTwo', 'folderTwoB', 'folderThree', 'fileOne', 'fileOneA', 'fileTwo', 'fileTwoB'); } /** * testMove method * * Verify that directories and files are moved recursively * even if the destination directory already exists. * Subdirectories existing in both destination and source directory * are merged recursively. * * @return void */ public function testMove() { extract($this->_setupFilesystem()); $Folder = new Folder($folderOne); $result = $Folder->move($folderTwo); $this->assertTrue($result); $this->assertTrue(file_exists($folderTwo . DS . 'file1.php')); $this->assertTrue(is_dir($folderTwo . DS . 'folderB')); $this->assertTrue(file_exists($folderTwo . DS . 'folderB' . DS . 'fileB.php')); $this->assertFalse(file_exists($fileOne)); $this->assertTrue(file_exists($folderTwo . DS . 'folderA')); $this->assertFalse(file_exists($folderOneA)); $this->assertFalse(file_exists($fileOneA)); $Folder = new Folder($folderTwo); $Folder->delete(); new Folder($folderOne, true); new Folder($folderOneA, true); touch($fileOne); touch($fileOneA); $Folder = new Folder($folderOne); $result = $Folder->move($folderTwo); $this->assertTrue($result); $this->assertTrue(file_exists($folderTwo . DS . 'file1.php')); $this->assertTrue(is_dir($folderTwo . DS . 'folderA')); $this->assertTrue(file_exists($folderTwo . DS . 'folderA' . DS . 'fileA.php')); $this->assertFalse(file_exists($fileOne)); $this->assertFalse(file_exists($folderOneA)); $this->assertFalse(file_exists($fileOneA)); $Folder = new Folder($folderTwo); $Folder->delete(); new Folder($folderOne, true); new Folder($folderOneA, true); new Folder($folderTwo, true); new Folder($folderTwoB, true); touch($fileOne); touch($fileOneA); new Folder($folderOne . DS . 'folderB', true); touch($folderOne . DS . 'folderB' . DS . 'fileB.php'); file_put_contents($folderTwoB . DS . 'fileB.php', 'untouched'); $Folder = new Folder($folderOne); $result = $Folder->move($folderTwo); $this->assertTrue($result); $this->assertTrue(file_exists($folderTwo . DS . 'file1.php')); $this->assertEquals('', file_get_contents($folderTwoB . DS . 'fileB.php')); $this->assertFalse(file_exists($fileOne)); $this->assertFalse(file_exists($folderOneA)); $this->assertFalse(file_exists($fileOneA)); $Folder = new Folder($path); $Folder->delete(); } /** * testMoveWithSkip method * * Verify that directories and files are moved recursively * even if the destination directory already exists. * Subdirectories existing in both destination and source directory * are skipped and not merged or overwritten. * * @return void */ public function testMoveWithSkip() { extract($this->_setupFilesystem()); $Folder = new Folder($folderOne); $result = $Folder->move(array('to' => $folderTwo, 'scheme' => Folder::SKIP)); $this->assertTrue($result); $this->assertTrue(file_exists($folderTwo . DS . 'file1.php')); $this->assertTrue(is_dir($folderTwo . DS . 'folderB')); $this->assertTrue(file_exists($folderTwoB . DS . 'fileB.php')); $this->assertFalse(file_exists($fileOne)); $this->assertFalse(file_exists($folderOneA)); $this->assertFalse(file_exists($fileOneA)); $Folder = new Folder($folderTwo); $Folder->delete(); new Folder($folderOne, true); new Folder($folderOneA, true); new Folder($folderTwo, true); touch($fileOne); touch($fileOneA); $Folder = new Folder($folderOne); $result = $Folder->move(array('to' => $folderTwo, 'scheme' => Folder::SKIP)); $this->assertTrue($result); $this->assertTrue(file_exists($folderTwo . DS . 'file1.php')); $this->assertTrue(is_dir($folderTwo . DS . 'folderA')); $this->assertTrue(file_exists($folderTwo . DS . 'folderA' . DS . 'fileA.php')); $this->assertFalse(file_exists($fileOne)); $this->assertFalse(file_exists($folderOneA)); $this->assertFalse(file_exists($fileOneA)); $Folder = new Folder($folderTwo); $Folder->delete(); new Folder($folderOne, true); new Folder($folderOneA, true); new Folder($folderTwo, true); new Folder($folderTwoB, true); touch($fileOne); touch($fileOneA); file_put_contents($folderTwoB . DS . 'fileB.php', 'untouched'); $Folder = new Folder($folderOne); $result = $Folder->move(array('to' => $folderTwo, 'scheme' => Folder::SKIP)); $this->assertTrue($result); $this->assertTrue(file_exists($folderTwo . DS . 'file1.php')); $this->assertEquals('untouched', file_get_contents($folderTwoB . DS . 'fileB.php')); $this->assertFalse(file_exists($fileOne)); $this->assertFalse(file_exists($folderOneA)); $this->assertFalse(file_exists($fileOneA)); $Folder = new Folder($path); $Folder->delete(); } } cakephp-2.8.0/lib/Cake/Test/Case/Utility/HashTest.php000066400000000000000000002123221265552240500222460ustar00rootroot00000000000000 array( 'id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body' ), 'User' => array( 'id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', ), 'Comment' => array( array( 'id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', ), array( 'id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', ), ), 'Tag' => array( array( 'id' => '1', 'tag' => 'tag1', ), array( 'id' => '2', 'tag' => 'tag2', ) ), 'Deep' => array( 'Nesting' => array( 'test' => array( 1 => 'foo', 2 => array( 'and' => array('more' => 'stuff') ) ) ) ) ), array( 'Article' => array( 'id' => '2', 'user_id' => '1', 'title' => 'Second Article', 'body' => 'Second Article Body', 'published' => 'Y', ), 'User' => array( 'id' => '2', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', ), 'Comment' => array(), 'Tag' => array() ), array( 'Article' => array( 'id' => '3', 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', ), 'User' => array( 'id' => '3', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', ), 'Comment' => array(), 'Tag' => array() ), array( 'Article' => array( 'id' => '4', 'user_id' => '1', 'title' => 'Fourth Article', 'body' => 'Fourth Article Body', ), 'User' => array( 'id' => '4', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', ), 'Comment' => array(), 'Tag' => array() ), array( 'Article' => array( 'id' => '5', 'user_id' => '1', 'title' => 'Fifth Article', 'body' => 'Fifth Article Body', ), 'User' => array( 'id' => '5', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', ), 'Comment' => array(), 'Tag' => array() ) ); } /** * Data provider * * @return array */ public static function userData() { return array( array( 'User' => array( 'id' => 2, 'group_id' => 1, 'Data' => array( 'user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias' ) ) ), array( 'User' => array( 'id' => 14, 'group_id' => 2, 'Data' => array( 'user' => 'phpnut', 'name' => 'Larry E. Masters' ) ) ), array( 'User' => array( 'id' => 25, 'group_id' => 1, 'Data' => array( 'user' => 'gwoo', 'name' => 'The Gwoo' ) ) ) ); } /** * Test get() * * @return void */ public function testGet() { $data = array('abc', 'def'); $result = Hash::get($data, '0'); $this->assertEquals('abc', $result); $result = Hash::get($data, 0); $this->assertEquals('abc', $result); $result = Hash::get($data, '1'); $this->assertEquals('def', $result); $data = static::articleData(); $result = Hash::get(array(), '1.Article.title'); $this->assertNull($result); $result = Hash::get($data, ''); $this->assertNull($result); $result = Hash::get($data, '0.Article.title'); $this->assertEquals('First Article', $result); $result = Hash::get($data, '1.Article.title'); $this->assertEquals('Second Article', $result); $result = Hash::get($data, '5.Article.title'); $this->assertNull($result); $default = array('empty'); $this->assertEquals($default, Hash::get($data, '5.Article.title', $default)); $this->assertEquals($default, Hash::get(array(), '5.Article.title', $default)); $result = Hash::get($data, '1.Article.title.not_there'); $this->assertNull($result); $result = Hash::get($data, '1.Article'); $this->assertEquals($data[1]['Article'], $result); $result = Hash::get($data, array('1', 'Article')); $this->assertEquals($data[1]['Article'], $result); } /** * Test get() with an invalid path * * @expectedException InvalidArgumentException * @return void */ public function testGetInvalidPath() { Hash::get(array('one' => 'two'), true); } /** * Test testGetNullPath() * * @return void */ public function testGetNullPath() { $result = Hash::get(array('one' => 'two'), null, '-'); $this->assertEquals('-', $result); $result = Hash::get(array('one' => 'two'), '', '-'); $this->assertEquals('-', $result); } /** * Test dimensions. * * @return void */ public function testDimensions() { $result = Hash::dimensions(array()); $this->assertEquals($result, 0); $data = array('one', '2', 'three'); $result = Hash::dimensions($data); $this->assertEquals($result, 1); $data = array('1' => '1.1', '2', '3'); $result = Hash::dimensions($data); $this->assertEquals($result, 1); $data = array('1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => '3.1.1')); $result = Hash::dimensions($data); $this->assertEquals($result, 2); $data = array('1' => '1.1', '2', '3' => array('3.1' => '3.1.1')); $result = Hash::dimensions($data); $this->assertEquals($result, 1); $data = array('1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => array('3.1.1' => '3.1.1.1'))); $result = Hash::dimensions($data); $this->assertEquals($result, 2); } /** * Test maxDimensions * * @return void */ public function testMaxDimensions() { $data = array(); $result = Hash::maxDimensions($data); $this->assertEquals(0, $result); $data = array('a', 'b'); $result = Hash::maxDimensions($data); $this->assertEquals(1, $result); $data = array('1' => '1.1', '2', '3' => array('3.1' => '3.1.1')); $result = Hash::maxDimensions($data); $this->assertEquals($result, 2); $data = array( '1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => array('3.1.1' => '3.1.1.1')) ); $result = Hash::maxDimensions($data); $this->assertEquals($result, 3); $data = array( '1' => array( '1.1' => '1.1.1', '1.2' => array( '1.2.1' => array( '1.2.1.1', array('1.2.2.1') ) ) ), '2' => array('2.1' => '2.1.1') ); $result = Hash::maxDimensions($data); $this->assertEquals($result, 5); } /** * Tests Hash::flatten * * @return void */ public function testFlatten() { $data = array('Larry', 'Curly', 'Moe'); $result = Hash::flatten($data); $this->assertEquals($result, $data); $data[9] = 'Shemp'; $result = Hash::flatten($data); $this->assertEquals($result, $data); $data = array( array( 'Post' => array('id' => '1', 'author_id' => '1', 'title' => 'First Post'), 'Author' => array('id' => '1', 'user' => 'nate', 'password' => 'foo'), ), array( 'Post' => array('id' => '2', 'author_id' => '3', 'title' => 'Second Post', 'body' => 'Second Post Body'), 'Author' => array('id' => '3', 'user' => 'larry', 'password' => null), ) ); $result = Hash::flatten($data); $expected = array( '0.Post.id' => '1', '0.Post.author_id' => '1', '0.Post.title' => 'First Post', '0.Author.id' => '1', '0.Author.user' => 'nate', '0.Author.password' => 'foo', '1.Post.id' => '2', '1.Post.author_id' => '3', '1.Post.title' => 'Second Post', '1.Post.body' => 'Second Post Body', '1.Author.id' => '3', '1.Author.user' => 'larry', '1.Author.password' => null ); $this->assertEquals($expected, $result); $data = array( array( 'Post' => array('id' => '1', 'author_id' => null, 'title' => 'First Post'), 'Author' => array(), ) ); $result = Hash::flatten($data); $expected = array( '0.Post.id' => '1', '0.Post.author_id' => null, '0.Post.title' => 'First Post', '0.Author' => array() ); $this->assertEquals($expected, $result); $data = array( array('Post' => array('id' => 1)), array('Post' => array('id' => 2)), ); $result = Hash::flatten($data, '/'); $expected = array( '0/Post/id' => '1', '1/Post/id' => '2', ); $this->assertEquals($expected, $result); } /** * Test diff(); * * @return void */ public function testDiff() { $a = array( 0 => array('name' => 'main'), 1 => array('name' => 'about') ); $b = array( 0 => array('name' => 'main'), 1 => array('name' => 'about'), 2 => array('name' => 'contact') ); $result = Hash::diff($a, array()); $expected = $a; $this->assertEquals($expected, $result); $result = Hash::diff(array(), $b); $expected = $b; $this->assertEquals($expected, $result); $result = Hash::diff($a, $b); $expected = array( 2 => array('name' => 'contact') ); $this->assertEquals($expected, $result); $b = array( 0 => array('name' => 'me'), 1 => array('name' => 'about') ); $result = Hash::diff($a, $b); $expected = array( 0 => array('name' => 'main') ); $this->assertEquals($expected, $result); $a = array(); $b = array('name' => 'bob', 'address' => 'home'); $result = Hash::diff($a, $b); $this->assertEquals($result, $b); $a = array('name' => 'bob', 'address' => 'home'); $b = array(); $result = Hash::diff($a, $b); $this->assertEquals($result, $a); $a = array('key' => true, 'another' => false, 'name' => 'me'); $b = array('key' => 1, 'another' => 0); $expected = array('name' => 'me'); $result = Hash::diff($a, $b); $this->assertEquals($expected, $result); $a = array('key' => 'value', 'another' => null, 'name' => 'me'); $b = array('key' => 'differentValue', 'another' => null); $expected = array('key' => 'value', 'name' => 'me'); $result = Hash::diff($a, $b); $this->assertEquals($expected, $result); $a = array('key' => 'value', 'another' => null, 'name' => 'me'); $b = array('key' => 'differentValue', 'another' => 'value'); $expected = array('key' => 'value', 'another' => null, 'name' => 'me'); $result = Hash::diff($a, $b); $this->assertEquals($expected, $result); $a = array('key' => 'value', 'another' => null, 'name' => 'me'); $b = array('key' => 'differentValue', 'another' => 'value'); $expected = array('key' => 'differentValue', 'another' => 'value', 'name' => 'me'); $result = Hash::diff($b, $a); $this->assertEquals($expected, $result); $a = array('key' => 'value', 'another' => null, 'name' => 'me'); $b = array(0 => 'differentValue', 1 => 'value'); $expected = $a + $b; $result = Hash::diff($a, $b); $this->assertEquals($expected, $result); } /** * Test merge() * * @return void */ public function testMerge() { $result = Hash::merge(array('foo'), array('bar')); $this->assertEquals($result, array('foo', 'bar')); $result = Hash::merge(array('foo'), array('user' => 'bob', 'no-bar'), 'bar'); $this->assertEquals($result, array('foo', 'user' => 'bob', 'no-bar', 'bar')); $a = array('foo', 'foo2'); $b = array('bar', 'bar2'); $expected = array('foo', 'foo2', 'bar', 'bar2'); $this->assertEquals($expected, Hash::merge($a, $b)); $a = array('foo' => 'bar', 'bar' => 'foo'); $b = array('foo' => 'no-bar', 'bar' => 'no-foo'); $expected = array('foo' => 'no-bar', 'bar' => 'no-foo'); $this->assertEquals($expected, Hash::merge($a, $b)); $a = array('users' => array('bob', 'jim')); $b = array('users' => array('lisa', 'tina')); $expected = array('users' => array('bob', 'jim', 'lisa', 'tina')); $this->assertEquals($expected, Hash::merge($a, $b)); $a = array('users' => array('jim', 'bob')); $b = array('users' => 'none'); $expected = array('users' => 'none'); $this->assertEquals($expected, Hash::merge($a, $b)); $a = array('users' => array('lisa' => array('id' => 5, 'pw' => 'secret')), 'cakephp'); $b = array('users' => array('lisa' => array('pw' => 'new-pass', 'age' => 23)), 'ice-cream'); $expected = array( 'users' => array('lisa' => array('id' => 5, 'pw' => 'new-pass', 'age' => 23)), 'cakephp', 'ice-cream' ); $result = Hash::merge($a, $b); $this->assertEquals($expected, $result); $c = array( 'users' => array('lisa' => array('pw' => 'you-will-never-guess', 'age' => 25, 'pet' => 'dog')), 'chocolate' ); $expected = array( 'users' => array('lisa' => array('id' => 5, 'pw' => 'you-will-never-guess', 'age' => 25, 'pet' => 'dog')), 'cakephp', 'ice-cream', 'chocolate' ); $this->assertEquals($expected, Hash::merge($a, $b, $c)); $this->assertEquals($expected, Hash::merge($a, $b, array(), $c)); $a = array( 'Tree', 'CounterCache', 'Upload' => array( 'folder' => 'products', 'fields' => array('image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id') ) ); $b = array( 'Cacheable' => array('enabled' => false), 'Limit', 'Bindable', 'Validator', 'Transactional' ); $expected = array( 'Tree', 'CounterCache', 'Upload' => array( 'folder' => 'products', 'fields' => array('image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id') ), 'Cacheable' => array('enabled' => false), 'Limit', 'Bindable', 'Validator', 'Transactional' ); $this->assertEquals($expected, Hash::merge($a, $b)); } /** * test normalizing arrays * * @return void */ public function testNormalize() { $result = Hash::normalize(array('one', 'two', 'three')); $expected = array('one' => null, 'two' => null, 'three' => null); $this->assertEquals($expected, $result); $result = Hash::normalize(array('one', 'two', 'three'), false); $expected = array('one', 'two', 'three'); $this->assertEquals($expected, $result); $result = Hash::normalize(array('one' => 1, 'two' => 2, 'three' => 3, 'four'), false); $expected = array('one' => 1, 'two' => 2, 'three' => 3, 'four' => null); $this->assertEquals($expected, $result); $result = Hash::normalize(array('one' => 1, 'two' => 2, 'three' => 3, 'four')); $expected = array('one' => 1, 'two' => 2, 'three' => 3, 'four' => null); $this->assertEquals($expected, $result); $result = Hash::normalize(array('one' => array('a', 'b', 'c' => 'cee'), 'two' => 2, 'three')); $expected = array('one' => array('a', 'b', 'c' => 'cee'), 'two' => 2, 'three' => null); $this->assertEquals($expected, $result); } /** * testContains method * * @return void */ public function testContains() { $data = array('apple', 'bee', 'cyclops'); $this->assertTrue(Hash::contains($data, array('apple'))); $this->assertFalse(Hash::contains($data, array('data'))); $a = array( 0 => array('name' => 'main'), 1 => array('name' => 'about') ); $b = array( 0 => array('name' => 'main'), 1 => array('name' => 'about'), 2 => array('name' => 'contact'), 'a' => 'b' ); $this->assertTrue(Hash::contains($a, $a)); $this->assertFalse(Hash::contains($a, $b)); $this->assertTrue(Hash::contains($b, $a)); $a = array( array('User' => array('id' => 1)), array('User' => array('id' => 2)), ); $b = array( array('User' => array('id' => 1)), array('User' => array('id' => 2)), array('User' => array('id' => 3)) ); $this->assertTrue(Hash::contains($b, $a)); $this->assertFalse(Hash::contains($a, $b)); $a = array(0 => 'test', 'string' => null); $this->assertTrue(Hash::contains($a, array('string' => null))); $a = array(0 => 'test', 'string' => null); $this->assertTrue(Hash::contains($a, array('test'))); } /** * testFilter method * * @return void */ public function testFilter() { $result = Hash::filter(array('0', false, true, 0, array('one thing', 'I can tell you', 'is you got to be', false))); $expected = array('0', 2 => true, 3 => 0, 4 => array('one thing', 'I can tell you', 'is you got to be')); $this->assertSame($expected, $result); $result = Hash::filter(array(1, array(false))); $expected = array(1); $this->assertEquals($expected, $result); $result = Hash::filter(array(1, array(false, false))); $expected = array(1); $this->assertEquals($expected, $result); $result = Hash::filter(array(1, array('empty', false))); $expected = array(1, array('empty')); $this->assertEquals($expected, $result); $result = Hash::filter(array(1, array('2', false, array(3, null)))); $expected = array(1, array('2', 2 => array(3))); $this->assertEquals($expected, $result); $this->assertSame(array(), Hash::filter(array())); } /** * testNumericArrayCheck method * * @return void */ public function testNumeric() { $data = array('one'); $this->assertTrue(Hash::numeric(array_keys($data))); $data = array(1 => 'one'); $this->assertFalse(Hash::numeric($data)); $data = array('one'); $this->assertFalse(Hash::numeric($data)); $data = array('one' => 'two'); $this->assertFalse(Hash::numeric($data)); $data = array('one' => 1); $this->assertTrue(Hash::numeric($data)); $data = array(0); $this->assertTrue(Hash::numeric($data)); $data = array('one', 'two', 'three', 'four', 'five'); $this->assertTrue(Hash::numeric(array_keys($data))); $data = array(1 => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five'); $this->assertTrue(Hash::numeric(array_keys($data))); $data = array('1' => 'one', 2 => 'two', 3 => 'three', 4 => 'four', 5 => 'five'); $this->assertTrue(Hash::numeric(array_keys($data))); $data = array('one', 2 => 'two', 3 => 'three', 4 => 'four', 'a' => 'five'); $this->assertFalse(Hash::numeric(array_keys($data))); $data = array(2.4, 1, 0, -1, -2); $this->assertTrue(Hash::numeric($data)); } /** * Test simple paths. * * @return void */ public function testExtractBasic() { $data = static::articleData(); $result = Hash::extract($data, ''); $this->assertEquals($data, $result); $result = Hash::extract($data, '0.Article.title'); $this->assertEquals(array('First Article'), $result); $result = Hash::extract($data, '1.Article.title'); $this->assertEquals(array('Second Article'), $result); $result = Hash::extract(array(false), '{n}.Something.another_thing'); $this->assertEquals(array(), $result); } /** * Test the {n} selector * * @return void */ public function testExtractNumericKey() { $data = static::articleData(); $result = Hash::extract($data, '{n}.Article.title'); $expected = array( 'First Article', 'Second Article', 'Third Article', 'Fourth Article', 'Fifth Article' ); $this->assertEquals($expected, $result); $result = Hash::extract($data, '0.Comment.{n}.user_id'); $expected = array( '2', '4' ); $this->assertEquals($expected, $result); } /** * Test the {n} selector with inconsistent arrays * * @return void */ public function testExtractNumericMixedKeys() { $data = array( 'User' => array( 0 => array( 'id' => 4, 'name' => 'Neo' ), 1 => array( 'id' => 5, 'name' => 'Morpheus' ), 'stringKey' => array( 'name' => 'Fail' ) ) ); $result = Hash::extract($data, 'User.{n}.name'); $expected = array('Neo', 'Morpheus'); $this->assertEquals($expected, $result); } /** * Test the {n} selector with non-zero based arrays * * @return void */ public function testExtractNumericNonZero() { $data = array( 1 => array( 'User' => array( 'id' => 1, 'name' => 'John', ) ), 2 => array( 'User' => array( 'id' => 2, 'name' => 'Bob', ) ), 3 => array( 'User' => array( 'id' => 3, 'name' => 'Tony', ) ) ); $result = Hash::extract($data, '{n}.User.name'); $expected = array('John', 'Bob', 'Tony'); $this->assertEquals($expected, $result); } /** * Test the {s} selector. * * @return void */ public function testExtractStringKey() { $data = static::articleData(); $result = Hash::extract($data, '{n}.{s}.user'); $expected = array( 'mariano', 'mariano', 'mariano', 'mariano', 'mariano' ); $this->assertEquals($expected, $result); $result = Hash::extract($data, '{n}.{s}.Nesting.test.1'); $this->assertEquals(array('foo'), $result); } /** * Test wildcard matcher * * @return void */ public function testExtractWildcard() { $data = array( '02000009C5560001' => array('name' => 'Mr. Alphanumeric'), '2300000918020101' => array('name' => 'Mr. Numeric'), '390000096AB30001' => array('name' => 'Mrs. Alphanumeric'), 'stuff' => array('name' => 'Ms. Word'), 123 => array('name' => 'Mr. Number'), true => array('name' => 'Ms. Bool'), ); $result = Hash::extract($data, '{*}.name'); $expected = array( 'Mr. Alphanumeric', 'Mr. Numeric', 'Mrs. Alphanumeric', 'Ms. Word', 'Mr. Number', 'Ms. Bool', ); $this->assertEquals($expected, $result); } /** * Test the attribute presense selector. * * @return void */ public function testExtractAttributePresence() { $data = static::articleData(); $result = Hash::extract($data, '{n}.Article[published]'); $expected = array($data[1]['Article']); $this->assertEquals($expected, $result); $result = Hash::extract($data, '{n}.Article[id][published]'); $expected = array($data[1]['Article']); $this->assertEquals($expected, $result); } /** * Test = and != operators. * * @return void */ public function testExtractAttributeEquality() { $data = static::articleData(); $result = Hash::extract($data, '{n}.Article[id=3]'); $expected = array($data[2]['Article']); $this->assertEquals($expected, $result); $result = Hash::extract($data, '{n}.Article[id = 3]'); $expected = array($data[2]['Article']); $this->assertEquals($expected, $result, 'Whitespace should not matter.'); $result = Hash::extract($data, '{n}.Article[id!=3]'); $this->assertEquals(1, $result[0]['id']); $this->assertEquals(2, $result[1]['id']); $this->assertEquals(4, $result[2]['id']); $this->assertEquals(5, $result[3]['id']); } /** * Test extracting based on attributes with boolean values. * * @return void */ public function testExtractAttributeBoolean() { $users = array( array( 'id' => 2, 'username' => 'johndoe', 'active' => true ), array( 'id' => 5, 'username' => 'kevin', 'active' => true ), array( 'id' => 9, 'username' => 'samantha', 'active' => false ), ); $result = Hash::extract($users, '{n}[active=0]'); $this->assertCount(1, $result); $this->assertEquals($users[2], $result[0]); $result = Hash::extract($users, '{n}[active=false]'); $this->assertCount(1, $result); $this->assertEquals($users[2], $result[0]); $result = Hash::extract($users, '{n}[active=1]'); $this->assertCount(2, $result); $this->assertEquals($users[0], $result[0]); $this->assertEquals($users[1], $result[1]); $result = Hash::extract($users, '{n}[active=true]'); $this->assertCount(2, $result); $this->assertEquals($users[0], $result[0]); $this->assertEquals($users[1], $result[1]); } /** * Test that attribute matchers don't cause errors on scalar data. * * @return void */ public function testExtractAttributeEqualityOnScalarValue() { $data = array( 'Entity' => array( 'id' => 1, 'data1' => 'value', ) ); $result = Hash::extract($data, 'Entity[id=1].data1'); $this->assertEquals(array('value'), $result); $data = array('Entity' => false ); $result = Hash::extract($data, 'Entity[id=1].data1'); $this->assertEquals(array(), $result); } /** * Test comparison operators. * * @return void */ public function testExtractAttributeComparison() { $data = static::articleData(); $result = Hash::extract($data, '{n}.Comment.{n}[user_id > 2]'); $expected = array($data[0]['Comment'][1]); $this->assertEquals($expected, $result); $this->assertEquals(4, $expected[0]['user_id']); $result = Hash::extract($data, '{n}.Comment.{n}[user_id >= 4]'); $expected = array($data[0]['Comment'][1]); $this->assertEquals($expected, $result); $this->assertEquals(4, $expected[0]['user_id']); $result = Hash::extract($data, '{n}.Comment.{n}[user_id < 3]'); $expected = array($data[0]['Comment'][0]); $this->assertEquals($expected, $result); $this->assertEquals(2, $expected[0]['user_id']); $result = Hash::extract($data, '{n}.Comment.{n}[user_id <= 2]'); $expected = array($data[0]['Comment'][0]); $this->assertEquals($expected, $result); $this->assertEquals(2, $expected[0]['user_id']); } /** * Test multiple attributes with conditions. * * @return void */ public function testExtractAttributeMultiple() { $data = static::articleData(); $result = Hash::extract($data, '{n}.Comment.{n}[user_id > 2][id=1]'); $this->assertEmpty($result); $result = Hash::extract($data, '{n}.Comment.{n}[user_id > 2][id=2]'); $expected = array($data[0]['Comment'][1]); $this->assertEquals($expected, $result); $this->assertEquals(4, $expected[0]['user_id']); } /** * Test attribute pattern matching. * * @return void */ public function testExtractAttributePattern() { $data = static::articleData(); $result = Hash::extract($data, '{n}.Article[title=/^First/]'); $expected = array($data[0]['Article']); $this->assertEquals($expected, $result); $result = Hash::extract($data, '{n}.Article[title=/^Fir[a-z]+/]'); $expected = array($data[0]['Article']); $this->assertEquals($expected, $result); } /** * Test that extract() + matching can hit null things. * * @return void */ public function testExtractMatchesNull() { $data = array( 'Country' => array( array('name' => 'Canada'), array('name' => 'Australia'), array('name' => null), ) ); $result = Hash::extract($data, 'Country.{n}[name=/Canada|^$/]'); $expected = array( array( 'name' => 'Canada', ), array( 'name' => null, ), ); $this->assertEquals($expected, $result); } /** * Test that uneven keys are handled correctly. * * @return void */ public function testExtractUnevenKeys() { $data = array( 'Level1' => array( 'Level2' => array('test1', 'test2'), 'Level2bis' => array('test3', 'test4') ) ); $this->assertEquals( array('test1', 'test2'), Hash::extract($data, 'Level1.Level2') ); $this->assertEquals( array('test3', 'test4'), Hash::extract($data, 'Level1.Level2bis') ); $data = array( 'Level1' => array( 'Level2bis' => array( array('test3', 'test4'), array('test5', 'test6') ) ) ); $expected = array( array('test3', 'test4'), array('test5', 'test6') ); $this->assertEquals($expected, Hash::extract($data, 'Level1.Level2bis')); $data['Level1']['Level2'] = array('test1', 'test2'); $this->assertEquals($expected, Hash::extract($data, 'Level1.Level2bis')); } /** * testSort method * * @return void */ public function testSort() { $result = Hash::sort(array(), '{n}.name'); $this->assertEquals(array(), $result); $a = array( 0 => array( 'Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate')) ), 1 => array( 'Person' => array('name' => 'Tracy'), 'Friend' => array(array('name' => 'Lindsay')) ) ); $b = array( 0 => array( 'Person' => array('name' => 'Tracy'), 'Friend' => array(array('name' => 'Lindsay')) ), 1 => array( 'Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate')) ) ); $a = Hash::sort($a, '{n}.Friend.{n}.name'); $this->assertEquals($a, $b); $b = array( 0 => array( 'Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate')) ), 1 => array( 'Person' => array('name' => 'Tracy'), 'Friend' => array(array('name' => 'Lindsay')) ) ); $a = array( 0 => array( 'Person' => array('name' => 'Tracy'), 'Friend' => array(array('name' => 'Lindsay')) ), 1 => array( 'Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate')) ) ); $a = Hash::sort($a, '{n}.Friend.{n}.name', 'desc'); $this->assertEquals($a, $b); $a = array( 0 => array( 'Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate')) ), 1 => array( 'Person' => array('name' => 'Tracy'), 'Friend' => array(array('name' => 'Lindsay')) ), 2 => array( 'Person' => array('name' => 'Adam'), 'Friend' => array(array('name' => 'Bob')) ) ); $b = array( 0 => array( 'Person' => array('name' => 'Adam'), 'Friend' => array(array('name' => 'Bob')) ), 1 => array( 'Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate')) ), 2 => array( 'Person' => array('name' => 'Tracy'), 'Friend' => array(array('name' => 'Lindsay')) ) ); $a = Hash::sort($a, '{n}.Person.name', 'asc'); $this->assertEquals($a, $b); $a = array( 0 => array('Person' => array('name' => 'Jeff')), 1 => array('Shirt' => array('color' => 'black')) ); $b = array( 0 => array('Shirt' => array('color' => 'black')), 1 => array('Person' => array('name' => 'Jeff')), ); $a = Hash::sort($a, '{n}.Person.name', 'ASC', 'STRING'); $this->assertSame($a, $b); $names = array( array('employees' => array( array('name' => array('first' => 'John', 'last' => 'Doe'))) ), array('employees' => array( array('name' => array('first' => 'Jane', 'last' => 'Doe'))) ), array('employees' => array(array('name' => array()))), array('employees' => array(array('name' => array()))) ); $result = Hash::sort($names, '{n}.employees.0.name', 'asc'); $expected = array( array('employees' => array( array('name' => array('first' => 'John', 'last' => 'Doe'))) ), array('employees' => array( array('name' => array('first' => 'Jane', 'last' => 'Doe'))) ), array('employees' => array(array('name' => array()))), array('employees' => array(array('name' => array()))) ); $this->assertSame($expected, $result); $a = array( 'SU' => array( 'total_fulfillable' => 2 ), 'AA' => array( 'total_fulfillable' => 1 ), 'LX' => array( 'total_fulfillable' => 0 ), 'BL' => array( 'total_fulfillable' => 3 ), ); $expected = array( 'LX' => array( 'total_fulfillable' => 0 ), 'AA' => array( 'total_fulfillable' => 1 ), 'SU' => array( 'total_fulfillable' => 2 ), 'BL' => array( 'total_fulfillable' => 3 ), ); $result = Hash::sort($a, '{s}.total_fulfillable', 'asc'); $this->assertSame($expected, $result); } /** * Test sort() with numeric option. * * @return void */ public function testSortNumeric() { $items = array( array('Item' => array('price' => '155,000')), array('Item' => array('price' => '139,000')), array('Item' => array('price' => '275,622')), array('Item' => array('price' => '230,888')), array('Item' => array('price' => '66,000')), ); $result = Hash::sort($items, '{n}.Item.price', 'asc', 'numeric'); $expected = array( array('Item' => array('price' => '66,000')), array('Item' => array('price' => '139,000')), array('Item' => array('price' => '155,000')), array('Item' => array('price' => '230,888')), array('Item' => array('price' => '275,622')), ); $this->assertEquals($expected, $result); $result = Hash::sort($items, '{n}.Item.price', 'desc', 'numeric'); $expected = array( array('Item' => array('price' => '275,622')), array('Item' => array('price' => '230,888')), array('Item' => array('price' => '155,000')), array('Item' => array('price' => '139,000')), array('Item' => array('price' => '66,000')), ); $this->assertEquals($expected, $result); } /** * Test natural sorting. * * @return void */ public function testSortNatural() { if (version_compare(PHP_VERSION, '5.4.0', '<')) { $this->markTestSkipped('SORT_NATURAL is available since PHP 5.4.'); } $items = array( array('Item' => array('image' => 'img1.jpg')), array('Item' => array('image' => 'img99.jpg')), array('Item' => array('image' => 'img12.jpg')), array('Item' => array('image' => 'img10.jpg')), array('Item' => array('image' => 'img2.jpg')), ); $result = Hash::sort($items, '{n}.Item.image', 'desc', 'natural'); $expected = array( array('Item' => array('image' => 'img99.jpg')), array('Item' => array('image' => 'img12.jpg')), array('Item' => array('image' => 'img10.jpg')), array('Item' => array('image' => 'img2.jpg')), array('Item' => array('image' => 'img1.jpg')), ); $this->assertEquals($expected, $result); $result = Hash::sort($items, '{n}.Item.image', 'asc', 'natural'); $expected = array( array('Item' => array('image' => 'img1.jpg')), array('Item' => array('image' => 'img2.jpg')), array('Item' => array('image' => 'img10.jpg')), array('Item' => array('image' => 'img12.jpg')), array('Item' => array('image' => 'img99.jpg')), ); $this->assertEquals($expected, $result); } /** * Test natural sorting ignoring case. * * @return void */ public function testSortNaturalIgnoreCase() { if (version_compare(PHP_VERSION, '5.4.0', '<')) { $this->markTestSkipped('SORT_NATURAL is available since PHP 5.4.'); } $items = array( array('Item' => array('image' => 'img1.jpg')), array('Item' => array('image' => 'img99.jpg')), array('Item' => array('image' => 'Img12.jpg')), array('Item' => array('image' => 'Img10.jpg')), array('Item' => array('image' => 'img2.jpg')), ); $result = Hash::sort($items, '{n}.Item.image', 'desc', array('type' => 'natural', 'ignoreCase' => true)); $expected = array( array('Item' => array('image' => 'img99.jpg')), array('Item' => array('image' => 'Img12.jpg')), array('Item' => array('image' => 'Img10.jpg')), array('Item' => array('image' => 'img2.jpg')), array('Item' => array('image' => 'img1.jpg')), ); $this->assertEquals($expected, $result); $result = Hash::sort($items, '{n}.Item.image', 'asc', array('type' => 'natural', 'ignoreCase' => true)); $expected = array( array('Item' => array('image' => 'img1.jpg')), array('Item' => array('image' => 'img2.jpg')), array('Item' => array('image' => 'Img10.jpg')), array('Item' => array('image' => 'Img12.jpg')), array('Item' => array('image' => 'img99.jpg')), ); $this->assertEquals($expected, $result); } /** * Test that sort() with 'natural' type will fallback to 'regular' as SORT_NATURAL is introduced in PHP 5.4 * * @return void */ public function testSortNaturalFallbackToRegular() { if (version_compare(PHP_VERSION, '5.4.0', '>=')) { $this->markTestSkipped('Skipping SORT_NATURAL fallback test on PHP >= 5.4'); } $a = array( 0 => array('Person' => array('name' => 'Jeff')), 1 => array('Shirt' => array('color' => 'black')) ); $b = array( 0 => array('Shirt' => array('color' => 'black')), 1 => array('Person' => array('name' => 'Jeff')), ); $sorted = Hash::sort($a, '{n}.Person.name', 'asc', 'natural'); $this->assertEquals($sorted, $b); } /** * test sorting with out of order keys. * * @return void */ public function testSortWithOutOfOrderKeys() { $data = array( 9 => array('class' => 510, 'test2' => 2), 1 => array('class' => 500, 'test2' => 1), 2 => array('class' => 600, 'test2' => 2), 5 => array('class' => 625, 'test2' => 4), 0 => array('class' => 605, 'test2' => 3), ); $expected = array( array('class' => 500, 'test2' => 1), array('class' => 510, 'test2' => 2), array('class' => 600, 'test2' => 2), array('class' => 605, 'test2' => 3), array('class' => 625, 'test2' => 4), ); $result = Hash::sort($data, '{n}.class', 'asc'); $this->assertEquals($expected, $result); $result = Hash::sort($data, '{n}.test2', 'asc'); $this->assertEquals($expected, $result); } /** * test sorting with string keys. * * @return void */ public function testSortStringKeys() { $toSort = array( 'four' => array('number' => 4, 'some' => 'foursome'), 'six' => array('number' => 6, 'some' => 'sixsome'), 'five' => array('number' => 5, 'some' => 'fivesome'), 'two' => array('number' => 2, 'some' => 'twosome'), 'three' => array('number' => 3, 'some' => 'threesome') ); $sorted = Hash::sort($toSort, '{s}.number', 'asc'); $expected = array( 'two' => array('number' => 2, 'some' => 'twosome'), 'three' => array('number' => 3, 'some' => 'threesome'), 'four' => array('number' => 4, 'some' => 'foursome'), 'five' => array('number' => 5, 'some' => 'fivesome'), 'six' => array('number' => 6, 'some' => 'sixsome') ); $this->assertEquals($expected, $sorted); $menus = array( 'blogs' => array('title' => 'Blogs', 'weight' => 3), 'comments' => array('title' => 'Comments', 'weight' => 2), 'users' => array('title' => 'Users', 'weight' => 1), ); $expected = array( 'users' => array('title' => 'Users', 'weight' => 1), 'comments' => array('title' => 'Comments', 'weight' => 2), 'blogs' => array('title' => 'Blogs', 'weight' => 3), ); $result = Hash::sort($menus, '{s}.weight', 'ASC'); $this->assertEquals($expected, $result); } /** * test sorting with string ignoring case. * * @return void */ public function testSortStringIgnoreCase() { $toSort = array( array('Item' => array('name' => 'bar')), array('Item' => array('name' => 'Baby')), array('Item' => array('name' => 'Baz')), array('Item' => array('name' => 'bat')), ); $sorted = Hash::sort($toSort, '{n}.Item.name', 'asc', array('type' => 'string', 'ignoreCase' => true)); $expected = array( array('Item' => array('name' => 'Baby')), array('Item' => array('name' => 'bar')), array('Item' => array('name' => 'bat')), array('Item' => array('name' => 'Baz')), ); $this->assertEquals($expected, $sorted); } /** * test regular sorting ignoring case. * * @return void */ public function testSortRegularIgnoreCase() { $toSort = array( array('Item' => array('name' => 'bar')), array('Item' => array('name' => 'Baby')), array('Item' => array('name' => 'Baz')), array('Item' => array('name' => 'bat')), ); $sorted = Hash::sort($toSort, '{n}.Item.name', 'asc', array('type' => 'regular', 'ignoreCase' => true)); $expected = array( array('Item' => array('name' => 'Baby')), array('Item' => array('name' => 'bar')), array('Item' => array('name' => 'bat')), array('Item' => array('name' => 'Baz')), ); $this->assertEquals($expected, $sorted); } /** * Test insert() * * @return void */ public function testInsertSimple() { $a = array( 'pages' => array('name' => 'page') ); $result = Hash::insert($a, 'files', array('name' => 'files')); $expected = array( 'pages' => array('name' => 'page'), 'files' => array('name' => 'files') ); $this->assertEquals($expected, $result); $a = array( 'pages' => array('name' => 'page') ); $result = Hash::insert($a, 'pages.name', array()); $expected = array( 'pages' => array('name' => array()), ); $this->assertEquals($expected, $result); $a = array( 'foo' => array('bar' => 'baz') ); $result = Hash::insert($a, 'some.0123.path', array('foo' => array('bar' => 'baz'))); $expected = array('foo' => array('bar' => 'baz')); $this->assertEquals($expected, Hash::get($result, 'some.0123.path')); } /** * Test inserting with multiple values. * * @return void */ public function testInsertMulti() { $data = static::articleData(); $result = Hash::insert($data, '{n}.Article.insert', 'value'); $this->assertEquals('value', $result[0]['Article']['insert']); $this->assertEquals('value', $result[1]['Article']['insert']); $result = Hash::insert($data, '{n}.Comment.{n}.insert', 'value'); $this->assertEquals('value', $result[0]['Comment'][0]['insert']); $this->assertEquals('value', $result[0]['Comment'][1]['insert']); $data = array( 0 => array('Item' => array('id' => 1, 'title' => 'first')), 1 => array('Item' => array('id' => 2, 'title' => 'second')), 2 => array('Item' => array('id' => 3, 'title' => 'third')), 3 => array('Item' => array('id' => 4, 'title' => 'fourth')), 4 => array('Item' => array('id' => 5, 'title' => 'fifth')), ); $result = Hash::insert($data, '{n}.Item[id=/\b2|\b4/]', array('test' => 2)); $expected = array( 0 => array('Item' => array('id' => 1, 'title' => 'first')), 1 => array('Item' => array('id' => 2, 'title' => 'second', 'test' => 2)), 2 => array('Item' => array('id' => 3, 'title' => 'third')), 3 => array('Item' => array('id' => 4, 'title' => 'fourth', 'test' => 2)), 4 => array('Item' => array('id' => 5, 'title' => 'fifth')), ); $this->assertEquals($expected, $result); } /** * Test that insert() can insert data over a string value. * * @return void */ public function testInsertOverwriteStringValue() { $data = array( 'Some' => array( 'string' => 'value' ) ); $result = Hash::insert($data, 'Some.string.value', array('values')); $expected = array( 'Some' => array( 'string' => array( 'value' => array('values') ) ) ); $this->assertEquals($expected, $result); } /** * Test remove() method. * * @return void */ public function testRemove() { $a = array( 'pages' => array('name' => 'page'), 'files' => array('name' => 'files') ); $result = Hash::remove($a, 'files'); $expected = array( 'pages' => array('name' => 'page') ); $this->assertEquals($expected, $result); $a = array( 'pages' => array( 0 => array('name' => 'main'), 1 => array( 'name' => 'about', 'vars' => array('title' => 'page title') ) ) ); $result = Hash::remove($a, 'pages.1.vars'); $expected = array( 'pages' => array( 0 => array('name' => 'main'), 1 => array('name' => 'about') ) ); $this->assertEquals($expected, $result); $result = Hash::remove($a, 'pages.2.vars'); $expected = $a; $this->assertEquals($expected, $result); $a = array( 0 => array( 'name' => 'pages' ), 1 => array( 'name' => 'files' ) ); $result = Hash::remove($a, '{n}[name=files]'); $expected = array( 0 => array( 'name' => 'pages' ) ); $this->assertEquals($expected, $result); $array = array( 0 => 'foo', 1 => array( 0 => 'baz' ) ); $expected = $array; $result = Hash::remove($array, '{n}.part'); $this->assertEquals($expected, $result); $result = Hash::remove($array, '{n}.{n}.part'); $this->assertEquals($expected, $result); } /** * Test removing multiple values. * * @return void */ public function testRemoveMulti() { $data = static::articleData(); $result = Hash::remove($data, '{n}.Article.title'); $this->assertFalse(isset($result[0]['Article']['title'])); $this->assertFalse(isset($result[1]['Article']['title'])); $result = Hash::remove($data, '{n}.Article.{s}'); $this->assertFalse(isset($result[0]['Article']['id'])); $this->assertFalse(isset($result[0]['Article']['user_id'])); $this->assertFalse(isset($result[0]['Article']['title'])); $this->assertFalse(isset($result[0]['Article']['body'])); $data = array( 0 => array('Item' => array('id' => 1, 'title' => 'first')), 1 => array('Item' => array('id' => 2, 'title' => 'second')), 2 => array('Item' => array('id' => 3, 'title' => 'third')), 3 => array('Item' => array('id' => 4, 'title' => 'fourth')), 4 => array('Item' => array('id' => 5, 'title' => 'fifth')), ); $result = Hash::remove($data, '{n}.Item[id=/\b2|\b4/]'); $expected = array( 0 => array('Item' => array('id' => 1, 'title' => 'first')), 2 => array('Item' => array('id' => 3, 'title' => 'third')), 4 => array('Item' => array('id' => 5, 'title' => 'fifth')), ); $this->assertEquals($expected, $result); } /** * testCheck method * * @return void */ public function testCheck() { $set = array( 'My Index 1' => array('First' => 'The first item') ); $this->assertTrue(Hash::check($set, 'My Index 1.First')); $this->assertTrue(Hash::check($set, 'My Index 1')); $set = array( 'My Index 1' => array( 'First' => array( 'Second' => array( 'Third' => array( 'Fourth' => 'Heavy. Nesting.' ) ) ) ) ); $this->assertTrue(Hash::check($set, 'My Index 1.First.Second')); $this->assertTrue(Hash::check($set, 'My Index 1.First.Second.Third')); $this->assertTrue(Hash::check($set, 'My Index 1.First.Second.Third.Fourth')); $this->assertFalse(Hash::check($set, 'My Index 1.First.Seconds.Third.Fourth')); } /** * testCombine method * * @return void */ public function testCombine() { $result = Hash::combine(array(), '{n}.User.id', '{n}.User.Data'); $this->assertTrue(empty($result)); $a = static::userData(); $result = Hash::combine($a, '{n}.User.id'); $expected = array(2 => null, 14 => null, 25 => null); $this->assertEquals($expected, $result); $result = Hash::combine($a, '{n}.User.id', '{n}.User.non-existant'); $expected = array(2 => null, 14 => null, 25 => null); $this->assertEquals($expected, $result); $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data'); $expected = array( 2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'), 14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters'), 25 => array('user' => 'gwoo', 'name' => 'The Gwoo')); $this->assertEquals($expected, $result); $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.name'); $expected = array( 2 => 'Mariano Iglesias', 14 => 'Larry E. Masters', 25 => 'The Gwoo'); $this->assertEquals($expected, $result); } /** * test combine() giving errors on key/value length mismatches. * * @expectedException CakeException * @return void */ public function testCombineErrorMissingValue() { $data = array( array('User' => array('id' => 1, 'name' => 'mark')), array('User' => array('name' => 'jose')), ); Hash::combine($data, '{n}.User.id', '{n}.User.name'); } /** * test combine() giving errors on key/value length mismatches. * * @expectedException CakeException * @return void */ public function testCombineErrorMissingKey() { $data = array( array('User' => array('id' => 1, 'name' => 'mark')), array('User' => array('id' => 2)), ); Hash::combine($data, '{n}.User.id', '{n}.User.name'); } /** * test combine() with a group path. * * @return void */ public function testCombineWithGroupPath() { $a = static::userData(); $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data', '{n}.User.group_id'); $expected = array( 1 => array( 2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'), 25 => array('user' => 'gwoo', 'name' => 'The Gwoo') ), 2 => array( 14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters') ) ); $this->assertEquals($expected, $result); $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.name', '{n}.User.group_id'); $expected = array( 1 => array( 2 => 'Mariano Iglesias', 25 => 'The Gwoo' ), 2 => array( 14 => 'Larry E. Masters' ) ); $this->assertEquals($expected, $result); $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data', '{n}.User.group_id'); $expected = array( 1 => array( 2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'), 25 => array('user' => 'gwoo', 'name' => 'The Gwoo') ), 2 => array( 14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters') ) ); $this->assertEquals($expected, $result); $result = Hash::combine($a, '{n}.User.id', '{n}.User.Data.name', '{n}.User.group_id'); $expected = array( 1 => array( 2 => 'Mariano Iglesias', 25 => 'The Gwoo' ), 2 => array( 14 => 'Larry E. Masters' ) ); $this->assertEquals($expected, $result); } /** * Test combine with formatting rules. * * @return void */ public function testCombineWithFormatting() { $a = static::userData(); $result = Hash::combine( $a, '{n}.User.id', array('%1$s: %2$s', '{n}.User.Data.user', '{n}.User.Data.name'), '{n}.User.group_id' ); $expected = array( 1 => array( 2 => 'mariano.iglesias: Mariano Iglesias', 25 => 'gwoo: The Gwoo' ), 2 => array( 14 => 'phpnut: Larry E. Masters' ) ); $this->assertEquals($expected, $result); $result = Hash::combine( $a, array( '%s: %s', '{n}.User.Data.user', '{n}.User.Data.name' ), '{n}.User.id' ); $expected = array( 'mariano.iglesias: Mariano Iglesias' => 2, 'phpnut: Larry E. Masters' => 14, 'gwoo: The Gwoo' => 25 ); $this->assertEquals($expected, $result); $result = Hash::combine( $a, array('%1$s: %2$d', '{n}.User.Data.user', '{n}.User.id'), '{n}.User.Data.name' ); $expected = array( 'mariano.iglesias: 2' => 'Mariano Iglesias', 'phpnut: 14' => 'Larry E. Masters', 'gwoo: 25' => 'The Gwoo' ); $this->assertEquals($expected, $result); $result = Hash::combine( $a, array('%2$d: %1$s', '{n}.User.Data.user', '{n}.User.id'), '{n}.User.Data.name' ); $expected = array( '2: mariano.iglesias' => 'Mariano Iglesias', '14: phpnut' => 'Larry E. Masters', '25: gwoo' => 'The Gwoo' ); $this->assertEquals($expected, $result); } /** * testFormat method * * @return void */ public function testFormat() { $data = static::userData(); $result = Hash::format( $data, array('{n}.User.Data.user', '{n}.User.id'), '%s, %s' ); $expected = array( 'mariano.iglesias, 2', 'phpnut, 14', 'gwoo, 25' ); $this->assertEquals($expected, $result); $result = Hash::format( $data, array('{n}.User.Data.user', '{n}.User.id'), '%2$s, %1$s' ); $expected = array( '2, mariano.iglesias', '14, phpnut', '25, gwoo' ); $this->assertEquals($expected, $result); } /** * testFormattingNullValues method * * @return void */ public function testFormatNullValues() { $data = array( array('Person' => array( 'first_name' => 'Nate', 'last_name' => 'Abele', 'city' => 'Boston', 'state' => 'MA', 'something' => '42' )), array('Person' => array( 'first_name' => 'Larry', 'last_name' => 'Masters', 'city' => 'Boondock', 'state' => 'TN', 'something' => null )), array('Person' => array( 'first_name' => 'Garrett', 'last_name' => 'Woodworth', 'city' => 'Venice Beach', 'state' => 'CA', 'something' => null )) ); $result = Hash::format($data, array('{n}.Person.something'), '%s'); $expected = array('42', '', ''); $this->assertEquals($expected, $result); $result = Hash::format($data, array('{n}.Person.city', '{n}.Person.something'), '%s, %s'); $expected = array('Boston, 42', 'Boondock, ', 'Venice Beach, '); $this->assertEquals($expected, $result); } /** * Test map() * * @return void */ public function testMap() { $data = static::articleData(); $result = Hash::map($data, '{n}.Article.id', array($this, 'mapCallback')); $expected = array(2, 4, 6, 8, 10); $this->assertEquals($expected, $result); } /** * testApply * * @return void */ public function testApply() { $data = static::articleData(); $result = Hash::apply($data, '{n}.Article.id', 'array_sum'); $this->assertEquals(15, $result); } /** * Test reduce() * * @return void */ public function testReduce() { $data = static::articleData(); $result = Hash::reduce($data, '{n}.Article.id', array($this, 'reduceCallback')); $this->assertEquals(15, $result); } /** * testing method for map callbacks. * * @param mixed $value Value * @return mixed */ public function mapCallback($value) { return $value * 2; } /** * testing method for reduce callbacks. * * @param mixed $one First param * @param mixed $two Second param * @return mixed */ public function reduceCallback($one, $two) { return $one + $two; } /** * test Hash nest with a normal model result set. For kicks rely on Hash nest detecting the key names * automatically * * @return void */ public function testNestModel() { $input = array( array( 'ModelName' => array( 'id' => 1, 'parent_id' => null ), ), array( 'ModelName' => array( 'id' => 2, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 3, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 4, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 5, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 6, 'parent_id' => null ), ), array( 'ModelName' => array( 'id' => 7, 'parent_id' => 6 ), ), array( 'ModelName' => array( 'id' => 8, 'parent_id' => 6 ), ), array( 'ModelName' => array( 'id' => 9, 'parent_id' => 6 ), ), array( 'ModelName' => array( 'id' => 10, 'parent_id' => 6 ) ) ); $expected = array( array( 'ModelName' => array( 'id' => 1, 'parent_id' => null ), 'children' => array( array( 'ModelName' => array( 'id' => 2, 'parent_id' => 1 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 3, 'parent_id' => 1 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 4, 'parent_id' => 1 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 5, 'parent_id' => 1 ), 'children' => array() ), ) ), array( 'ModelName' => array( 'id' => 6, 'parent_id' => null ), 'children' => array( array( 'ModelName' => array( 'id' => 7, 'parent_id' => 6 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 8, 'parent_id' => 6 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 9, 'parent_id' => 6 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 10, 'parent_id' => 6 ), 'children' => array() ) ) ) ); $result = Hash::nest($input); $this->assertEquals($expected, $result); } /** * test Hash nest with a normal model result set, and a nominated root id * * @return void */ public function testNestModelExplicitRoot() { $input = array( array( 'ModelName' => array( 'id' => 1, 'parent_id' => null ), ), array( 'ModelName' => array( 'id' => 2, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 3, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 4, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 5, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 6, 'parent_id' => null ), ), array( 'ModelName' => array( 'id' => 7, 'parent_id' => 6 ), ), array( 'ModelName' => array( 'id' => 8, 'parent_id' => 6 ), ), array( 'ModelName' => array( 'id' => 9, 'parent_id' => 6 ), ), array( 'ModelName' => array( 'id' => 10, 'parent_id' => 6 ) ) ); $expected = array( array( 'ModelName' => array( 'id' => 6, 'parent_id' => null ), 'children' => array( array( 'ModelName' => array( 'id' => 7, 'parent_id' => 6 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 8, 'parent_id' => 6 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 9, 'parent_id' => 6 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 10, 'parent_id' => 6 ), 'children' => array() ) ) ) ); $result = Hash::nest($input, array('root' => 6)); $this->assertEquals($expected, $result); } /** * test Hash nest with a 1d array - this method should be able to handle any type of array input * * @return void */ public function testNest1Dimensional() { $input = array( array( 'id' => 1, 'parent_id' => null ), array( 'id' => 2, 'parent_id' => 1 ), array( 'id' => 3, 'parent_id' => 1 ), array( 'id' => 4, 'parent_id' => 1 ), array( 'id' => 5, 'parent_id' => 1 ), array( 'id' => 6, 'parent_id' => null ), array( 'id' => 7, 'parent_id' => 6 ), array( 'id' => 8, 'parent_id' => 6 ), array( 'id' => 9, 'parent_id' => 6 ), array( 'id' => 10, 'parent_id' => 6 ) ); $expected = array( array( 'id' => 1, 'parent_id' => null, 'children' => array( array( 'id' => 2, 'parent_id' => 1, 'children' => array() ), array( 'id' => 3, 'parent_id' => 1, 'children' => array() ), array( 'id' => 4, 'parent_id' => 1, 'children' => array() ), array( 'id' => 5, 'parent_id' => 1, 'children' => array() ), ) ), array( 'id' => 6, 'parent_id' => null, 'children' => array( array( 'id' => 7, 'parent_id' => 6, 'children' => array() ), array( 'id' => 8, 'parent_id' => 6, 'children' => array() ), array( 'id' => 9, 'parent_id' => 6, 'children' => array() ), array( 'id' => 10, 'parent_id' => 6, 'children' => array() ) ) ) ); $result = Hash::nest($input, array('idPath' => '{n}.id', 'parentPath' => '{n}.parent_id')); $this->assertEquals($expected, $result); } /** * test Hash nest with no specified parent data. * * The result should be the same as the input. * For an easier comparison, unset all the empty children arrays from the result * * @return void */ public function testMissingParent() { $input = array( array( 'id' => 1, ), array( 'id' => 2, ), array( 'id' => 3, ), array( 'id' => 4, ), array( 'id' => 5, ), array( 'id' => 6, ), array( 'id' => 7, ), array( 'id' => 8, ), array( 'id' => 9, ), array( 'id' => 10, ) ); $result = Hash::nest($input, array('idPath' => '{n}.id', 'parentPath' => '{n}.parent_id')); foreach ($result as &$row) { if (empty($row['children'])) { unset($row['children']); } } $this->assertEquals($input, $result); } /** * Tests that nest() throws an InvalidArgumentException when providing an invalid input. * * @expectedException InvalidArgumentException * @return void */ public function testNestInvalid() { $input = array( array( 'ParentCategory' => array( 'id' => '1', 'name' => 'Lorem ipsum dolor sit amet', 'parent_id' => '1' ) ) ); Hash::nest($input); } /** * testMergeDiff method * * @return void */ public function testMergeDiff() { $first = array( 'ModelOne' => array( 'id' => 1001, 'field_one' => 'a1.m1.f1', 'field_two' => 'a1.m1.f2' ) ); $second = array( 'ModelTwo' => array( 'id' => 1002, 'field_one' => 'a2.m2.f1', 'field_two' => 'a2.m2.f2' ) ); $result = Hash::mergeDiff($first, $second); $this->assertEquals($result, $first + $second); $result = Hash::mergeDiff($first, array()); $this->assertEquals($result, $first); $result = Hash::mergeDiff(array(), $first); $this->assertEquals($result, $first); $third = array( 'ModelOne' => array( 'id' => 1003, 'field_one' => 'a3.m1.f1', 'field_two' => 'a3.m1.f2', 'field_three' => 'a3.m1.f3' ) ); $result = Hash::mergeDiff($first, $third); $expected = array( 'ModelOne' => array( 'id' => 1001, 'field_one' => 'a1.m1.f1', 'field_two' => 'a1.m1.f2', 'field_three' => 'a3.m1.f3' ) ); $this->assertEquals($expected, $result); $first = array( 0 => array('ModelOne' => array('id' => 1001, 'field_one' => 's1.0.m1.f1', 'field_two' => 's1.0.m1.f2')), 1 => array('ModelTwo' => array('id' => 1002, 'field_one' => 's1.1.m2.f2', 'field_two' => 's1.1.m2.f2')) ); $second = array( 0 => array('ModelOne' => array('id' => 1001, 'field_one' => 's2.0.m1.f1', 'field_two' => 's2.0.m1.f2')), 1 => array('ModelTwo' => array('id' => 1002, 'field_one' => 's2.1.m2.f2', 'field_two' => 's2.1.m2.f2')) ); $result = Hash::mergeDiff($first, $second); $this->assertEquals($result, $first); $third = array( 0 => array( 'ModelThree' => array( 'id' => 1003, 'field_one' => 's3.0.m3.f1', 'field_two' => 's3.0.m3.f2' ) ) ); $result = Hash::mergeDiff($first, $third); $expected = array( 0 => array( 'ModelOne' => array( 'id' => 1001, 'field_one' => 's1.0.m1.f1', 'field_two' => 's1.0.m1.f2' ), 'ModelThree' => array( 'id' => 1003, 'field_one' => 's3.0.m3.f1', 'field_two' => 's3.0.m3.f2' ) ), 1 => array( 'ModelTwo' => array( 'id' => 1002, 'field_one' => 's1.1.m2.f2', 'field_two' => 's1.1.m2.f2' ) ) ); $this->assertEquals($expected, $result); $result = Hash::mergeDiff($first, null); $this->assertEquals($result, $first); $result = Hash::mergeDiff($first, $second); $this->assertEquals($result, $first + $second); } /** * Tests Hash::expand * * @return void */ public function testExpand() { $data = array('My', 'Array', 'To', 'Flatten'); $flat = Hash::flatten($data); $result = Hash::expand($flat); $this->assertEquals($data, $result); $data = array( '0.Post.id' => '1', '0.Post.author_id' => '1', '0.Post.title' => 'First Post', '0.Author.id' => '1', '0.Author.user' => 'nate', '0.Author.password' => 'foo', '1.Post.id' => '2', '1.Post.author_id' => '3', '1.Post.title' => 'Second Post', '1.Post.body' => 'Second Post Body', '1.Author.id' => '3', '1.Author.user' => 'larry', '1.Author.password' => null ); $result = Hash::expand($data); $expected = array( array( 'Post' => array('id' => '1', 'author_id' => '1', 'title' => 'First Post'), 'Author' => array('id' => '1', 'user' => 'nate', 'password' => 'foo'), ), array( 'Post' => array('id' => '2', 'author_id' => '3', 'title' => 'Second Post', 'body' => 'Second Post Body'), 'Author' => array('id' => '3', 'user' => 'larry', 'password' => null), ) ); $this->assertEquals($expected, $result); $data = array( '0/Post/id' => 1, '0/Post/name' => 'test post' ); $result = Hash::expand($data, '/'); $expected = array( array( 'Post' => array( 'id' => 1, 'name' => 'test post' ) ) ); $this->assertEquals($expected, $result); $data = array('a.b.100.a' => null, 'a.b.200.a' => null); $expected = array( 'a' => array( 'b' => array( 100 => array('a' => null), 200 => array('a' => null) ) ) ); $result = Hash::expand($data); $this->assertEquals($expected, $result); } /** * Test that flattening a large complex set doesn't loop forever. * * @return void */ public function testFlattenInfiniteLoop() { $data = array( 'Order.ASI' => '0', 'Order.Accounting' => '0', 'Order.Admin' => '0', 'Order.Art' => '0', 'Order.ArtChecker' => '0', 'Order.Canned' => '0', 'Order.Customer_Tags' => '', 'Order.Embroidery' => '0', 'Order.Item.0.Product.style_number' => 'a11222', 'Order.Item.0.Product.slug' => 'a11222', 'Order.Item.0.Product._id' => '4ff8b8d3d7bbe8ad30000000', 'Order.Item.0.Product.Color.slug' => 'kelly_green', 'Order.Item.0.Product.ColorSizes.0.Color.color' => 'Sport Grey', 'Order.Item.0.Product.ColorSizes.0.Color.slug' => 'sport_grey', 'Order.Item.0.Product.ColorSizes.1.Color.color' => 'Kelly Green', 'Order.Item.0.Product.ColorSizes.1.Color.slug' => 'kelly_green', 'Order.Item.0.Product.ColorSizes.2.Color.color' => 'Orange', 'Order.Item.0.Product.ColorSizes.2.Color.slug' => 'orange', 'Order.Item.0.Product.ColorSizes.3.Color.color' => 'Yellow Haze', 'Order.Item.0.Product.ColorSizes.3.Color.slug' => 'yellow_haze', 'Order.Item.0.Product.brand' => 'OUTER BANKS', 'Order.Item.0.Product.style' => 'T-shirt', 'Order.Item.0.Product.description' => 'uhiuhuih oin ooi ioo ioio', 'Order.Item.0.Product.sizes.0.Size.qty' => '', 'Order.Item.0.Product.sizes.0.Size.size' => '0-3mo', 'Order.Item.0.Product.sizes.0.Size.id' => '38', 'Order.Item.0.Product.sizes.1.Size.qty' => '', 'Order.Item.0.Product.sizes.1.Size.size' => '3-6mo', 'Order.Item.0.Product.sizes.1.Size.id' => '39', 'Order.Item.0.Product.sizes.2.Size.qty' => '78', 'Order.Item.0.Product.sizes.2.Size.size' => '6-9mo', 'Order.Item.0.Product.sizes.2.Size.id' => '40', 'Order.Item.0.Product.sizes.3.Size.qty' => '', 'Order.Item.0.Product.sizes.3.Size.size' => '6-12mo', 'Order.Item.0.Product.sizes.3.Size.id' => '41', 'Order.Item.0.Product.sizes.4.Size.qty' => '', 'Order.Item.0.Product.sizes.4.Size.size' => '12-18mo', 'Order.Item.0.Product.sizes.4.Size.id' => '42', 'Order.Item.0.Art.imprint_locations.0.id' => 2, 'Order.Item.0.Art.imprint_locations.0.name' => 'Left Chest', 'Order.Item.0.Art.imprint_locations.0.imprint_type.id' => 7, 'Order.Item.0.Art.imprint_locations.0.imprint_type.type' => 'Embroidery', 'Order.Item.0.Art.imprint_locations.0.art' => '', 'Order.Item.0.Art.imprint_locations.0.num_colors' => 3, 'Order.Item.0.Art.imprint_locations.0.description' => 'Wooo! This is Embroidery!!', 'Order.Item.0.Art.imprint_locations.0.lines.0' => 'Platen', 'Order.Item.0.Art.imprint_locations.0.lines.1' => 'Logo', 'Order.Item.0.Art.imprint_locations.0.height' => 4, 'Order.Item.0.Art.imprint_locations.0.width' => 5, 'Order.Item.0.Art.imprint_locations.0.stitch_density' => 'Light', 'Order.Item.0.Art.imprint_locations.0.metallic_thread' => true, 'Order.Item.0.Art.imprint_locations.1.id' => 4, 'Order.Item.0.Art.imprint_locations.1.name' => 'Full Back', 'Order.Item.0.Art.imprint_locations.1.imprint_type.id' => 6, 'Order.Item.0.Art.imprint_locations.1.imprint_type.type' => 'Screenprinting', 'Order.Item.0.Art.imprint_locations.1.art' => '', 'Order.Item.0.Art.imprint_locations.1.num_colors' => 3, 'Order.Item.0.Art.imprint_locations.1.description' => 'Wooo! This is Screenprinting!!', 'Order.Item.0.Art.imprint_locations.1.lines.0' => 'Platen', 'Order.Item.0.Art.imprint_locations.1.lines.1' => 'Logo', 'Order.Item.0.Art.imprint_locations.2.id' => 26, 'Order.Item.0.Art.imprint_locations.2.name' => 'HS - JSY Name Below', 'Order.Item.0.Art.imprint_locations.2.imprint_type.id' => 9, 'Order.Item.0.Art.imprint_locations.2.imprint_type.type' => 'Names', 'Order.Item.0.Art.imprint_locations.2.description' => 'Wooo! This is Names!!', 'Order.Item.0.Art.imprint_locations.2.sizes.S.0.active' => 1, 'Order.Item.0.Art.imprint_locations.2.sizes.S.0.name' => 'Benjamin Talavera', 'Order.Item.0.Art.imprint_locations.2.sizes.S.0.color' => 'Red', 'Order.Item.0.Art.imprint_locations.2.sizes.S.0.height' => '3', 'Order.Item.0.Art.imprint_locations.2.sizes.S.0.layout' => 'Arched', 'Order.Item.0.Art.imprint_locations.2.sizes.S.0.style' => 'Classic', 'Order.Item.0.Art.imprint_locations.2.sizes.S.1.active' => 0, 'Order.Item.0.Art.imprint_locations.2.sizes.S.1.name' => 'Rishi Narayan', 'Order.Item.0.Art.imprint_locations.2.sizes.S.1.color' => 'Cardinal', 'Order.Item.0.Art.imprint_locations.2.sizes.S.1.height' => '4', 'Order.Item.0.Art.imprint_locations.2.sizes.S.1.layout' => 'Straight', 'Order.Item.0.Art.imprint_locations.2.sizes.S.1.style' => 'Team US', 'Order.Item.0.Art.imprint_locations.2.sizes.M.0.active' => 1, 'Order.Item.0.Art.imprint_locations.2.sizes.M.0.name' => 'Brandon Plasters', 'Order.Item.0.Art.imprint_locations.2.sizes.M.0.color' => 'Red', 'Order.Item.0.Art.imprint_locations.2.sizes.M.0.height' => '3', 'Order.Item.0.Art.imprint_locations.2.sizes.M.0.layout' => 'Arched', 'Order.Item.0.Art.imprint_locations.2.sizes.M.0.style' => 'Classic', 'Order.Item.0.Art.imprint_locations.2.sizes.M.1.active' => 0, 'Order.Item.0.Art.imprint_locations.2.sizes.M.1.name' => 'Andrew Reed', 'Order.Item.0.Art.imprint_locations.2.sizes.M.1.color' => 'Cardinal', 'Order.Item.0.Art.imprint_locations.2.sizes.M.1.height' => '4', 'Order.Item.0.Art.imprint_locations.2.sizes.M.1.layout' => 'Straight', 'Order.Item.0.Art.imprint_locations.2.sizes.M.1.style' => 'Team US', 'Order.Job.0._id' => 'job-1', 'Order.Job.0.type' => 'screenprinting', 'Order.Job.0.postPress' => 'job-2', 'Order.Job.1._id' => 'job-2', 'Order.Job.1.type' => 'embroidery', 'Order.Postpress' => '0', 'Order.PriceAdjustment.0._id' => 'price-adjustment-1', 'Order.PriceAdjustment.0.adjustment' => '-20', 'Order.PriceAdjustment.0.adjustment_type' => 'percent', 'Order.PriceAdjustment.0.type' => 'grand_total', 'Order.PriceAdjustment.1.adjustment' => '20', 'Order.PriceAdjustment.1.adjustment_type' => 'flat', 'Order.PriceAdjustment.1.min-items' => '10', 'Order.PriceAdjustment.1.type' => 'min-items', 'Order.PriceAdjustment.1._id' => 'another-test-adjustment', 'Order.Purchasing' => '0', 'Order.QualityControl' => '0', 'Order.Receiving' => '0', 'Order.ScreenPrinting' => '0', 'Order.Stage.art_approval' => 0, 'Order.Stage.draft' => 1, 'Order.Stage.quote' => 1, 'Order.Stage.order' => 1, 'Order.StoreLiason' => '0', 'Order.Tag_UI_Email' => '', 'Order.Tags' => '', 'Order._id' => 'test-2', 'Order.add_print_location' => '', 'Order.created' => '2011-Dec-29 05:40:18', 'Order.force_admin' => '0', 'Order.modified' => '2012-Jul-25 01:24:49', 'Order.name' => 'towering power', 'Order.order_id' => '135961', 'Order.slug' => 'test-2', 'Order.title' => 'test job 2', 'Order.type' => 'ttt' ); $expanded = Hash::expand($data); $flattened = Hash::flatten($expanded); $this->assertEquals($data, $flattened); } } cakephp-2.8.0/lib/Cake/Test/Case/Utility/InflectorTest.php000066400000000000000000000660041265552240500233140ustar00rootroot00000000000000 array ( /* German */ 'ร„' => 'Ae', 'ร–' => 'Oe', 'รœ' => 'Ue', 'รค' => 'ae', 'รถ' => 'oe', 'รผ' => 'ue', 'รŸ' => 'ss', 'แบž' => 'SS' ), 'latin' => array ( 'ร€' => 'A', 'ร' => 'A', 'ร‚' => 'A', 'รƒ' => 'A', 'ร…' => 'A', 'ฤ‚' => 'A', 'ร†' => 'AE', 'ร‡' => 'C', 'รˆ' => 'E', 'ร‰' => 'E', 'รŠ' => 'E', 'ร‹' => 'E', 'รŒ' => 'I', 'ร' => 'I', 'รŽ' => 'I', 'ร' => 'I', 'ร' => 'D', 'ร‘' => 'N', 'ร’' => 'O', 'ร“' => 'O', 'ร”' => 'O', 'ร•' => 'O', 'ล' => 'O', 'ร˜' => 'O', 'ศ˜' => 'S', 'ศš' => 'T', 'ร™' => 'U', 'รš' => 'U', 'ร›' => 'U', 'ลฐ' => 'U', 'ร' => 'Y', 'รž' => 'TH', 'ร ' => 'a', 'รก' => 'a', 'รข' => 'a', 'รฃ' => 'a', 'รฅ' => 'a', 'ฤƒ' => 'a', 'รฆ' => 'ae', 'รง' => 'c', 'รจ' => 'e', 'รฉ' => 'e', 'รช' => 'e', 'รซ' => 'e', 'รฌ' => 'i', 'รญ' => 'i', 'รฎ' => 'i', 'รฏ' => 'i', 'รฐ' => 'd', 'รฑ' => 'n', 'รฒ' => 'o', 'รณ' => 'o', 'รด' => 'o', 'รต' => 'o', 'ล‘' => 'o', 'รธ' => 'o', 'ศ™' => 's', 'ศ›' => 't', 'รน' => 'u', 'รบ' => 'u', 'รป' => 'u', 'ลฑ' => 'u', 'รฝ' => 'y', 'รพ' => 'th', 'รฟ' => 'y' ), 'tr' => array ( /* Turkish */ 'ลŸ' => 's', 'ลž' => 'S', 'ฤฑ' => 'i', 'ฤฐ' => 'I', 'รง' => 'c', 'ร‡' => 'C', 'ฤŸ' => 'g', 'ฤž' => 'G' ), 'uk' => array ( /* Ukrainian */ 'ะ„' => 'Ye', 'ะ†' => 'I', 'ะ‡' => 'Yi', 'า' => 'G', 'ั”' => 'ye', 'ั–' => 'i', 'ั—' => 'yi', 'า‘' => 'g' ), 'cs' => array ( /* Czech */ 'ฤ' => 'c', 'ฤ' => 'd', 'ฤ›' => 'e', 'ลˆ' => 'n', 'ล™' => 'r', 'ลก' => 's', 'ลฅ' => 't', 'ลฏ' => 'u', 'ลพ' => 'z', 'ฤŒ' => 'C', 'ฤŽ' => 'D', 'ฤš' => 'E', 'ล‡' => 'N', 'ล˜' => 'R', 'ล ' => 'S', 'ลค' => 'T', 'ลฎ' => 'U', 'ลฝ' => 'Z' ), 'pl' => array ( /* Polish */ 'ฤ…' => 'a', 'ฤ‡' => 'c', 'ฤ™' => 'e', 'ล‚' => 'l', 'ล„' => 'n', 'รณ' => 'o', 'ล›' => 's', 'ลบ' => 'z', 'ลผ' => 'z', 'ฤ„' => 'A', 'ฤ†' => 'C', 'ล' => 'L', 'ลƒ' => 'N', 'ร“' => 'O', 'ลš' => 'S', 'ลน' => 'Z', 'ลป' => 'Z' ), 'ro' => array ( /* Romanian */ 'ฤƒ' => 'a', 'รข' => 'a', 'รฎ' => 'i', 'ศ™' => 's', 'ศ›' => 't', 'ลข' => 'T', 'ลฃ' => 't' ), 'lv' => array ( /* Latvian */ 'ฤ' => 'a', 'ฤ' => 'c', 'ฤ“' => 'e', 'ฤฃ' => 'g', 'ฤซ' => 'i', 'ฤท' => 'k', 'ฤผ' => 'l', 'ล†' => 'n', 'ลก' => 's', 'ลซ' => 'u', 'ลพ' => 'z', 'ฤ€' => 'A', 'ฤŒ' => 'C', 'ฤ’' => 'E', 'ฤข' => 'G', 'ฤช' => 'I', 'ฤถ' => 'K', 'ฤป' => 'L', 'ล…' => 'N', 'ล ' => 'S', 'ลช' => 'U', 'ลฝ' => 'Z' ), 'lt' => array ( /* Lithuanian */ 'ฤ…' => 'a', 'ฤ' => 'c', 'ฤ™' => 'e', 'ฤ—' => 'e', 'ฤฏ' => 'i', 'ลก' => 's', 'ลณ' => 'u', 'ลซ' => 'u', 'ลพ' => 'z', 'ฤ„' => 'A', 'ฤŒ' => 'C', 'ฤ˜' => 'E', 'ฤ–' => 'E', 'ฤฎ' => 'I', 'ล ' => 'S', 'ลฒ' => 'U', 'ลช' => 'U', 'ลฝ' => 'Z' ) ); /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); Inflector::reset(); } /** * testInflectingSingulars method * * @return void */ public function testInflectingSingulars() { $this->assertEquals(Inflector::singularize('categorias'), 'categoria'); $this->assertEquals(Inflector::singularize('menus'), 'menu'); $this->assertEquals(Inflector::singularize('news'), 'news'); $this->assertEquals(Inflector::singularize('food_menus'), 'food_menu'); $this->assertEquals(Inflector::singularize('Menus'), 'Menu'); $this->assertEquals(Inflector::singularize('FoodMenus'), 'FoodMenu'); $this->assertEquals(Inflector::singularize('houses'), 'house'); $this->assertEquals(Inflector::singularize('powerhouses'), 'powerhouse'); $this->assertEquals(Inflector::singularize('quizzes'), 'quiz'); $this->assertEquals(Inflector::singularize('Buses'), 'Bus'); $this->assertEquals(Inflector::singularize('buses'), 'bus'); $this->assertEquals(Inflector::singularize('matrix_rows'), 'matrix_row'); $this->assertEquals(Inflector::singularize('matrices'), 'matrix'); $this->assertEquals(Inflector::singularize('vertices'), 'vertex'); $this->assertEquals(Inflector::singularize('indices'), 'index'); $this->assertEquals(Inflector::singularize('Aliases'), 'Alias'); $this->assertEquals(Inflector::singularize('Alias'), 'Alias'); $this->assertEquals(Inflector::singularize('Media'), 'Media'); $this->assertEquals(Inflector::singularize('NodeMedia'), 'NodeMedia'); $this->assertEquals(Inflector::singularize('alumni'), 'alumnus'); $this->assertEquals(Inflector::singularize('bacilli'), 'bacillus'); $this->assertEquals(Inflector::singularize('cacti'), 'cactus'); $this->assertEquals(Inflector::singularize('foci'), 'focus'); $this->assertEquals(Inflector::singularize('fungi'), 'fungus'); $this->assertEquals(Inflector::singularize('nuclei'), 'nucleus'); $this->assertEquals(Inflector::singularize('octopuses'), 'octopus'); $this->assertEquals(Inflector::singularize('octopuses'), 'octopus'); $this->assertEquals(Inflector::singularize('radii'), 'radius'); $this->assertEquals(Inflector::singularize('stimuli'), 'stimulus'); $this->assertEquals(Inflector::singularize('syllabi'), 'syllabus'); $this->assertEquals(Inflector::singularize('termini'), 'terminus'); $this->assertEquals(Inflector::singularize('viruses'), 'virus'); $this->assertEquals(Inflector::singularize('people'), 'person'); $this->assertEquals(Inflector::singularize('gloves'), 'glove'); $this->assertEquals(Inflector::singularize('doves'), 'dove'); $this->assertEquals(Inflector::singularize('lives'), 'life'); $this->assertEquals(Inflector::singularize('knives'), 'knife'); $this->assertEquals(Inflector::singularize('wolves'), 'wolf'); $this->assertEquals(Inflector::singularize('slaves'), 'slave'); $this->assertEquals(Inflector::singularize('shelves'), 'shelf'); $this->assertEquals(Inflector::singularize('taxis'), 'taxi'); $this->assertEquals(Inflector::singularize('taxes'), 'tax'); $this->assertEquals(Inflector::singularize('Taxes'), 'Tax'); $this->assertEquals(Inflector::singularize('AwesomeTaxes'), 'AwesomeTax'); $this->assertEquals(Inflector::singularize('faxes'), 'fax'); $this->assertEquals(Inflector::singularize('waxes'), 'wax'); $this->assertEquals(Inflector::singularize('niches'), 'niche'); $this->assertEquals(Inflector::singularize('caves'), 'cave'); $this->assertEquals(Inflector::singularize('graves'), 'grave'); $this->assertEquals(Inflector::singularize('waves'), 'wave'); $this->assertEquals(Inflector::singularize('bureaus'), 'bureau'); $this->assertEquals(Inflector::singularize('genetic_analyses'), 'genetic_analysis'); $this->assertEquals(Inflector::singularize('doctor_diagnoses'), 'doctor_diagnosis'); $this->assertEquals(Inflector::singularize('parantheses'), 'paranthesis'); $this->assertEquals(Inflector::singularize('Causes'), 'Cause'); $this->assertEquals(Inflector::singularize('colossuses'), 'colossus'); $this->assertEquals(Inflector::singularize('diagnoses'), 'diagnosis'); $this->assertEquals(Inflector::singularize('bases'), 'basis'); $this->assertEquals(Inflector::singularize('analyses'), 'analysis'); $this->assertEquals(Inflector::singularize('curves'), 'curve'); $this->assertEquals(Inflector::singularize('cafes'), 'cafe'); $this->assertEquals(Inflector::singularize('roofs'), 'roof'); $this->assertEquals(Inflector::singularize('foes'), 'foe'); $this->assertEquals(Inflector::singularize('databases'), 'database'); $this->assertEquals(Inflector::singularize('cookies'), 'cookie'); $this->assertEquals(Inflector::singularize('thieves'), 'thief'); $this->assertEquals(Inflector::singularize('potatoes'), 'potato'); $this->assertEquals(Inflector::singularize('heroes'), 'hero'); $this->assertEquals(Inflector::singularize('buffalos'), 'buffalo'); $this->assertEquals(Inflector::singularize('babies'), 'baby'); $this->assertEquals(Inflector::singularize('teeth'), 'tooth'); $this->assertEquals(Inflector::singularize('geese'), 'goose'); $this->assertEquals(Inflector::singularize('feet'), 'foot'); $this->assertEquals(Inflector::singularize('objectives'), 'objective'); $this->assertEquals(Inflector::singularize('archives'), 'archive'); $this->assertEquals(Inflector::singularize('briefs'), 'brief'); $this->assertEquals(Inflector::singularize('quotas'), 'quota'); $this->assertEquals(Inflector::singularize('curves'), 'curve'); $this->assertEquals(Inflector::singularize('body_curves'), 'body_curve'); $this->assertEquals(Inflector::singularize('metadata'), 'metadata'); $this->assertEquals(Inflector::singularize('files_metadata'), 'files_metadata'); $this->assertEquals(Inflector::singularize('sieves'), 'sieve'); $this->assertEquals(Inflector::singularize('blue_octopuses'), 'blue_octopus'); $this->assertEquals(Inflector::singularize(''), ''); } /** * Test that overlapping irregulars don't collide. * * @return void */ public function testSingularizeMultiWordIrregular() { Inflector::rules('singular', array( 'irregular' => array( 'preguntas_frecuentes' => 'pregunta_frecuente', 'categorias_preguntas_frecuentes' => 'categoria_pregunta_frecuente', ) )); $this->assertEquals('pregunta_frecuente', Inflector::singularize('preguntas_frecuentes')); $this->assertEquals( 'categoria_pregunta_frecuente', Inflector::singularize('categorias_preguntas_frecuentes') ); $this->assertEquals( 'faq_categoria_pregunta_frecuente', Inflector::singularize('faq_categorias_preguntas_frecuentes') ); } /** * testInflectingPlurals method * * @return void */ public function testInflectingPlurals() { $this->assertEquals(Inflector::pluralize('axman'), 'axmen'); $this->assertEquals(Inflector::pluralize('man'), 'men'); $this->assertEquals(Inflector::pluralize('woman'), 'women'); $this->assertEquals(Inflector::pluralize('human'), 'humans'); $this->assertEquals(Inflector::pluralize('categoria'), 'categorias'); $this->assertEquals(Inflector::pluralize('house'), 'houses'); $this->assertEquals(Inflector::pluralize('powerhouse'), 'powerhouses'); $this->assertEquals(Inflector::pluralize('Bus'), 'Buses'); $this->assertEquals(Inflector::pluralize('bus'), 'buses'); $this->assertEquals(Inflector::pluralize('menu'), 'menus'); $this->assertEquals(Inflector::pluralize('news'), 'news'); $this->assertEquals(Inflector::pluralize('food_menu'), 'food_menus'); $this->assertEquals(Inflector::pluralize('Menu'), 'Menus'); $this->assertEquals(Inflector::pluralize('FoodMenu'), 'FoodMenus'); $this->assertEquals(Inflector::pluralize('quiz'), 'quizzes'); $this->assertEquals(Inflector::pluralize('matrix_row'), 'matrix_rows'); $this->assertEquals(Inflector::pluralize('matrix'), 'matrices'); $this->assertEquals(Inflector::pluralize('vertex'), 'vertices'); $this->assertEquals(Inflector::pluralize('index'), 'indices'); $this->assertEquals(Inflector::pluralize('Alias'), 'Aliases'); $this->assertEquals(Inflector::pluralize('Aliases'), 'Aliases'); $this->assertEquals(Inflector::pluralize('Media'), 'Media'); $this->assertEquals(Inflector::pluralize('NodeMedia'), 'NodeMedia'); $this->assertEquals(Inflector::pluralize('alumnus'), 'alumni'); $this->assertEquals(Inflector::pluralize('bacillus'), 'bacilli'); $this->assertEquals(Inflector::pluralize('cactus'), 'cacti'); $this->assertEquals(Inflector::pluralize('focus'), 'foci'); $this->assertEquals(Inflector::pluralize('fungus'), 'fungi'); $this->assertEquals(Inflector::pluralize('nucleus'), 'nuclei'); $this->assertEquals(Inflector::pluralize('octopus'), 'octopuses'); $this->assertEquals(Inflector::pluralize('radius'), 'radii'); $this->assertEquals(Inflector::pluralize('stimulus'), 'stimuli'); $this->assertEquals(Inflector::pluralize('syllabus'), 'syllabi'); $this->assertEquals(Inflector::pluralize('terminus'), 'termini'); $this->assertEquals(Inflector::pluralize('virus'), 'viruses'); $this->assertEquals(Inflector::pluralize('person'), 'people'); $this->assertEquals(Inflector::pluralize('people'), 'people'); $this->assertEquals(Inflector::pluralize('glove'), 'gloves'); $this->assertEquals(Inflector::pluralize('crisis'), 'crises'); $this->assertEquals(Inflector::pluralize('tax'), 'taxes'); $this->assertEquals(Inflector::pluralize('wave'), 'waves'); $this->assertEquals(Inflector::pluralize('bureau'), 'bureaus'); $this->assertEquals(Inflector::pluralize('cafe'), 'cafes'); $this->assertEquals(Inflector::pluralize('roof'), 'roofs'); $this->assertEquals(Inflector::pluralize('foe'), 'foes'); $this->assertEquals(Inflector::pluralize('cookie'), 'cookies'); $this->assertEquals(Inflector::pluralize('wolf'), 'wolves'); $this->assertEquals(Inflector::pluralize('thief'), 'thieves'); $this->assertEquals(Inflector::pluralize('potato'), 'potatoes'); $this->assertEquals(Inflector::pluralize('hero'), 'heroes'); $this->assertEquals(Inflector::pluralize('buffalo'), 'buffalo'); $this->assertEquals(Inflector::pluralize('tooth'), 'teeth'); $this->assertEquals(Inflector::pluralize('goose'), 'geese'); $this->assertEquals(Inflector::pluralize('foot'), 'feet'); $this->assertEquals(Inflector::pluralize('objective'), 'objectives'); $this->assertEquals(Inflector::pluralize('brief'), 'briefs'); $this->assertEquals(Inflector::pluralize('quota'), 'quotas'); $this->assertEquals(Inflector::pluralize('curve'), 'curves'); $this->assertEquals(Inflector::pluralize('body_curve'), 'body_curves'); $this->assertEquals(Inflector::pluralize('metadata'), 'metadata'); $this->assertEquals(Inflector::pluralize('files_metadata'), 'files_metadata'); $this->assertEquals(Inflector::pluralize('stadia'), 'stadia'); $this->assertEquals(Inflector::pluralize('sieve'), 'sieves'); $this->assertEquals(Inflector::pluralize('blue_octopus'), 'blue_octopuses'); $this->assertEquals(Inflector::pluralize(''), ''); } /** * Test that overlapping irregulars don't collide. * * @return void */ public function testPluralizeMultiWordIrregular() { Inflector::rules('plural', array( 'irregular' => array( 'mytable1' => 'mytables1', 'mytable2' => 'mytables2', 'mytable1_mytable2' => 'mytables1_mytables2', 'pregunta_frecuente' => 'preguntas_frecuentes', 'categoria_pregunta_frecuente' => 'categorias_preguntas_frecuentes', ) )); $this->assertEquals('preguntas_frecuentes', Inflector::pluralize('pregunta_frecuente')); $this->assertEquals( 'categorias_preguntas_frecuentes', Inflector::pluralize('categoria_pregunta_frecuente') ); $this->assertEquals( 'faq_categorias_preguntas_frecuentes', Inflector::pluralize('faq_categoria_pregunta_frecuente') ); $this->assertEquals('mytables1', Inflector::pluralize('mytable1')); $this->assertEquals('mytables2', Inflector::pluralize('mytable2')); $this->assertEquals('mytables1_mytables2', Inflector::pluralize('mytable1_mytable2')); $this->assertEquals('mytables1_mytables2', Inflector::tableize('Mytable1Mytable2')); } /** * testInflectingMultiWordIrregulars * * @return void */ public function testInflectingMultiWordIrregulars() { // unset the default rules in order to avoid them possibly matching // the words in case the irregular regex won't match, the tests // should fail in that case Inflector::rules('plural', array( 'rules' => array(), )); Inflector::rules('singular', array( 'rules' => array(), )); $this->assertEquals(Inflector::singularize('wisdom teeth'), 'wisdom tooth'); $this->assertEquals(Inflector::singularize('wisdom-teeth'), 'wisdom-tooth'); $this->assertEquals(Inflector::singularize('wisdom_teeth'), 'wisdom_tooth'); $this->assertEquals(Inflector::pluralize('sweet potato'), 'sweet potatoes'); $this->assertEquals(Inflector::pluralize('sweet-potato'), 'sweet-potatoes'); $this->assertEquals(Inflector::pluralize('sweet_potato'), 'sweet_potatoes'); } /** * testInflectorSlug method * * @return void */ public function testInflectorSlug() { $result = Inflector::slug('Foo Bar: Not just for breakfast any-more'); $expected = 'Foo_Bar_Not_just_for_breakfast_any_more'; $this->assertEquals($expected, $result); $result = Inflector::slug('this/is/a/path'); $expected = 'this_is_a_path'; $this->assertEquals($expected, $result); $result = Inflector::slug('Foo Bar: Not just for breakfast any-more', "-"); $expected = 'Foo-Bar-Not-just-for-breakfast-any-more'; $this->assertEquals($expected, $result); $result = Inflector::slug('Foo Bar: Not just for breakfast any-more', "+"); $expected = 'Foo+Bar+Not+just+for+breakfast+any+more'; $this->assertEquals($expected, $result); $result = Inflector::slug('ร„pfel รœber ร–l grรผn รคrgert groรŸ รถko', '-'); $expected = 'Aepfel-Ueber-Oel-gruen-aergert-gross-oeko'; $this->assertEquals($expected, $result); $result = Inflector::slug('The truth - and- more- news', '-'); $expected = 'The-truth-and-more-news'; $this->assertEquals($expected, $result); $result = Inflector::slug('The truth: and more news', '-'); $expected = 'The-truth-and-more-news'; $this->assertEquals($expected, $result); $result = Inflector::slug('La langue franรงaise est un attribut de souverainetรฉ en France', '-'); $expected = 'La-langue-francaise-est-un-attribut-de-souverainete-en-France'; $this->assertEquals($expected, $result); $result = Inflector::slug('!@$#exciting stuff! - what !@-# was that?', '-'); $expected = 'exciting-stuff-what-was-that'; $this->assertEquals($expected, $result); $result = Inflector::slug('20% of profits went to me!', '-'); $expected = '20-of-profits-went-to-me'; $this->assertEquals($expected, $result); $result = Inflector::slug('#this melts your face1#2#3', '-'); $expected = 'this-melts-your-face1-2-3'; $this->assertEquals($expected, $result); $result = Inflector::slug('controller/action/ใ‚Šใ‚“ใ”/1'); $expected = 'controller_action_ใ‚Šใ‚“ใ”_1'; $this->assertEquals($expected, $result); $result = Inflector::slug('ใฎ่ฉฑใŒๅ‡บใŸใฎใงๅคงไธˆๅคซใ‹ใชใ‚ใจ'); $expected = 'ใฎ่ฉฑใŒๅ‡บใŸใฎใงๅคงไธˆๅคซใ‹ใชใ‚ใจ'; $this->assertEquals($expected, $result); $result = Inflector::slug('posts/view/ํ•œ๊ตญ์–ด/page:1/sort:asc'); $expected = 'posts_view_ํ•œ๊ตญ์–ด_page_1_sort_asc'; $this->assertEquals($expected, $result); $result = Inflector::slug("non\xc2\xa0breaking\xc2\xa0space"); $this->assertEquals('non_breaking_space', $result); } /** * Test slug() with a complete list of special chars. * * @return void */ public function testInflectorSlugCharList() { foreach (static::$maps as $language => $list) { foreach ($list as $from => $to) { $result = Inflector::slug($from); $this->assertEquals($to, $result, $from . ' (' . $language . ') should be ' . $to . ' - but is ' . $result); } } } /** * testInflectorSlugWithMap method * * @return void */ public function testInflectorSlugWithMap() { Inflector::rules('transliteration', array('/r/' => '1')); $result = Inflector::slug('replace every r'); $expected = '1eplace_eve1y_1'; $this->assertEquals($expected, $result); $result = Inflector::slug('replace every r', '_'); $expected = '1eplace_eve1y_1'; $this->assertEquals($expected, $result); } /** * testInflectorSlugWithMapOverridingDefault method * * @return void */ public function testInflectorSlugWithMapOverridingDefault() { Inflector::rules('transliteration', array('/รฅ/' => 'aa', '/รธ/' => 'oe')); $result = Inflector::slug('Testing รฆ รธ รฅ', '-'); $expected = 'Testing-ae-oe-aa'; $this->assertEquals($expected, $result); } /** * testInflectorUnderscore method * * @return void */ public function testInflectorUnderscore() { $this->assertSame(Inflector::underscore('TestThing'), 'test_thing'); $this->assertSame(Inflector::underscore('testThing'), 'test_thing'); $this->assertSame(Inflector::underscore('TestThingExtra'), 'test_thing_extra'); $this->assertSame(Inflector::underscore('testThingExtra'), 'test_thing_extra'); $this->assertSame(Inflector::underscore('testThingExtrรฅ'), 'test_thing_extrรฅ'); // Identical checks test the cache code path. $this->assertSame(Inflector::underscore('TestThing'), 'test_thing'); $this->assertSame(Inflector::underscore('testThing'), 'test_thing'); $this->assertSame(Inflector::underscore('TestThingExtra'), 'test_thing_extra'); $this->assertSame(Inflector::underscore('testThingExtra'), 'test_thing_extra'); $this->assertSame(Inflector::underscore('testThingExtrรฅ'), 'test_thing_extrรฅ'); // Test stupid values $this->assertSame(Inflector::underscore(''), ''); $this->assertSame(Inflector::underscore(0), '0'); $this->assertSame(Inflector::underscore(false), ''); } /** * Test camelize() * * @return void */ public function testCamelize() { $this->assertSame('BlogArticles', Inflector::camelize('blog_articles')); $this->assertSame('BlogArticles', Inflector::camelize('blog articles')); $this->assertSame('MyPlugin.MyClass', Inflector::camelize('MyPlugin.MyClass')); $this->assertSame('MyPlugin.MyClass', Inflector::camelize('my_plugin.MyClass')); $this->assertSame('MyPlugin.myClass', Inflector::camelize('MyPlugin.my_class')); } /** * testVariableNaming method * * @return void */ public function testVariableNaming() { $this->assertEquals(Inflector::variable('test_field'), 'testField'); $this->assertEquals(Inflector::variable('test_fieLd'), 'testFieLd'); $this->assertEquals(Inflector::variable('test field'), 'testField'); $this->assertEquals(Inflector::variable('Test_field'), 'testField'); } /** * testClassNaming method * * @return void */ public function testClassNaming() { $this->assertEquals(Inflector::classify('artists_genres'), 'ArtistsGenre'); $this->assertEquals(Inflector::classify('file_systems'), 'FileSystem'); $this->assertEquals(Inflector::classify('news'), 'News'); $this->assertEquals(Inflector::classify('bureaus'), 'Bureau'); } /** * testTableNaming method * * @return void */ public function testTableNaming() { $this->assertEquals('artists_genres', Inflector::tableize('ArtistsGenre')); $this->assertEquals('file_systems', Inflector::tableize('FileSystem')); $this->assertEquals('news', Inflector::tableize('News')); $this->assertEquals('bureaus', Inflector::tableize('Bureau')); } /** * testHumanization method * * @return void */ public function testHumanization() { $this->assertEquals('Posts', Inflector::humanize('posts')); $this->assertEquals('Posts Tags', Inflector::humanize('posts_tags')); $this->assertEquals('File Systems', Inflector::humanize('file_systems')); $this->assertEquals('FiLe SysTems', Inflector::humanize('FiLe_SysTems')); $this->assertEquals('Hello Wรถrld', Inflector::humanize('hello_wรถrld')); $this->assertEquals('็ฆๅฒก City', Inflector::humanize('็ฆๅฒก_city')); } /** * testCustomPluralRule method * * @return void */ public function testCustomPluralRule() { Inflector::rules('plural', array('/^(custom)$/i' => '\1izables')); $this->assertEquals(Inflector::pluralize('custom'), 'customizables'); Inflector::rules('plural', array('uninflected' => array('uninflectable'))); $this->assertEquals(Inflector::pluralize('uninflectable'), 'uninflectable'); Inflector::rules('plural', array( 'rules' => array('/^(alert)$/i' => '\1ables'), 'uninflected' => array('noflect', 'abtuse'), 'irregular' => array('amaze' => 'amazable', 'phone' => 'phonezes') )); $this->assertEquals(Inflector::pluralize('noflect'), 'noflect'); $this->assertEquals(Inflector::pluralize('abtuse'), 'abtuse'); $this->assertEquals(Inflector::pluralize('alert'), 'alertables'); $this->assertEquals(Inflector::pluralize('amaze'), 'amazable'); $this->assertEquals(Inflector::pluralize('phone'), 'phonezes'); } /** * testCustomSingularRule method * * @return void */ public function testCustomSingularRule() { Inflector::rules('singular', array('/(eple)r$/i' => '\1', '/(jente)r$/i' => '\1')); $this->assertEquals(Inflector::singularize('epler'), 'eple'); $this->assertEquals(Inflector::singularize('jenter'), 'jente'); Inflector::rules('singular', array( 'rules' => array('/^(bil)er$/i' => '\1', '/^(inflec|contribu)tors$/i' => '\1ta'), 'uninflected' => array('singulars'), 'irregular' => array('spins' => 'spinor') )); $this->assertEquals(Inflector::singularize('inflectors'), 'inflecta'); $this->assertEquals(Inflector::singularize('contributors'), 'contributa'); $this->assertEquals(Inflector::singularize('spins'), 'spinor'); $this->assertEquals(Inflector::singularize('singulars'), 'singulars'); } /** * testCustomTransliterationRule method * * @return void */ public function testCustomTransliterationRule() { $this->assertEquals(Inflector::slug('Testing รฆ รธ รฅ'), 'Testing_ae_o_a'); Inflector::rules('transliteration', array('/รฅ/' => 'aa', '/รธ/' => 'oe')); $this->assertEquals(Inflector::slug('Testing รฆ รธ รฅ'), 'Testing_ae_oe_aa'); Inflector::rules('transliteration', array('/รค|รฆ/' => 'ae', '/รฅ/' => 'aa'), true); $this->assertEquals(Inflector::slug('Testing รฆ รธ รฅ'), 'Testing_ae_รธ_aa'); } /** * test that setting new rules clears the inflector caches. * * @return void */ public function testRulesClearsCaches() { $this->assertEquals(Inflector::singularize('Bananas'), 'Banana'); $this->assertEquals(Inflector::tableize('Banana'), 'bananas'); $this->assertEquals(Inflector::pluralize('Banana'), 'Bananas'); Inflector::rules('singular', array( 'rules' => array('/(.*)nas$/i' => '\1zzz') )); $this->assertEquals('Banazzz', Inflector::singularize('Bananas'), 'Was inflected with old rules.'); Inflector::rules('plural', array( 'rules' => array('/(.*)na$/i' => '\1zzz'), 'irregular' => array('corpus' => 'corpora') )); $this->assertEquals(Inflector::pluralize('Banana'), 'Banazzz', 'Was inflected with old rules.'); $this->assertEquals(Inflector::pluralize('corpus'), 'corpora', 'Was inflected with old irregular form.'); } /** * Test resetting inflection rules. * * @return void */ public function testCustomRuleWithReset() { $uninflected = array('atlas', 'lapis', 'onibus', 'pires', 'virus', '.*x'); $pluralIrregular = array('as' => 'ases'); Inflector::rules('singular', array( 'rules' => array('/^(.*)(a|e|o|u)is$/i' => '\1\2l'), 'uninflected' => $uninflected, ), true); Inflector::rules('plural', array( 'rules' => array( '/^(.*)(a|e|o|u)l$/i' => '\1\2is', ), 'uninflected' => $uninflected, 'irregular' => $pluralIrregular ), true); $this->assertEquals(Inflector::pluralize('Alcool'), 'Alcoois'); $this->assertEquals(Inflector::pluralize('Atlas'), 'Atlas'); $this->assertEquals(Inflector::singularize('Alcoois'), 'Alcool'); $this->assertEquals(Inflector::singularize('Atlas'), 'Atlas'); } } cakephp-2.8.0/lib/Cake/Test/Case/Utility/ObjectCollectionTest.php000066400000000000000000000420221265552240500246030ustar00rootroot00000000000000_Collection = $collection; $this->settings = $settings; } } /** * First Extension of Generic Object */ class FirstGenericObject extends GenericObject { /** * A generic callback * * @return void */ public function callback() { } } /** * Second Extension of Generic Object */ class SecondGenericObject extends GenericObject { /** * @return void */ public function callback() { } } /** * Third Extension of Generic Object */ class ThirdGenericObject extends GenericObject { /** * @return void */ public function callback() { } } /** * A collection of Generic objects */ class GenericObjectCollection extends ObjectCollection { /** * Loads a generic object * * @param string $object Object name * @param array $settings Settings array * @return array List of loaded objects */ public function load($object, $settings = array()) { list(, $name) = pluginSplit($object); if (isset($this->_loaded[$name])) { return $this->_loaded[$name]; } $objectClass = $name . 'GenericObject'; $this->_loaded[$name] = new $objectClass($this, $settings); $enable = isset($settings['enabled']) ? $settings['enabled'] : true; if ($enable === true) { $this->enable($name); } return $this->_loaded[$name]; } /** * Helper method for adding/overwriting enabled objects including * settings * * @param string $name Name of the object * @param Object $object The object to use * @param array $settings Settings to apply for the object * @return array Loaded objects */ public function setObject($name, $object, $settings = array()) { $this->_loaded[$name] = $object; if (isset($settings['priority'])) { $this->setPriority($name, $settings['priority']); } $enable = isset($settings['enabled']) ? $settings['enabled'] : true; if ($enable === true) { $this->enable($name); } return $this->_loaded; } } class ObjectCollectionTest extends CakeTestCase { /** * setUp * * @return void */ public function setUp() { parent::setUp(); $this->Objects = new GenericObjectCollection(); } /** * tearDown * * @return void */ public function tearDown() { parent::tearDown(); unset($this->Objects); } /** * test triggering callbacks on loaded helpers * * @return void */ public function testLoad() { $result = $this->Objects->load('First'); $this->assertInstanceOf('FirstGenericObject', $result); $this->assertInstanceOf('FirstGenericObject', $this->Objects->First); $result = $this->Objects->loaded(); $this->assertEquals(array('First'), $result, 'loaded() results are wrong.'); $this->assertTrue($this->Objects->enabled('First')); $result = $this->Objects->load('First'); $this->assertSame($result, $this->Objects->First); } /** * test unload() * * @return void */ public function testUnload() { $this->Objects->load('First'); $this->Objects->load('Second'); $result = $this->Objects->loaded(); $this->assertEquals(array('First', 'Second'), $result, 'loaded objects are wrong'); $this->Objects->unload('First'); $this->assertFalse(isset($this->Objects->First)); $this->assertTrue(isset($this->Objects->Second)); $result = $this->Objects->loaded(); $this->assertEquals(array('Second'), $result, 'loaded objects are wrong'); $result = $this->Objects->loaded(); $this->assertEquals(array('Second'), $result, 'enabled objects are wrong'); } /** * Tests set() * * @return void */ public function testSet() { $this->Objects->load('First'); $result = $this->Objects->loaded(); $this->assertEquals(array('First'), $result, 'loaded objects are wrong'); $result = $this->Objects->set('First', new SecondGenericObject($this->Objects)); $this->assertInstanceOf('SecondGenericObject', $result['First'], 'set failed'); $result = $this->Objects->set('Second', new SecondGenericObject($this->Objects)); $this->assertInstanceOf('SecondGenericObject', $result['Second'], 'set failed'); $this->assertEquals(2, count($result)); } /** * creates mock classes for testing * * @return void */ protected function _makeMockClasses() { $this->FirstGenericObject = $this->getMock('FirstGenericObject', array(), array(), '', false); $this->SecondGenericObject = $this->getMock('SecondGenericObject', array(), array(), '', false); $this->ThirdGenericObject = $this->getMock('ThirdGenericObject', array(), array(), '', false); } /** * test triggering callbacks. * * @return void */ public function testTrigger() { $this->_makeMockClasses(); $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject); $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject); $this->Objects->TriggerMockFirst->expects($this->once()) ->method('callback') ->will($this->returnValue(true)); $this->Objects->TriggerMockSecond->expects($this->once()) ->method('callback') ->will($this->returnValue(true)); $this->assertTrue($this->Objects->trigger('callback')); } /** * test trigger and disabled objects * * @return void */ public function testTriggerWithDisabledObjects() { $this->_makeMockClasses(); $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject); $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject, array('enabled' => false)); $this->Objects->TriggerMockFirst->expects($this->once()) ->method('callback') ->will($this->returnValue(true)); $this->Objects->TriggerMockSecond->expects($this->never()) ->method('callback') ->will($this->returnValue(true)); $this->assertTrue($this->Objects->trigger('callback', array())); } /** * test that the collectReturn option works. * * @return void */ public function testTriggerWithCollectReturn() { $this->_makeMockClasses(); $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject); $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject); $this->Objects->TriggerMockFirst->expects($this->once()) ->method('callback') ->will($this->returnValue(array('one', 'two'))); $this->Objects->TriggerMockSecond->expects($this->once()) ->method('callback') ->will($this->returnValue(array('three', 'four'))); $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true)); $expected = array( array('one', 'two'), array('three', 'four') ); $this->assertEquals($expected, $result); } /** * test that trigger with break & breakOn works. * * @return void */ public function testTriggerWithBreak() { $this->_makeMockClasses(); $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject); $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject); $this->Objects->TriggerMockFirst->expects($this->once()) ->method('callback') ->will($this->returnValue(false)); $this->Objects->TriggerMockSecond->expects($this->never()) ->method('callback'); $result = $this->Objects->trigger( 'callback', array(), array('break' => true, 'breakOn' => false) ); $this->assertFalse($result); } /** * test that trigger with modParams works. * * @return void */ public function testTriggerWithModParams() { $this->_makeMockClasses(); $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject); $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject); $this->Objects->TriggerMockFirst->expects($this->once()) ->method('callback') ->with(array('value')) ->will($this->returnValue(array('new value'))); $this->Objects->TriggerMockSecond->expects($this->once()) ->method('callback') ->with(array('new value')) ->will($this->returnValue(array('newer value'))); $result = $this->Objects->trigger( 'callback', array(array('value')), array('modParams' => 0) ); $this->assertEquals(array('newer value'), $result); } /** * test that setting modParams to an index that doesn't exist doesn't cause errors. * * @expectedException CakeException * @return void */ public function testTriggerModParamsInvalidIndex() { $this->_makeMockClasses(); $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject); $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject); $this->Objects->TriggerMockFirst->expects($this->never()) ->method('callback'); $this->Objects->TriggerMockSecond->expects($this->never()) ->method('callback'); $this->Objects->trigger( 'callback', array(array('value')), array('modParams' => 2) ); } /** * test that returning null doesn't modify parameters. * * @return void */ public function testTriggerModParamsNullIgnored() { $this->_makeMockClasses(); $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject); $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject); $this->Objects->TriggerMockFirst->expects($this->once()) ->method('callback') ->with(array('value')) ->will($this->returnValue(null)); $this->Objects->TriggerMockSecond->expects($this->once()) ->method('callback') ->with(array('value')) ->will($this->returnValue(array('new value'))); $result = $this->Objects->trigger( 'callback', array(array('value')), array('modParams' => 0) ); $this->assertEquals(array('new value'), $result); } /** * test order of callbacks triggering based on priority. * * @return void */ public function testTriggerPriority() { $this->_makeMockClasses(); $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject); $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject, array('priority' => 5)); $this->Objects->TriggerMockFirst->expects($this->any()) ->method('callback') ->will($this->returnValue('1st')); $this->Objects->TriggerMockSecond->expects($this->any()) ->method('callback') ->will($this->returnValue('2nd')); $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true)); $expected = array( '2nd', '1st' ); $this->assertEquals($expected, $result); $this->Objects->setObject('TriggerMockThird', $this->ThirdGenericObject, array('priority' => 7)); $this->Objects->TriggerMockThird->expects($this->any()) ->method('callback') ->will($this->returnValue('3rd')); $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true)); $expected = array( '2nd', '3rd', '1st' ); $this->assertEquals($expected, $result); $this->Objects->disable('TriggerMockFirst'); $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true)); $expected = array( '2nd', '3rd' ); $this->assertEquals($expected, $result); $this->Objects->enable('TriggerMockFirst'); $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true)); $expected = array( '2nd', '3rd', '1st' ); $this->assertEquals($expected, $result); $this->Objects->disable('TriggerMockThird'); $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true)); $expected = array( '2nd', '1st' ); $this->assertEquals($expected, $result); $this->Objects->enable('TriggerMockThird', false); $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true)); $expected = array( '2nd', '1st', '3rd' ); $this->assertEquals($expected, $result); $this->Objects->setPriority('TriggerMockThird', 1); $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true)); $expected = array( '3rd', '2nd', '1st' ); $this->assertEquals($expected, $result); $this->Objects->disable('TriggerMockThird'); $this->Objects->setPriority('TriggerMockThird', 11); $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true)); $expected = array( '2nd', '1st' ); $this->assertEquals($expected, $result); $this->Objects->enable('TriggerMockThird'); $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true)); $expected = array( '2nd', '1st', '3rd' ); $this->assertEquals($expected, $result); $this->Objects->setPriority('TriggerMockThird'); $result = $this->Objects->trigger('callback', array(), array('collectReturn' => true)); $expected = array( '2nd', '1st', '3rd' ); $this->assertEquals($expected, $result); } /** * test normalizeObjectArray * * @return void */ public function testnormalizeObjectArray() { $components = array( 'Html', 'Foo.Bar' => array('one', 'two'), 'Something', 'Banana.Apple' => array('foo' => 'bar') ); $result = ObjectCollection::normalizeObjectArray($components); $expected = array( 'Html' => array('class' => 'Html', 'settings' => array()), 'Bar' => array('class' => 'Foo.Bar', 'settings' => array('one', 'two')), 'Something' => array('class' => 'Something', 'settings' => array()), 'Apple' => array('class' => 'Banana.Apple', 'settings' => array('foo' => 'bar')), ); $this->assertEquals($expected, $result); // This is the result after Controller::_mergeVars $components = array( 'Html' => null, 'Foo.Bar' => array('one', 'two'), 'Something' => null, 'Banana.Apple' => array('foo' => 'bar') ); $result = ObjectCollection::normalizeObjectArray($components); $this->assertEquals($expected, $result); } /** * tests that passing an instance of CakeEvent to trigger will prepend the subject to the list of arguments * * @return void * @triggers callback $subjectClass, array('first argument') */ public function testDispatchEventWithSubject() { $this->_makeMockClasses(); $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject); $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject); $subjectClass = new Object(); $this->Objects->TriggerMockFirst->expects($this->once()) ->method('callback') ->with($subjectClass, 'first argument') ->will($this->returnValue(true)); $this->Objects->TriggerMockSecond->expects($this->once()) ->method('callback') ->with($subjectClass, 'first argument') ->will($this->returnValue(true)); $event = new CakeEvent('callback', $subjectClass, array('first argument')); $this->assertTrue($this->Objects->trigger($event)); } /** * tests that passing an instance of CakeEvent to trigger with omitSubject property * will NOT prepend the subject to the list of arguments * * @return void * @triggers callback $subjectClass, array('first argument') */ public function testDispatchEventNoSubject() { $this->_makeMockClasses(); $this->Objects->setObject('TriggerMockFirst', $this->FirstGenericObject); $this->Objects->setObject('TriggerMockSecond', $this->SecondGenericObject); $subjectClass = new Object(); $this->Objects->TriggerMockFirst->expects($this->once()) ->method('callback') ->with('first argument') ->will($this->returnValue(true)); $this->Objects->TriggerMockSecond->expects($this->once()) ->method('callback') ->with('first argument') ->will($this->returnValue(true)); $event = new CakeEvent('callback', $subjectClass, array('first argument')); $event->omitSubject = true; $this->assertTrue($this->Objects->trigger($event)); } /** * test that the various methods ignore plugin prefixes * * plugin prefixes should be removed consistently as load() will * remove them. Furthermore the __get() method does not support * names with '.' in them. * * @return void */ public function testPluginPrefixes() { $this->Objects->load('TestPlugin.First'); $this->assertTrue($this->Objects->loaded('First')); $this->assertTrue($this->Objects->loaded('TestPlugin.First')); $this->assertTrue($this->Objects->enabled('First')); $this->assertTrue($this->Objects->enabled('TestPlugin.First')); $this->assertNull($this->Objects->disable('TestPlugin.First')); $this->assertFalse($this->Objects->enabled('First')); $this->assertFalse($this->Objects->enabled('TestPlugin.First')); $this->assertNull($this->Objects->enable('TestPlugin.First')); $this->assertTrue($this->Objects->enabled('First')); $this->assertTrue($this->Objects->enabled('TestPlugin.First')); $this->Objects->setPriority('TestPlugin.First', 1000); $result = $this->Objects->prioritize(); $this->assertEquals(1000, $result['First'][0]); } } cakephp-2.8.0/lib/Cake/Test/Case/Utility/SanitizeTest.php000066400000000000000000000375501265552240500231610ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Utility * @since CakePHP(tm) v 1.2.0.5428 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Sanitize', 'Utility'); /** * DataTest class * * @package Cake.Test.Case.Utility */ class SanitizeDataTest extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'data_tests'; } /** * Article class * * @package Cake.Test.Case.Utility */ class SanitizeArticle extends CakeTestModel { /** * useTable property * * @var string */ public $useTable = 'articles'; } /** * SanitizeTest class * * @package Cake.Test.Case.Utility */ class SanitizeTest extends CakeTestCase { /** * autoFixtures property * * @var bool */ public $autoFixtures = false; /** * fixtures property * * @var array */ public $fixtures = array('core.data_test', 'core.article'); /** * testEscapeAlphaNumeric method * * @return void */ public function testEscapeAlphaNumeric() { $resultAlpha = Sanitize::escape('abc', 'test'); $this->assertEquals('abc', $resultAlpha); $resultNumeric = Sanitize::escape('123', 'test'); $this->assertEquals('123', $resultNumeric); $resultNumeric = Sanitize::escape(1234, 'test'); $this->assertEquals(1234, $resultNumeric); $resultNumeric = Sanitize::escape(1234.23, 'test'); $this->assertEquals(1234.23, $resultNumeric); $resultNumeric = Sanitize::escape('#1234.23', 'test'); $this->assertEquals('#1234.23', $resultNumeric); $resultNull = Sanitize::escape(null, 'test'); $this->assertEquals(null, $resultNull); $resultNull = Sanitize::escape(false, 'test'); $this->assertEquals(false, $resultNull); $resultNull = Sanitize::escape(true, 'test'); $this->assertEquals(true, $resultNull); } /** * testClean method * * @return void */ public function testClean() { $string = 'test & "quote" \'other\' ;.$ symbol.' . "\r" . 'another line'; $expected = 'test & "quote" 'other' ;.$ symbol.another line'; $result = Sanitize::clean($string, array('connection' => 'test')); $this->assertEquals($expected, $result); $string = 'test & "quote" \'other\' ;.$ symbol.' . "\r" . 'another line'; $expected = 'test & ' . Sanitize::escape('"quote"', 'test') . ' ' . Sanitize::escape('\'other\'', 'test') . ' ;.$ symbol.another line'; $result = Sanitize::clean($string, array('encode' => false, 'connection' => 'test')); $this->assertEquals($expected, $result); $string = 'test & "quote" \'other\' ;.$ \\$ symbol.' . "\r" . 'another line'; $expected = 'test & "quote" \'other\' ;.$ $ symbol.another line'; $result = Sanitize::clean($string, array('encode' => false, 'escape' => false, 'connection' => 'test')); $this->assertEquals($expected, $result); $string = 'test & "quote" \'other\' ;.$ \\$ symbol.' . "\r" . 'another line'; $expected = 'test & "quote" \'other\' ;.$ \\$ symbol.another line'; $result = Sanitize::clean($string, array('encode' => false, 'escape' => false, 'dollar' => false, 'connection' => 'test')); $this->assertEquals($expected, $result); $string = 'test & "quote" \'other\' ;.$ symbol.' . "\r" . 'another line'; $expected = 'test & "quote" \'other\' ;.$ symbol.' . "\r" . 'another line'; $result = Sanitize::clean($string, array('encode' => false, 'escape' => false, 'carriage' => false, 'connection' => 'test')); $this->assertEquals($expected, $result); $array = array(array('test & "quote" \'other\' ;.$ symbol.' . "\r" . 'another line')); $expected = array(array('test & "quote" 'other' ;.$ symbol.another line')); $result = Sanitize::clean($array, array('connection' => 'test')); $this->assertEquals($expected, $result); $array = array(array('test & "quote" \'other\' ;.$ \\$ symbol.' . "\r" . 'another line')); $expected = array(array('test & "quote" \'other\' ;.$ $ symbol.another line')); $result = Sanitize::clean($array, array('encode' => false, 'escape' => false, 'connection' => 'test')); $this->assertEquals($expected, $result); $array = array(array('test odd ร„ spacesรฉ')); $expected = array(array('test odd Ä spacesé')); $result = Sanitize::clean($array, array('odd_spaces' => false, 'escape' => false, 'connection' => 'test')); $this->assertEquals($expected, $result); $array = array(array('\\$', array('key' => 'test & "quote" \'other\' ;.$ \\$ symbol.' . "\r" . 'another line'))); $expected = array(array('$', array('key' => 'test & "quote" \'other\' ;.$ $ symbol.another line'))); $result = Sanitize::clean($array, array('encode' => false, 'escape' => false, 'connection' => 'test')); $this->assertEquals($expected, $result); $string = ''; $expected = ''; $result = Sanitize::clean($string, array('connection' => 'test')); $this->assertEquals($expected, $result); $data = array( 'Grant' => array( 'title' => '2 o clock grant', 'grant_peer_review_id' => 3, 'institution_id' => 5, 'created_by' => 1, 'modified_by' => 1, 'created' => '2010-07-15 14:11:00', 'modified' => '2010-07-19 10:45:41' ), 'GrantsMember' => array( 0 => array( 'id' => 68, 'grant_id' => 120, 'member_id' => 16, 'program_id' => 29, 'pi_percent_commitment' => 1 ) ) ); $result = Sanitize::clean($data, array('connection' => 'test')); $this->assertEquals($data, $result); } /** * testHtml method * * @return void */ public function testHtml() { $string = '

This is a test string & so is this

'; $expected = 'This is a test string & so is this'; $result = Sanitize::html($string, array('remove' => true)); $this->assertEquals($expected, $result); $string = 'The "lazy" dog \'jumped\' & flew over the moon. If (1+1) = 2 is true, (2-1) = 1 is also true'; $expected = 'The "lazy" dog 'jumped' & flew over the moon. If (1+1) = 2 <em>is</em> true, (2-1) = 1 is also true'; $result = Sanitize::html($string); $this->assertEquals($expected, $result); $string = 'The "lazy" dog \'jumped\''; $expected = 'The "lazy" dog \'jumped\''; $result = Sanitize::html($string, array('quotes' => ENT_COMPAT)); $this->assertEquals($expected, $result); $string = 'The "lazy" dog \'jumped\''; $result = Sanitize::html($string, array('quotes' => ENT_NOQUOTES)); $this->assertEquals($string, $result); $string = 'The "lazy" dog \'jumped\' & flew over the moon. If (1+1) = 2 is true, (2-1) = 1 is also true'; $expected = 'The "lazy" dog 'jumped' & flew over the moon. If (1+1) = 2 <em>is</em> true, (2-1) = 1 is also true'; $result = Sanitize::html($string); $this->assertEquals($expected, $result); $string = 'The "lazy" dog & his friend Apple® conquered the world'; $expected = 'The "lazy" dog & his friend Apple&reg; conquered the world'; $result = Sanitize::html($string); $this->assertEquals($expected, $result); $string = 'The "lazy" dog & his friend Apple® conquered the world'; $expected = 'The "lazy" dog & his friend Apple® conquered the world'; $result = Sanitize::html($string, array('double' => false)); $this->assertEquals($expected, $result); } /** * testStripWhitespace method * * @return void */ public function testStripWhitespace() { $string = "This sentence \t\t\t has lots of \n\n white\nspace \rthat \r\n needs to be \t \n trimmed."; $expected = "This sentence has lots of whitespace that needs to be trimmed."; $result = Sanitize::stripWhitespace($string); $this->assertEquals($expected, $result); $text = 'I love รŸรกโ€ รถโˆš letters.'; $result = Sanitize::stripWhitespace($text); $expected = 'I love รŸรกโ€ รถโˆš letters.'; $this->assertEquals($expected, $result); } /** * testParanoid method * * @return void */ public function testParanoid() { $string = 'I would like to !%@#% & dance & sing ^$&*()-+'; $expected = 'Iwouldliketodancesing'; $result = Sanitize::paranoid($string); $this->assertEquals($expected, $result); $string = array('This |s th% s0ng that never ends it g*es', 'on and on my friends, b^ca#use it is the', 'so&g th===t never ends.'); $expected = array('This s th% s0ng that never ends it g*es', 'on and on my friends bcause it is the', 'sog tht never ends.'); $result = Sanitize::paranoid($string, array('%', '*', '.', ' ')); $this->assertEquals($expected, $result); $string = "anything' OR 1 = 1"; $expected = 'anythingOR11'; $result = Sanitize::paranoid($string); $this->assertEquals($expected, $result); $string = "x' AND email IS NULL; --"; $expected = 'xANDemailISNULL'; $result = Sanitize::paranoid($string); $this->assertEquals($expected, $result); $string = "x' AND 1=(SELECT COUNT(*) FROM users); --"; $expected = 'xAND1SELECTCOUNTFROMusers'; $result = Sanitize::paranoid($string); $this->assertEquals($expected, $result); $string = "x'; DROP TABLE members; --"; $expected = 'xDROPTABLEmembers'; $result = Sanitize::paranoid($string); $this->assertEquals($expected, $result); } /** * testStripImages method * * @return void */ public function testStripImages() { $string = 'my image'; $expected = 'my image
'; $result = Sanitize::stripImages($string); $this->assertEquals($expected, $result); $string = ''; $expected = ''; $result = Sanitize::stripImages($string); $this->assertEquals($expected, $result); $string = 'test image alt'; $expected = 'test image alt
'; $result = Sanitize::stripImages($string); $this->assertEquals($expected, $result); $string = ''; $expected = ''; $result = Sanitize::stripImages($string); $this->assertEquals($expected, $result); } /** * testStripScripts method * * @return void */ public function testStripScripts() { $string = ''; $expected = ''; $result = Sanitize::stripScripts($string); $this->assertEquals($expected, $result); $string = '' . "\n" . '' . "\n" . '' . "\n" . ''; $expected = "\n" . '' . "\n" . '' . "\n" . ''; $result = Sanitize::stripScripts($string); $this->assertEquals($expected, $result); $string = ''; $expected = ''; $result = Sanitize::stripScripts($string); $this->assertEquals($expected, $result); $string = ''; $expected = ''; $result = Sanitize::stripScripts($string); $this->assertEquals($expected, $result); $string = ''; $expected = ''; $result = Sanitize::stripScripts($string); $this->assertEquals($expected, $result); $string = ''; $expected = ''; $result = Sanitize::stripScripts($string); $this->assertEquals($expected, $result); $string = << text HTML; $expected = "text\n\ntext"; $result = Sanitize::stripScripts($string); $this->assertTextEquals($expected, $result); $string = << text HTML; $expected = "text\n\ntext"; $result = Sanitize::stripScripts($string); $this->assertTextEquals($expected, $result); } /** * testStripAll method * * @return void */ public function testStripAll() { $string = '"/>'; $expected = '"/>'; $result = Sanitize::stripAll($string); $this->assertEquals($expected, $result); $string = ''; $expected = ''; $result = Sanitize::stripAll($string); $this->assertEquals($expected, $result); $string = '<'; $expected = '<'; $result = Sanitize::stripAll($string); $this->assertEquals($expected, $result); $string = '' . "\n" . "

This is ok \t\n text

\n" . '' . "\n" . ''; $expected = '

This is ok text

'; $result = Sanitize::stripAll($string); $this->assertEquals($expected, $result); } /** * testStripTags method * * @return void */ public function testStripTags() { $string = '

Headline

My Link could go to a bad site

'; $expected = 'Headline

My Link could go to a bad site

'; $result = Sanitize::stripTags($string, 'h2', 'a'); $this->assertEquals($expected, $result); $string = ''; $expected = ' '; $result = Sanitize::stripTags($string, 'script'); $this->assertEquals($expected, $result); $string = '

Important

Additional information here . Read even more here

'; $expected = 'Important

Additional information here . Read even more here

'; $result = Sanitize::stripTags($string, 'h2', 'a'); $this->assertEquals($expected, $result); $string = '

Important

Additional information here . Read even more here

'; $expected = 'Important

Additional information here . Read even more here

'; $result = Sanitize::stripTags($string, 'h2', 'a', 'img'); $this->assertEquals($expected, $result); $string = 'Important message!
This message will self destruct!'; $expected = 'Important message!
This message will self destruct!'; $result = Sanitize::stripTags($string, 'b'); $this->assertEquals($expected, $result); $string = 'Important message!
This message will self destruct!'; $expected = 'Important message!
This message will self destruct!'; $result = Sanitize::stripTags($string, 'b'); $this->assertEquals($expected, $result); $string = '

Important

Additional information here . Read even more here

'; $expected = 'Important

Additional information here . Read even more here

'; $result = Sanitize::stripTags($string, 'h2', 'a', 'img'); $this->assertEquals($expected, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Utility/SecurityTest.php000066400000000000000000000271741265552240500232030ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @since CakePHP(tm) v 1.2.0.5432 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Security', 'Utility'); /** * SecurityTest class * * @package Cake.Test.Case.Utility */ class SecurityTest extends CakeTestCase { /** * sut property * * @var mixed */ public $sut = null; /** * testInactiveMins method * * @return void */ public function testInactiveMins() { Configure::write('Security.level', 'high'); $this->assertEquals(10, Security::inactiveMins()); Configure::write('Security.level', 'medium'); $this->assertEquals(100, Security::inactiveMins()); Configure::write('Security.level', 'low'); $this->assertEquals(300, Security::inactiveMins()); } /** * testGenerateAuthkey method * * @return void */ public function testGenerateAuthkey() { $this->assertEquals(strlen(Security::generateAuthKey()), 40); } /** * testValidateAuthKey method * * @return void */ public function testValidateAuthKey() { $authKey = Security::generateAuthKey(); $this->assertTrue(Security::validateAuthKey($authKey)); } /** * testHashInvalidSalt method * * @expectedException PHPUnit_Framework_Error * @return void */ public function testHashInvalidSalt() { Security::hash('someKey', 'blowfish', true); } /** * testHashAnotherInvalidSalt * * @expectedException PHPUnit_Framework_Error * @return void */ public function testHashAnotherInvalidSalt() { Security::hash('someKey', 'blowfish', '$1$lksdjoijfaoijs'); } /** * testHashYetAnotherInvalidSalt * * @expectedException PHPUnit_Framework_Error * @return void */ public function testHashYetAnotherInvalidSalt() { Security::hash('someKey', 'blowfish', '$2a$10$123'); } /** * testHashInvalidCost method * * @expectedException PHPUnit_Framework_Error * @return void */ public function testHashInvalidCost() { Security::setCost(1000); } /** * testHash method * * @return void */ public function testHash() { $_hashType = Security::$hashType; $key = 'someKey'; $hash = 'someHash'; $this->assertSame(40, strlen(Security::hash($key, null, false))); $this->assertSame(40, strlen(Security::hash($key, 'sha1', false))); $this->assertSame(40, strlen(Security::hash($key, null, true))); $this->assertSame(40, strlen(Security::hash($key, 'sha1', true))); $result = Security::hash($key, null, $hash); $this->assertSame($result, 'e38fcb877dccb6a94729a81523851c931a46efb1'); $result = Security::hash($key, 'sha1', $hash); $this->assertSame($result, 'e38fcb877dccb6a94729a81523851c931a46efb1'); $hashType = 'sha1'; Security::setHash($hashType); $this->assertSame($hashType, Security::$hashType); $this->assertSame(40, strlen(Security::hash($key, null, true))); $this->assertSame(40, strlen(Security::hash($key, null, false))); $this->assertSame(32, strlen(Security::hash($key, 'md5', false))); $this->assertSame(32, strlen(Security::hash($key, 'md5', true))); $hashType = 'md5'; Security::setHash($hashType); $this->assertSame($hashType, Security::$hashType); $this->assertSame(32, strlen(Security::hash($key, null, false))); $this->assertSame(32, strlen(Security::hash($key, null, true))); if (!function_exists('hash') && !function_exists('mhash')) { $this->assertSame(32, strlen(Security::hash($key, 'sha256', false))); $this->assertSame(32, strlen(Security::hash($key, 'sha256', true))); } else { $this->assertSame(64, strlen(Security::hash($key, 'sha256', false))); $this->assertSame(64, strlen(Security::hash($key, 'sha256', true))); } Security::setHash($_hashType); } /** * Test that hash() works with blowfish. * * @return void */ public function testHashBlowfish() { Security::setCost(10); $test = Security::hash('password', 'blowfish'); $this->skipIf(strpos($test, '$2a$') === false, 'Blowfish hashes are incorrect.'); $_hashType = Security::$hashType; $key = 'someKey'; $hashType = 'blowfish'; Security::setHash($hashType); $this->assertSame($hashType, Security::$hashType); $this->assertSame(60, strlen(Security::hash($key, null, false))); $password = $submittedPassword = $key; $storedPassword = Security::hash($password); $hashedPassword = Security::hash($submittedPassword, null, $storedPassword); $this->assertSame($storedPassword, $hashedPassword); $submittedPassword = 'someOtherKey'; $hashedPassword = Security::hash($submittedPassword, null, $storedPassword); $this->assertNotSame($storedPassword, $hashedPassword); $expected = sha1('customsaltsomevalue'); $result = Security::hash('somevalue', 'sha1', 'customsalt'); $this->assertSame($expected, $result); $oldSalt = Configure::read('Security.salt'); Configure::write('Security.salt', 'customsalt'); $expected = sha1('customsaltsomevalue'); $result = Security::hash('somevalue', 'sha1', true); $this->assertSame($expected, $result); Configure::write('Security.salt', $oldSalt); Security::setHash($_hashType); } /** * testCipher method * * @return void */ public function testCipher() { $length = 10; $txt = ''; for ($i = 0; $i < $length; $i++) { $txt .= mt_rand(0, 255); } $key = 'my_key'; $result = Security::cipher($txt, $key); $this->assertEquals($txt, Security::cipher($result, $key)); $txt = ''; $key = 'my_key'; $result = Security::cipher($txt, $key); $this->assertEquals($txt, Security::cipher($result, $key)); $txt = 123456; $key = 'my_key'; $result = Security::cipher($txt, $key); $this->assertEquals($txt, Security::cipher($result, $key)); $txt = '123456'; $key = 'my_key'; $result = Security::cipher($txt, $key); $this->assertEquals($txt, Security::cipher($result, $key)); } /** * testCipherEmptyKey method * * @expectedException PHPUnit_Framework_Error * @return void */ public function testCipherEmptyKey() { $txt = 'some_text'; $key = ''; Security::cipher($txt, $key); } /** * testRijndael method * * @return void */ public function testRijndael() { $this->skipIf(!function_exists('mcrypt_encrypt')); $txt = 'The quick brown fox jumped over the lazy dog.'; $key = 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi'; $result = Security::rijndael($txt, $key, 'encrypt'); $this->assertEquals($txt, Security::rijndael($result, $key, 'decrypt')); $result = Security::rijndael($key, $txt, 'encrypt'); $this->assertEquals($key, Security::rijndael($result, $txt, 'decrypt')); $result = Security::rijndael('', $key, 'encrypt'); $this->assertEquals('', Security::rijndael($result, $key, 'decrypt')); $key = 'this is my key of over 32 chars, yes it is'; $result = Security::rijndael($txt, $key, 'encrypt'); $this->assertEquals($txt, Security::rijndael($result, $key, 'decrypt')); } /** * Test that rijndael() can still decrypt values with a fixed iv. * * @return void */ public function testRijndaelBackwardCompatibility() { $this->skipIf(!function_exists('mcrypt_encrypt')); $txt = 'The quick brown fox jumped over the lazy dog.'; $key = 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi'; // Encrypted before random iv $value = base64_decode('1WPjnq96LMzLGwNgmudHF+cAIqVUN5DaUZEpf5tm1EzSgt5iYY9o3d66iRI/fKJLTlTVGsa8HzW0jDNitmVXoQ=='); $this->assertEquals($txt, Security::rijndael($value, $key, 'decrypt')); } /** * testRijndaelInvalidOperation method * * @expectedException PHPUnit_Framework_Error * @return void */ public function testRijndaelInvalidOperation() { $txt = 'The quick brown fox jumped over the lazy dog.'; $key = 'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi'; Security::rijndael($txt, $key, 'foo'); } /** * testRijndaelInvalidKey method * * @expectedException PHPUnit_Framework_Error * @return void */ public function testRijndaelInvalidKey() { $txt = 'The quick brown fox jumped over the lazy dog.'; $key = 'too small'; Security::rijndael($txt, $key, 'encrypt'); } /** * Test encrypt/decrypt. * * @return void */ public function testEncryptDecrypt() { $txt = 'The quick brown fox'; $key = 'This key is longer than 32 bytes long.'; $result = Security::encrypt($txt, $key); $this->assertNotEquals($txt, $result, 'Should be encrypted.'); $this->assertNotEquals($result, Security::encrypt($txt, $key), 'Each result is unique.'); $this->assertEquals($txt, Security::decrypt($result, $key)); } /** * Test that changing the key causes decryption to fail. * * @return void */ public function testDecryptKeyFailure() { $txt = 'The quick brown fox'; $key = 'This key is longer than 32 bytes long.'; Security::encrypt($txt, $key); $key = 'Not the same key. This one will fail'; $this->assertFalse(Security::decrypt($txt, $key), 'Modified key will fail.'); } /** * Test that decrypt fails when there is an hmac error. * * @return void */ public function testDecryptHmacFailure() { $txt = 'The quick brown fox'; $key = 'This key is quite long and works well.'; $salt = 'this is a delicious salt!'; $result = Security::encrypt($txt, $key, $salt); // Change one of the bytes in the hmac. $result[10] = 'x'; $this->assertFalse(Security::decrypt($result, $key, $salt), 'Modified hmac causes failure.'); } /** * Test that changing the hmac salt will cause failures. * * @return void */ public function testDecryptHmacSaltFailure() { $txt = 'The quick brown fox'; $key = 'This key is quite long and works well.'; $salt = 'this is a delicious salt!'; $result = Security::encrypt($txt, $key, $salt); $salt = 'humpty dumpty had a great fall.'; $this->assertFalse(Security::decrypt($result, $key, $salt), 'Modified salt causes failure.'); } /** * Test that short keys cause errors * * @expectedException CakeException * @expectedExceptionMessage Invalid key for encrypt(), key must be at least 256 bits (32 bytes) long. * @return void */ public function testEncryptInvalidKey() { $txt = 'The quick brown fox jumped over the lazy dog.'; $key = 'this is too short'; Security::encrypt($txt, $key); } /** * Test encrypting falsey data * * @return void */ public function testEncryptDecryptFalseyData() { $key = 'This is a key that is long enough to be ok.'; $result = Security::encrypt('', $key); $this->assertSame('', Security::decrypt($result, $key)); $result = Security::encrypt(false, $key); $this->assertSame('', Security::decrypt($result, $key)); $result = Security::encrypt(null, $key); $this->assertSame('', Security::decrypt($result, $key)); $result = Security::encrypt(0, $key); $this->assertSame('0', Security::decrypt($result, $key)); $result = Security::encrypt('0', $key); $this->assertSame('0', Security::decrypt($result, $key)); } /** * Test that short keys cause errors * * @expectedException CakeException * @expectedExceptionMessage Invalid key for decrypt(), key must be at least 256 bits (32 bytes) long. * @return void */ public function testDecryptInvalidKey() { $txt = 'The quick brown fox jumped over the lazy dog.'; $key = 'this is too short'; Security::decrypt($txt, $key); } /** * Test that empty data cause errors * * @expectedException CakeException * @expectedExceptionMessage The data to decrypt cannot be empty. * @return void */ public function testDecryptInvalidData() { $txt = ''; $key = 'This is a key that is long enough to be ok.'; Security::decrypt($txt, $key); } } cakephp-2.8.0/lib/Cake/Test/Case/Utility/SetTest.php000066400000000000000000003362561265552240500221330ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Utility * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Set', 'Utility'); App::uses('Model', 'Model'); /** * SetTest class * * @package Cake.Test.Case.Utility */ class SetTest extends CakeTestCase { /** * testNumericKeyExtraction method * * @return void */ public function testNumericKeyExtraction() { $data = array('plugin' => null, 'controller' => '', 'action' => '', 1, 'whatever'); $this->assertEquals(array(1, 'whatever'), Set::extract($data, '{n}')); $this->assertEquals(array('plugin' => null, 'controller' => '', 'action' => ''), Set::diff($data, Set::extract($data, '{n}'))); } /** * testEnum method * * @return void */ public function testEnum() { $result = Set::enum(1, 'one, two'); $this->assertEquals('two', $result); $result = Set::enum(2, 'one, two'); $this->assertNull($result); $set = array('one', 'two'); $result = Set::enum(0, $set); $this->assertEquals('one', $result); $result = Set::enum(1, $set); $this->assertEquals('two', $result); $result = Set::enum(1, array('one', 'two')); $this->assertEquals('two', $result); $result = Set::enum(2, array('one', 'two')); $this->assertNull($result); $result = Set::enum('first', array('first' => 'one', 'second' => 'two')); $this->assertEquals('one', $result); $result = Set::enum('third', array('first' => 'one', 'second' => 'two')); $this->assertNull($result); $result = Set::enum('no', array('no' => 0, 'yes' => 1)); $this->assertEquals(0, $result); $result = Set::enum('not sure', array('no' => 0, 'yes' => 1)); $this->assertNull($result); $result = Set::enum(0); $this->assertEquals('no', $result); $result = Set::enum(1); $this->assertEquals('yes', $result); $result = Set::enum(2); $this->assertNull($result); } /** * testFilter method * * @see Hash test cases, as Set::filter() is just a proxy. * @return void */ public function testFilter() { $result = Set::filter(array('0', false, true, 0, array('one thing', 'I can tell you', 'is you got to be', false))); $expected = array('0', 2 => true, 3 => 0, 4 => array('one thing', 'I can tell you', 'is you got to be')); $this->assertSame($expected, $result); } /** * testNumericArrayCheck method * * @see Hash test cases, as Set::numeric() is just a proxy. * @return void */ public function testNumericArrayCheck() { $data = array('one'); $this->assertTrue(Set::numeric(array_keys($data))); } /** * testKeyCheck method * * @return void */ public function testKeyCheck() { $data = array('Multi' => array('dimensonal' => array('array'))); $this->assertTrue(Set::check($data, 'Multi.dimensonal')); $this->assertFalse(Set::check($data, 'Multi.dimensonal.array')); $data = array( array( 'Article' => array('id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'), 'User' => array('id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'), 'Comment' => array( array('id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31'), array('id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31'), ), 'Tag' => array( array('id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31'), array('id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31') ) ), array( 'Article' => array('id' => '3', 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31'), 'User' => array('id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'), 'Comment' => array(), 'Tag' => array() ) ); $this->assertTrue(Set::check($data, '0.Article.user_id')); $this->assertTrue(Set::check($data, '0.Comment.0.id')); $this->assertFalse(Set::check($data, '0.Comment.0.id.0')); $this->assertTrue(Set::check($data, '0.Article.user_id')); $this->assertFalse(Set::check($data, '0.Article.user_id.a')); } /** * testMerge method * * @return void */ public function testMerge() { $r = Set::merge(array('foo')); $this->assertEquals(array('foo'), $r); $r = Set::merge('foo'); $this->assertEquals(array('foo'), $r); $r = Set::merge('foo', 'bar'); $this->assertEquals(array('foo', 'bar'), $r); $r = Set::merge(array('foo'), array(), array('bar')); $this->assertEquals(array('foo', 'bar'), $r); $r = Set::merge('foo', array('user' => 'bob', 'no-bar'), 'bar'); $this->assertEquals(array('foo', 'user' => 'bob', 'no-bar', 'bar'), $r); $a = array('foo', 'foo2'); $b = array('bar', 'bar2'); $this->assertEquals(array('foo', 'foo2', 'bar', 'bar2'), Set::merge($a, $b)); $a = array('foo' => 'bar', 'bar' => 'foo'); $b = array('foo' => 'no-bar', 'bar' => 'no-foo'); $this->assertEquals(array('foo' => 'no-bar', 'bar' => 'no-foo'), Set::merge($a, $b)); $a = array('users' => array('bob', 'jim')); $b = array('users' => array('lisa', 'tina')); $this->assertEquals(array('users' => array('bob', 'jim', 'lisa', 'tina')), Set::merge($a, $b)); $a = array('users' => array('jim', 'bob')); $b = array('users' => 'none'); $this->assertEquals(array('users' => 'none'), Set::merge($a, $b)); $a = array('users' => array('lisa' => array('id' => 5, 'pw' => 'secret')), 'cakephp'); $b = array('users' => array('lisa' => array('pw' => 'new-pass', 'age' => 23)), 'ice-cream'); $this->assertEquals(array('users' => array('lisa' => array('id' => 5, 'pw' => 'new-pass', 'age' => 23)), 'cakephp', 'ice-cream'), Set::merge($a, $b)); $c = array('users' => array('lisa' => array('pw' => 'you-will-never-guess', 'age' => 25, 'pet' => 'dog')), 'chocolate'); $expected = array('users' => array('lisa' => array('id' => 5, 'pw' => 'you-will-never-guess', 'age' => 25, 'pet' => 'dog')), 'cakephp', 'ice-cream', 'chocolate'); $this->assertEquals($expected, Set::merge($a, $b, $c)); $this->assertEquals($expected, Set::merge($a, $b, array(), $c)); $r = Set::merge($a, $b, $c); $this->assertEquals($expected, $r); $a = array('Tree', 'CounterCache', 'Upload' => array('folder' => 'products', 'fields' => array('image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id'))); $b = array('Cacheable' => array('enabled' => false), 'Limit', 'Bindable', 'Validator', 'Transactional'); $expected = array('Tree', 'CounterCache', 'Upload' => array('folder' => 'products', 'fields' => array('image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id')), 'Cacheable' => array('enabled' => false), 'Limit', 'Bindable', 'Validator', 'Transactional'); $this->assertEquals($expected, Set::merge($a, $b)); $expected = array('Tree' => null, 'CounterCache' => null, 'Upload' => array('folder' => 'products', 'fields' => array('image_1_id', 'image_2_id', 'image_3_id', 'image_4_id', 'image_5_id')), 'Cacheable' => array('enabled' => false), 'Limit' => null, 'Bindable' => null, 'Validator' => null, 'Transactional' => null); $this->assertEquals($expected, Set::normalize(Set::merge($a, $b))); } /** * testSort method * * @return void */ public function testSort() { $result = Set::sort(array(), '{n}.name', 'asc'); $this->assertEquals(array(), $result); $a = array( 0 => array('Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate'))), 1 => array('Person' => array('name' => 'Tracy'), 'Friend' => array(array('name' => 'Lindsay'))) ); $b = array( 0 => array('Person' => array('name' => 'Tracy'), 'Friend' => array(array('name' => 'Lindsay'))), 1 => array('Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate'))) ); $a = Set::sort($a, '{n}.Friend.{n}.name', 'asc'); $this->assertEquals($a, $b); $b = array( 0 => array('Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate'))), 1 => array('Person' => array('name' => 'Tracy'), 'Friend' => array(array('name' => 'Lindsay'))) ); $a = array( 0 => array('Person' => array('name' => 'Tracy'), 'Friend' => array(array('name' => 'Lindsay'))), 1 => array('Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate'))) ); $a = Set::sort($a, '{n}.Friend.{n}.name', 'desc'); $this->assertEquals($a, $b); $a = array( 0 => array('Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate'))), 1 => array('Person' => array('name' => 'Tracy'), 'Friend' => array(array('name' => 'Lindsay'))), 2 => array('Person' => array('name' => 'Adam'), 'Friend' => array(array('name' => 'Bob'))) ); $b = array( 0 => array('Person' => array('name' => 'Adam'), 'Friend' => array(array('name' => 'Bob'))), 1 => array('Person' => array('name' => 'Jeff'), 'Friend' => array(array('name' => 'Nate'))), 2 => array('Person' => array('name' => 'Tracy'), 'Friend' => array(array('name' => 'Lindsay'))) ); $a = Set::sort($a, '{n}.Person.name', 'asc'); $this->assertEquals($a, $b); $a = array( array(7, 6, 4), array(3, 4, 5), array(3, 2, 1), ); $b = array( array(3, 2, 1), array(3, 4, 5), array(7, 6, 4), ); $a = Set::sort($a, '{n}.{n}', 'asc'); $this->assertEquals($a, $b); $a = array( array(7, 6, 4), array(3, 4, 5), array(3, 2, array(1, 1, 1)), ); $b = array( array(3, 2, array(1, 1, 1)), array(3, 4, 5), array(7, 6, 4), ); $a = Set::sort($a, '{n}', 'asc'); $this->assertEquals($a, $b); $a = array( 0 => array('Person' => array('name' => 'Jeff')), 1 => array('Shirt' => array('color' => 'black')) ); $b = array( 0 => array('Shirt' => array('color' => 'black')), 1 => array('Person' => array('name' => 'Jeff')), ); $a = Set::sort($a, '{n}.Person.name', 'ASC'); $this->assertEquals($a, $b); $names = array( array('employees' => array(array('name' => array('first' => 'John', 'last' => 'Doe')))), array('employees' => array(array('name' => array('first' => 'Jane', 'last' => 'Doe')))), array('employees' => array(array('name' => array()))), array('employees' => array(array('name' => array()))) ); $result = Set::sort($names, '{n}.employees.0.name', 'asc', 1); $expected = array( array('employees' => array(array('name' => array('first' => 'John', 'last' => 'Doe')))), array('employees' => array(array('name' => array('first' => 'Jane', 'last' => 'Doe')))), array('employees' => array(array('name' => array()))), array('employees' => array(array('name' => array()))) ); $this->assertEquals($expected, $result); $menus = array( 'blogs' => array('title' => 'Blogs', 'weight' => 3), 'comments' => array('title' => 'Comments', 'weight' => 2), 'users' => array('title' => 'Users', 'weight' => 1), ); $expected = array( 'users' => array('title' => 'Users', 'weight' => 1), 'comments' => array('title' => 'Comments', 'weight' => 2), 'blogs' => array('title' => 'Blogs', 'weight' => 3), ); $result = Set::sort($menus, '{[a-z]+}.weight', 'ASC'); $this->assertEquals($expected, $result); } /** * test sorting with string keys. * * @return void */ public function testSortString() { $toSort = array( 'four' => array('number' => 4, 'some' => 'foursome'), 'six' => array('number' => 6, 'some' => 'sixsome'), 'five' => array('number' => 5, 'some' => 'fivesome'), 'two' => array('number' => 2, 'some' => 'twosome'), 'three' => array('number' => 3, 'some' => 'threesome') ); $sorted = Set::sort($toSort, '{s}.number', 'asc'); $expected = array( 'two' => array('number' => 2, 'some' => 'twosome'), 'three' => array('number' => 3, 'some' => 'threesome'), 'four' => array('number' => 4, 'some' => 'foursome'), 'five' => array('number' => 5, 'some' => 'fivesome'), 'six' => array('number' => 6, 'some' => 'sixsome') ); $this->assertEquals($expected, $sorted); } /** * test sorting with out of order keys. * * @return void */ public function testSortWithOutOfOrderKeys() { $data = array( 9 => array('class' => 510, 'test2' => 2), 1 => array('class' => 500, 'test2' => 1), 2 => array('class' => 600, 'test2' => 2), 5 => array('class' => 625, 'test2' => 4), 0 => array('class' => 605, 'test2' => 3), ); $expected = array( array('class' => 500, 'test2' => 1), array('class' => 510, 'test2' => 2), array('class' => 600, 'test2' => 2), array('class' => 605, 'test2' => 3), array('class' => 625, 'test2' => 4), ); $result = Set::sort($data, '{n}.class', 'asc'); $this->assertEquals($expected, $result); $result = Set::sort($data, '{n}.test2', 'asc'); $this->assertEquals($expected, $result); } /** * testExtract method * * @return void */ public function testExtract() { $a = array( array( 'Article' => array('id' => '1', 'user_id' => '1', 'title' => 'First Article', 'body' => 'First Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'), 'User' => array('id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'), 'Comment' => array( array('id' => '1', 'article_id' => '1', 'user_id' => '2', 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:45:23', 'updated' => '2007-03-18 10:47:31'), array('id' => '2', 'article_id' => '1', 'user_id' => '4', 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31'), ), 'Tag' => array( array('id' => '1', 'tag' => 'tag1', 'created' => '2007-03-18 12:22:23', 'updated' => '2007-03-18 12:24:31'), array('id' => '2', 'tag' => 'tag2', 'created' => '2007-03-18 12:24:23', 'updated' => '2007-03-18 12:26:31') ), 'Deep' => array( 'Nesting' => array( 'test' => array( 1 => 'foo', 2 => array( 'and' => array('more' => 'stuff') ) ) ) ) ), array( 'Article' => array('id' => '3', 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31'), 'User' => array('id' => '2', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'), 'Comment' => array(), 'Tag' => array() ), array( 'Article' => array('id' => '3', 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31'), 'User' => array('id' => '3', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'), 'Comment' => array(), 'Tag' => array() ), array( 'Article' => array('id' => '3', 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31'), 'User' => array('id' => '4', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'), 'Comment' => array(), 'Tag' => array() ), array( 'Article' => array('id' => '3', 'user_id' => '1', 'title' => 'Third Article', 'body' => 'Third Article Body', 'published' => 'Y', 'created' => '2007-03-18 10:43:23', 'updated' => '2007-03-18 10:45:31'), 'User' => array('id' => '5', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31'), 'Comment' => array(), 'Tag' => array() ) ); $b = array('Deep' => $a[0]['Deep']); $c = array( array('a' => array('I' => array('a' => 1))), array( 'a' => array( 2 ) ), array('a' => array('II' => array('a' => 3, 'III' => array('a' => array('foo' => 4))))), ); $expected = array(array('a' => $c[2]['a'])); $r = Set::extract('/a/II[a=3]/..', $c); $this->assertEquals($expected, $r); $expected = array(1, 2, 3, 4, 5); $this->assertEquals($expected, Set::extract('/User/id', $a)); $expected = array(1, 2, 3, 4, 5); $this->assertEquals($expected, Set::extract('/User/id', $a)); $expected = array( array('id' => 1), array('id' => 2), array('id' => 3), array('id' => 4), array('id' => 5) ); $r = Set::extract('/User/id', $a, array('flatten' => false)); $this->assertEquals($expected, $r); $expected = array(array('test' => $a[0]['Deep']['Nesting']['test'])); $this->assertEquals($expected, Set::extract('/Deep/Nesting/test', $a)); $this->assertEquals($expected, Set::extract('/Deep/Nesting/test', $b)); $expected = array(array('test' => $a[0]['Deep']['Nesting']['test'])); $r = Set::extract('/Deep/Nesting/test/1/..', $a); $this->assertEquals($expected, $r); $expected = array(array('test' => $a[0]['Deep']['Nesting']['test'])); $r = Set::extract('/Deep/Nesting/test/2/and/../..', $a); $this->assertEquals($expected, $r); $expected = array(array('test' => $a[0]['Deep']['Nesting']['test'])); $r = Set::extract('/Deep/Nesting/test/2/../../../Nesting/test/2/..', $a); $this->assertEquals($expected, $r); $expected = array(2); $r = Set::extract('/User[2]/id', $a); $this->assertEquals($expected, $r); $expected = array(4, 5); $r = Set::extract('/User[id>3]/id', $a); $this->assertEquals($expected, $r); $expected = array(2, 3); $r = Set::extract('/User[id>1][id<=3]/id', $a); $this->assertEquals($expected, $r); $expected = array(array('I'), array('II')); $r = Set::extract('/a/@*', $c); $this->assertEquals($expected, $r); $single = array( 'User' => array( 'id' => 4, 'name' => 'Neo', ) ); $tricky = array( 0 => array( 'User' => array( 'id' => 1, 'name' => 'John', ) ), 1 => array( 'User' => array( 'id' => 2, 'name' => 'Bob', ) ), 2 => array( 'User' => array( 'id' => 3, 'name' => 'Tony', ) ), 'User' => array( 'id' => 4, 'name' => 'Neo', ) ); $expected = array(1, 2, 3, 4); $r = Set::extract('/User/id', $tricky); $this->assertEquals($expected, $r); $expected = array(4); $r = Set::extract('/User/id', $single); $this->assertEquals($expected, $r); $expected = array(1, 3); $r = Set::extract('/User[name=/n/]/id', $tricky); $this->assertEquals($expected, $r); $expected = array(4); $r = Set::extract('/User[name=/N/]/id', $tricky); $this->assertEquals($expected, $r); $expected = array(1, 3, 4); $r = Set::extract('/User[name=/N/i]/id', $tricky); $this->assertEquals($expected, $r); $expected = array(array('id', 'name'), array('id', 'name'), array('id', 'name'), array('id', 'name')); $r = Set::extract('/User/@*', $tricky); $this->assertEquals($expected, $r); $common = array( array( 'Article' => array( 'id' => 1, 'name' => 'Article 1', ), 'Comment' => array( array( 'id' => 1, 'user_id' => 5, 'article_id' => 1, 'text' => 'Comment 1', ), array( 'id' => 2, 'user_id' => 23, 'article_id' => 1, 'text' => 'Comment 2', ), array( 'id' => 3, 'user_id' => 17, 'article_id' => 1, 'text' => 'Comment 3', ), ), ), array( 'Article' => array( 'id' => 2, 'name' => 'Article 2', ), 'Comment' => array( array( 'id' => 4, 'user_id' => 2, 'article_id' => 2, 'text' => 'Comment 4', 'addition' => '', ), array( 'id' => 5, 'user_id' => 23, 'article_id' => 2, 'text' => 'Comment 5', 'addition' => 'foo', ), ), ), array( 'Article' => array( 'id' => 3, 'name' => 'Article 3', ), 'Comment' => array(), ) ); $r = Set::extract('/Comment/id', $common); $expected = array(1, 2, 3, 4, 5); $this->assertEquals($expected, $r); $expected = array(1, 2, 4, 5); $r = Set::extract('/Comment[id!=3]/id', $common); $this->assertEquals($expected, $r); $r = Set::extract('/', $common); $this->assertEquals($r, $common); $expected = array(1, 2, 4, 5); $r = Set::extract($common, '/Comment[id!=3]/id'); $this->assertEquals($expected, $r); $expected = array($common[0]['Comment'][2]); $r = Set::extract($common, '/Comment/2'); $this->assertEquals($expected, $r); $expected = array($common[0]['Comment'][0]); $r = Set::extract($common, '/Comment[1]/.[id=1]'); $this->assertEquals($expected, $r); $expected = array($common[1]['Comment'][1]); $r = Set::extract($common, '/1/Comment/.[2]'); $this->assertEquals($expected, $r); $expected = array(); $r = Set::extract('/User/id', array()); $this->assertEquals($expected, $r); $expected = array(5); $r = Set::extract('/Comment/id[:last]', $common); $this->assertEquals($expected, $r); $expected = array(1); $r = Set::extract('/Comment/id[:first]', $common); $this->assertEquals($expected, $r); $expected = array(3); $r = Set::extract('/Article[:last]/id', $common); $this->assertEquals($expected, $r); $expected = array(array('Comment' => $common[1]['Comment'][0])); $r = Set::extract('/Comment[addition=]', $common); $this->assertEquals($expected, $r); $habtm = array( array( 'Post' => array( 'id' => 1, 'title' => 'great post', ), 'Comment' => array( array( 'id' => 1, 'text' => 'foo', 'User' => array( 'id' => 1, 'name' => 'bob' ), ), array( 'id' => 2, 'text' => 'bar', 'User' => array( 'id' => 2, 'name' => 'tod' ), ), ), ), array( 'Post' => array( 'id' => 2, 'title' => 'fun post', ), 'Comment' => array( array( 'id' => 3, 'text' => '123', 'User' => array( 'id' => 3, 'name' => 'dan' ), ), array( 'id' => 4, 'text' => '987', 'User' => array( 'id' => 4, 'name' => 'jim' ), ), ), ), ); $r = Set::extract('/Comment/User[name=/bob|dan/]/..', $habtm); $this->assertEquals('bob', $r[0]['Comment']['User']['name']); $this->assertEquals('dan', $r[1]['Comment']['User']['name']); $this->assertEquals(2, count($r)); $r = Set::extract('/Comment/User[name=/bob|tod/]/..', $habtm); $this->assertEquals('bob', $r[0]['Comment']['User']['name']); $this->assertEquals('tod', $r[1]['Comment']['User']['name']); $this->assertEquals(2, count($r)); $tree = array( array( 'Category' => array('name' => 'Category 1'), 'children' => array(array('Category' => array('name' => 'Category 1.1'))) ), array( 'Category' => array('name' => 'Category 2'), 'children' => array( array('Category' => array('name' => 'Category 2.1')), array('Category' => array('name' => 'Category 2.2')) ) ), array( 'Category' => array('name' => 'Category 3'), 'children' => array(array('Category' => array('name' => 'Category 3.1'))) ) ); $expected = array(array('Category' => $tree[1]['Category'])); $r = Set::extract('/Category[name=Category 2]', $tree); $this->assertEquals($expected, $r); $expected = array( array('Category' => $tree[1]['Category'], 'children' => $tree[1]['children']) ); $r = Set::extract('/Category[name=Category 2]/..', $tree); $this->assertEquals($expected, $r); $expected = array( array('children' => $tree[1]['children'][0]), array('children' => $tree[1]['children'][1]) ); $r = Set::extract('/Category[name=Category 2]/../children', $tree); $this->assertEquals($expected, $r); $habtm = array( array( 'Post' => array( 'id' => 1, 'title' => 'great post', ), 'Comment' => array( array( 'id' => 1, 'text' => 'foo', 'User' => array( 'id' => 1, 'name' => 'bob' ), ), array( 'id' => 2, 'text' => 'bar', 'User' => array( 'id' => 2, 'name' => 'tod' ), ), ), ), array( 'Post' => array( 'id' => 2, 'title' => 'fun post', ), 'Comment' => array( array( 'id' => 3, 'text' => '123', 'User' => array( 'id' => 3, 'name' => 'dan' ), ), array( 'id' => 4, 'text' => '987', 'User' => array( 'id' => 4, 'name' => 'jim' ), ), ), ), ); $r = Set::extract('/Comment/User[name=/\w+/]/..', $habtm); $this->assertEquals('bob', $r[0]['Comment']['User']['name']); $this->assertEquals('tod', $r[1]['Comment']['User']['name']); $this->assertEquals('dan', $r[2]['Comment']['User']['name']); $this->assertEquals('dan', $r[3]['Comment']['User']['name']); $this->assertEquals(4, count($r)); $r = Set::extract('/Comment/User[name=/[a-z]+/]/..', $habtm); $this->assertEquals('bob', $r[0]['Comment']['User']['name']); $this->assertEquals('tod', $r[1]['Comment']['User']['name']); $this->assertEquals('dan', $r[2]['Comment']['User']['name']); $this->assertEquals('dan', $r[3]['Comment']['User']['name']); $this->assertEquals(4, count($r)); $r = Set::extract('/Comment/User[name=/bob|dan/]/..', $habtm); $this->assertEquals('bob', $r[0]['Comment']['User']['name']); $this->assertEquals('dan', $r[1]['Comment']['User']['name']); $this->assertEquals(2, count($r)); $r = Set::extract('/Comment/User[name=/bob|tod/]/..', $habtm); $this->assertEquals('bob', $r[0]['Comment']['User']['name']); $this->assertEquals('tod', $r[1]['Comment']['User']['name']); $this->assertEquals(2, count($r)); $mixedKeys = array( 'User' => array( 0 => array( 'id' => 4, 'name' => 'Neo' ), 1 => array( 'id' => 5, 'name' => 'Morpheus' ), 'stringKey' => array() ) ); $expected = array('Neo', 'Morpheus'); $r = Set::extract('/User/name', $mixedKeys); $this->assertEquals($expected, $r); $f = array( array( 'file' => array( 'name' => 'zipfile.zip', 'type' => 'application/zip', 'tmp_name' => '/tmp/php178.tmp', 'error' => 0, 'size' => '564647' ) ), array( 'file' => array( 'name' => 'zipfile2.zip', 'type' => 'application/x-zip-compressed', 'tmp_name' => '/tmp/php179.tmp', 'error' => 0, 'size' => '354784' ) ), array( 'file' => array( 'name' => 'picture.jpg', 'type' => 'image/jpeg', 'tmp_name' => '/tmp/php180.tmp', 'error' => 0, 'size' => '21324' ) ) ); $expected = array(array('name' => 'zipfile2.zip', 'type' => 'application/x-zip-compressed', 'tmp_name' => '/tmp/php179.tmp', 'error' => 0, 'size' => '354784')); $r = Set::extract('/file/.[type=application/x-zip-compressed]', $f); $this->assertEquals($expected, $r); $expected = array(array('name' => 'zipfile.zip', 'type' => 'application/zip', 'tmp_name' => '/tmp/php178.tmp', 'error' => 0, 'size' => '564647')); $r = Set::extract('/file/.[type=application/zip]', $f); $this->assertEquals($expected, $r); $f = array( array( 'file' => array( 'name' => 'zipfile.zip', 'type' => 'application/zip', 'tmp_name' => '/tmp/php178.tmp', 'error' => 0, 'size' => '564647' ) ), array( 'file' => array( 'name' => 'zipfile2.zip', 'type' => 'application/x zip compressed', 'tmp_name' => '/tmp/php179.tmp', 'error' => 0, 'size' => '354784' ) ), array( 'file' => array( 'name' => 'picture.jpg', 'type' => 'image/jpeg', 'tmp_name' => '/tmp/php180.tmp', 'error' => 0, 'size' => '21324' ) ) ); $expected = array(array('name' => 'zipfile2.zip', 'type' => 'application/x zip compressed', 'tmp_name' => '/tmp/php179.tmp', 'error' => 0, 'size' => '354784')); $r = Set::extract('/file/.[type=application/x zip compressed]', $f); $this->assertEquals($expected, $r); $expected = array( array('name' => 'zipfile.zip', 'type' => 'application/zip', 'tmp_name' => '/tmp/php178.tmp', 'error' => 0, 'size' => '564647'), array('name' => 'zipfile2.zip', 'type' => 'application/x zip compressed', 'tmp_name' => '/tmp/php179.tmp', 'error' => 0, 'size' => '354784') ); $r = Set::extract('/file/.[tmp_name=/tmp\/php17/]', $f); $this->assertEquals($expected, $r); $hasMany = array( 'Node' => array( 'id' => 1, 'name' => 'First', 'state' => 50 ), 'ParentNode' => array( 0 => array( 'id' => 2, 'name' => 'Second', 'state' => 60, ) ) ); $result = Set::extract('/ParentNode/name', $hasMany); $expected = array('Second'); $this->assertEquals($expected, $result); $data = array( array( 'Category' => array( 'id' => 1, 'name' => 'First' ), 0 => array( 'value' => 50 ) ), array( 'Category' => array( 'id' => 2, 'name' => 'Second' ), 0 => array( 'value' => 60 ) ) ); $expected = array( array( 'Category' => array( 'id' => 1, 'name' => 'First' ), 0 => array( 'value' => 50 ) ) ); $result = Set::extract('/Category[id=1]/..', $data); $this->assertEquals($expected, $result); $data = array( array( 'ChildNode' => array('id' => 1), array('name' => 'Item 1') ), array( 'ChildNode' => array('id' => 2), array('name' => 'Item 2') ), ); $expected = array( 'Item 1', 'Item 2' ); $result = Set::extract('/0/name', $data); $this->assertEquals($expected, $result); $data = array( array('A1', 'B1'), array('A2', 'B2') ); $expected = array('A1', 'A2'); $result = Set::extract('/0', $data); $this->assertEquals($expected, $result); } /** * test parent selectors with extract * * @return void */ public function testExtractParentSelector() { $tree = array( array( 'Category' => array( 'name' => 'Category 1' ), 'children' => array( array( 'Category' => array( 'name' => 'Category 1.1' ) ) ) ), array( 'Category' => array( 'name' => 'Category 2' ), 'children' => array( array( 'Category' => array( 'name' => 'Category 2.1' ) ), array( 'Category' => array( 'name' => 'Category 2.2' ) ), ) ), array( 'Category' => array( 'name' => 'Category 3' ), 'children' => array( array( 'Category' => array( 'name' => 'Category 3.1' ) ) ) ) ); $expected = array(array('Category' => $tree[1]['Category'])); $r = Set::extract('/Category[name=Category 2]', $tree); $this->assertEquals($expected, $r); $expected = array(array('Category' => $tree[1]['Category'], 'children' => $tree[1]['children'])); $r = Set::extract('/Category[name=Category 2]/..', $tree); $this->assertEquals($expected, $r); $expected = array(array('children' => $tree[1]['children'][0]), array('children' => $tree[1]['children'][1])); $r = Set::extract('/Category[name=Category 2]/../children', $tree); $this->assertEquals($expected, $r); $single = array( array( 'CallType' => array( 'name' => 'Internal Voice' ), 'x' => array( 'hour' => 7 ) ) ); $expected = array(7); $r = Set::extract('/CallType[name=Internal Voice]/../x/hour', $single); $this->assertEquals($expected, $r); $multiple = array( array( 'CallType' => array( 'name' => 'Internal Voice' ), 'x' => array( 'hour' => 7 ) ), array( 'CallType' => array( 'name' => 'Internal Voice' ), 'x' => array( 'hour' => 2 ) ), array( 'CallType' => array( 'name' => 'Internal Voice' ), 'x' => array( 'hour' => 1 ) ) ); $expected = array(7, 2, 1); $r = Set::extract('/CallType[name=Internal Voice]/../x/hour', $multiple); $this->assertEquals($expected, $r); $a = array( 'Model' => array( '0' => array( 'id' => 18, 'SubModelsModel' => array( 'id' => 1, 'submodel_id' => 66, 'model_id' => 18, 'type' => 1 ), ), '1' => array( 'id' => 0, 'SubModelsModel' => array( 'id' => 2, 'submodel_id' => 66, 'model_id' => 0, 'type' => 1 ), ), '2' => array( 'id' => 17, 'SubModelsModel' => array( 'id' => 3, 'submodel_id' => 66, 'model_id' => 17, 'type' => 2 ), ), '3' => array( 'id' => 0, 'SubModelsModel' => array( 'id' => 4, 'submodel_id' => 66, 'model_id' => 0, 'type' => 2 ) ) ) ); $expected = array( array( 'Model' => array( 'id' => 17, 'SubModelsModel' => array( 'id' => 3, 'submodel_id' => 66, 'model_id' => 17, 'type' => 2 ), ) ), array( 'Model' => array( 'id' => 0, 'SubModelsModel' => array( 'id' => 4, 'submodel_id' => 66, 'model_id' => 0, 'type' => 2 ) ) ) ); $r = Set::extract('/Model/SubModelsModel[type=2]/..', $a); $this->assertEquals($expected, $r); } /** * test that extract() still works when arrays don't contain a 0 index. * * @return void */ public function testExtractWithNonZeroArrays() { $nonZero = array( 1 => array( 'User' => array( 'id' => 1, 'name' => 'John', ) ), 2 => array( 'User' => array( 'id' => 2, 'name' => 'Bob', ) ), 3 => array( 'User' => array( 'id' => 3, 'name' => 'Tony', ) ) ); $expected = array(1, 2, 3); $r = Set::extract('/User/id', $nonZero); $this->assertEquals($expected, $r); $expected = array( array('User' => array('id' => 1, 'name' => 'John')), array('User' => array('id' => 2, 'name' => 'Bob')), array('User' => array('id' => 3, 'name' => 'Tony')), ); $result = Set::extract('/User', $nonZero); $this->assertEquals($expected, $result); $nonSequential = array( 'User' => array( 0 => array('id' => 1), 2 => array('id' => 2), 6 => array('id' => 3), 9 => array('id' => 4), 3 => array('id' => 5), ), ); $nonZero = array( 'User' => array( 2 => array('id' => 1), 4 => array('id' => 2), 6 => array('id' => 3), 9 => array('id' => 4), 3 => array('id' => 5), ), ); $expected = array(1, 2, 3, 4, 5); $this->assertEquals($expected, Set::extract('/User/id', $nonSequential)); $result = Set::extract('/User/id', $nonZero); $this->assertEquals($expected, $result, 'Failed non zero array key extract'); $expected = array(1, 2, 3, 4, 5); $this->assertEquals($expected, Set::extract('/User/id', $nonSequential)); $result = Set::extract('/User/id', $nonZero); $this->assertEquals($expected, $result, 'Failed non zero array key extract'); $startingAtOne = array( 'Article' => array( 1 => array( 'id' => 1, 'approved' => 1, ), ) ); $expected = array(0 => array('Article' => array('id' => 1, 'approved' => 1))); $result = Set::extract('/Article[approved=1]', $startingAtOne); $this->assertEquals($expected, $result); $items = array( 240 => array( 'A' => array( 'field1' => 'a240', 'field2' => 'a240', ), 'B' => array( 'field1' => 'b240', 'field2' => 'b240' ), ) ); $expected = array( 0 => 'b240' ); $result = Set::extract('/B/field1', $items); $this->assertSame($expected, $result); $this->assertSame($result, Set::extract('{n}.B.field1', $items)); } /** * testExtractWithArrays method * * @return void */ public function testExtractWithArrays() { $data = array( 'Level1' => array( 'Level2' => array('test1', 'test2'), 'Level2bis' => array('test3', 'test4') ) ); $this->assertEquals(array(array('Level2' => array('test1', 'test2'))), Set::extract('/Level1/Level2', $data)); $this->assertEquals(array(array('Level2bis' => array('test3', 'test4'))), Set::extract('/Level1/Level2bis', $data)); } /** * test extract() with elements that have non-array children. * * @return void */ public function testExtractWithNonArrayElements() { $data = array( 'node' => array( array('foo'), 'bar' ) ); $result = Set::extract('/node', $data); $expected = array( array('node' => array('foo')), 'bar' ); $this->assertEquals($expected, $result); $data = array( 'node' => array( 'foo' => array('bar'), 'bar' => array('foo') ) ); $result = Set::extract('/node', $data); $expected = array( array('foo' => array('bar')), array('bar' => array('foo')), ); $this->assertEquals($expected, $result); $data = array( 'node' => array( 'foo' => array( 'bar' ), 'bar' => 'foo' ) ); $result = Set::extract('/node', $data); $expected = array( array('foo' => array('bar')), 'foo' ); $this->assertEquals($expected, $result); } /** * Test that extract() + matching can hit null things. * * @return void */ public function testExtractMatchesNull() { $data = array( 'Country' => array( array('name' => 'Canada'), array('name' => 'Australia'), array('name' => null), ) ); $result = Set::extract('/Country[name=/Canada|^$/]', $data); $expected = array( array( 'Country' => array( 'name' => 'Canada', ), ), array( 'Country' => array( 'name' => null, ), ), ); $this->assertEquals($expected, $result); } /** * testMatches method * * @return void */ public function testMatches() { $a = array( array('Article' => array('id' => 1, 'title' => 'Article 1')), array('Article' => array('id' => 2, 'title' => 'Article 2')), array('Article' => array('id' => 3, 'title' => 'Article 3')) ); $this->assertTrue(Set::matches(array('id=2'), $a[1]['Article'])); $this->assertFalse(Set::matches(array('id>2'), $a[1]['Article'])); $this->assertTrue(Set::matches(array('id>=2'), $a[1]['Article'])); $this->assertFalse(Set::matches(array('id>=3'), $a[1]['Article'])); $this->assertTrue(Set::matches(array('id<=2'), $a[1]['Article'])); $this->assertFalse(Set::matches(array('id<2'), $a[1]['Article'])); $this->assertTrue(Set::matches(array('id>1'), $a[1]['Article'])); $this->assertTrue(Set::matches(array('id>1', 'id<3', 'id!=0'), $a[1]['Article'])); $this->assertTrue(Set::matches(array('3'), null, 3)); $this->assertTrue(Set::matches(array('5'), null, 5)); $this->assertTrue(Set::matches(array('id'), $a[1]['Article'])); $this->assertTrue(Set::matches(array('id', 'title'), $a[1]['Article'])); $this->assertFalse(Set::matches(array('non-existant'), $a[1]['Article'])); $this->assertTrue(Set::matches('/Article[id=2]', $a)); $this->assertFalse(Set::matches('/Article[id=4]', $a)); $this->assertTrue(Set::matches(array(), $a)); $r = array( 'Attachment' => array( 'keep' => array() ), 'Comment' => array( 'keep' => array( 'Attachment' => array( 'fields' => array( 0 => 'attachment', ), ), ) ), 'User' => array( 'keep' => array() ), 'Article' => array( 'keep' => array( 'Comment' => array( 'fields' => array( 0 => 'comment', 1 => 'published', ), ), 'User' => array( 'fields' => array( 0 => 'user', ), ), ) ) ); $this->assertTrue(Set::matches('/Article/keep/Comment', $r)); $this->assertEquals(array('comment', 'published'), Set::extract('/Article/keep/Comment/fields', $r)); $this->assertEquals(array('user'), Set::extract('/Article/keep/User/fields', $r)); } /** * testSetExtractReturnsEmptyArray method * * @return void */ public function testSetExtractReturnsEmptyArray() { $this->assertEquals(Set::extract(array(), '/Post/id'), array()); $this->assertEquals(Set::extract('/Post/id', array()), array()); $this->assertEquals(Set::extract('/Post/id', array( array('Post' => array('name' => 'bob')), array('Post' => array('name' => 'jim')) )), array()); $this->assertEquals(Set::extract(array(), 'Message.flash'), null); } /** * testClassicExtract method * * @return void */ public function testClassicExtract() { $a = array( array('Article' => array('id' => 1, 'title' => 'Article 1')), array('Article' => array('id' => 2, 'title' => 'Article 2')), array('Article' => array('id' => 3, 'title' => 'Article 3')) ); $result = Set::extract($a, '{n}.Article.id'); $expected = array(1, 2, 3); $this->assertEquals($expected, $result); $result = Set::extract($a, '{n}.Article.title'); $expected = array('Article 1', 'Article 2', 'Article 3'); $this->assertEquals($expected, $result); $result = Set::extract($a, '1.Article.title'); $expected = 'Article 2'; $this->assertEquals($expected, $result); $result = Set::extract($a, '3.Article.title'); $expected = null; $this->assertEquals($expected, $result); $a = array( array( 'Article' => array('id' => 1, 'title' => 'Article 1', 'User' => array('id' => 1, 'username' => 'mariano.iglesias')) ), array( 'Article' => array('id' => 2, 'title' => 'Article 2', 'User' => array('id' => 1, 'username' => 'mariano.iglesias')) ), array( 'Article' => array('id' => 3, 'title' => 'Article 3', 'User' => array('id' => 2, 'username' => 'phpnut')) ) ); $result = Set::extract($a, '{n}.Article.User.username'); $expected = array('mariano.iglesias', 'mariano.iglesias', 'phpnut'); $this->assertEquals($expected, $result); $a = array( array( 'Article' => array( 'id' => 1, 'title' => 'Article 1', 'Comment' => array( array('id' => 10, 'title' => 'Comment 10'), array('id' => 11, 'title' => 'Comment 11'), array('id' => 12, 'title' => 'Comment 12') ) ) ), array( 'Article' => array( 'id' => 2, 'title' => 'Article 2', 'Comment' => array( array('id' => 13, 'title' => 'Comment 13'), array('id' => 14, 'title' => 'Comment 14') ) ) ), array('Article' => array('id' => 3, 'title' => 'Article 3')) ); $result = Set::extract($a, '{n}.Article.Comment.{n}.id'); $expected = array(array(10, 11, 12), array(13, 14), null); $this->assertEquals($expected, $result); $result = Set::extract($a, '{n}.Article.Comment.{n}.title'); $expected = array( array('Comment 10', 'Comment 11', 'Comment 12'), array('Comment 13', 'Comment 14'), null ); $this->assertEquals($expected, $result); $a = array(array('1day' => '20 sales'), array('1day' => '2 sales')); $result = Set::extract($a, '{n}.1day'); $expected = array('20 sales', '2 sales'); $this->assertEquals($expected, $result); $a = array( 'pages' => array('name' => 'page'), 'fruites' => array('name' => 'fruit'), 0 => array('name' => 'zero') ); $result = Set::extract($a, '{s}.name'); $expected = array('page', 'fruit'); $this->assertEquals($expected, $result); $a = array( 0 => array('pages' => array('name' => 'page')), 1 => array('fruites' => array('name' => 'fruit')), 'test' => array(array('name' => 'jippi')), 'dot.test' => array(array('name' => 'jippi')) ); $result = Set::extract($a, '{n}.{s}.name'); $expected = array(0 => array('page'), 1 => array('fruit')); $this->assertEquals($expected, $result); $result = Set::extract($a, '{s}.{n}.name'); $expected = array(array('jippi'), array('jippi')); $this->assertEquals($expected, $result); $result = Set::extract($a, '{\w+}.{\w+}.name'); $expected = array( array('pages' => 'page'), array('fruites' => 'fruit'), 'test' => array('jippi'), 'dot.test' => array('jippi') ); $this->assertEquals($expected, $result); $result = Set::extract($a, '{\d+}.{\w+}.name'); $expected = array(array('pages' => 'page'), array('fruites' => 'fruit')); $this->assertEquals($expected, $result); $result = Set::extract($a, '{n}.{\w+}.name'); $expected = array(array('pages' => 'page'), array('fruites' => 'fruit')); $this->assertEquals($expected, $result); $result = Set::extract($a, '{s}.{\d+}.name'); $expected = array(array('jippi'), array('jippi')); $this->assertEquals($expected, $result); $result = Set::extract($a, '{s}'); $expected = array(array(array('name' => 'jippi')), array(array('name' => 'jippi'))); $this->assertEquals($expected, $result); $result = Set::extract($a, '{[a-z]}'); $expected = array( 'test' => array(array('name' => 'jippi')), 'dot.test' => array(array('name' => 'jippi')) ); $this->assertEquals($expected, $result); $result = Set::extract($a, '{dot\.test}.{n}'); $expected = array('dot.test' => array(array('name' => 'jippi'))); $this->assertEquals($expected, $result); $a = new stdClass(); $a->articles = array( array('Article' => array('id' => 1, 'title' => 'Article 1')), array('Article' => array('id' => 2, 'title' => 'Article 2')), array('Article' => array('id' => 3, 'title' => 'Article 3')) ); $result = Set::extract($a, 'articles.{n}.Article.id'); $expected = array(1, 2, 3); $this->assertEquals($expected, $result); $result = Set::extract($a, 'articles.{n}.Article.title'); $expected = array('Article 1', 'Article 2', 'Article 3'); $this->assertEquals($expected, $result); $a = new ArrayObject(); $a['articles'] = array( array('Article' => array('id' => 1, 'title' => 'Article 1')), array('Article' => array('id' => 2, 'title' => 'Article 2')), array('Article' => array('id' => 3, 'title' => 'Article 3')) ); $result = Set::extract($a, 'articles.{n}.Article.id'); $expected = array(1, 2, 3); $this->assertEquals($expected, $result); $result = Set::extract($a, 'articles.{n}.Article.title'); $expected = array('Article 1', 'Article 2', 'Article 3'); $this->assertEquals($expected, $result); $result = Set::extract($a, 'articles.0.Article.title'); $expected = 'Article 1'; $this->assertEquals($expected, $result); } /** * test classicExtract with keys that exceed 32bit max int. * * @return void */ public function testClassicExtractMaxInt() { $data = array( 'Data' => array( '13376924712' => 'abc' ) ); $this->assertEquals('abc', Set::classicExtract($data, 'Data.13376924712')); } /** * testInsert method * * @see Hash tests, as Set::insert() is just a proxy. * @return void */ public function testInsert() { $a = array( 'pages' => array('name' => 'page') ); $result = Set::insert($a, 'files', array('name' => 'files')); $expected = array( 'pages' => array('name' => 'page'), 'files' => array('name' => 'files') ); $this->assertEquals($expected, $result); } /** * testRemove method * * @return void */ public function testRemove() { $a = array( 'pages' => array('name' => 'page'), 'files' => array('name' => 'files') ); $result = Set::remove($a, 'files'); $expected = array( 'pages' => array('name' => 'page') ); $this->assertEquals($expected, $result); } /** * testCheck method * * @return void */ public function testCheck() { $set = array( 'My Index 1' => array('First' => 'The first item') ); $this->assertTrue(Set::check($set, 'My Index 1.First')); $this->assertTrue(Set::check($set, 'My Index 1')); $this->assertEquals(Set::check($set, array()), $set); $set = array( 'My Index 1' => array('First' => array('Second' => array('Third' => array('Fourth' => 'Heavy. Nesting.')))) ); $this->assertTrue(Set::check($set, 'My Index 1.First.Second')); $this->assertTrue(Set::check($set, 'My Index 1.First.Second.Third')); $this->assertTrue(Set::check($set, 'My Index 1.First.Second.Third.Fourth')); $this->assertFalse(Set::check($set, 'My Index 1.First.Seconds.Third.Fourth')); } /** * testWritingWithFunkyKeys method * * @return void */ public function testWritingWithFunkyKeys() { $set = Set::insert(array(), 'Session Test', "test"); $this->assertEquals('test', Set::extract($set, 'Session Test')); $set = Set::remove($set, 'Session Test'); $this->assertFalse(Set::check($set, 'Session Test')); $expected = array('Session Test' => array('Test Case' => 'test')); $this->assertEquals($expected, Set::insert(array(), 'Session Test.Test Case', "test")); $this->assertTrue(Set::check($expected, 'Session Test.Test Case')); } /** * testDiff method * * @return void */ public function testDiff() { $a = array( 0 => array('name' => 'main'), 1 => array('name' => 'about') ); $b = array( 0 => array('name' => 'main'), 1 => array('name' => 'about'), 2 => array('name' => 'contact') ); $result = Set::diff($a, $b); $expected = array( 2 => array('name' => 'contact') ); $this->assertEquals($expected, $result); $result = Set::diff($a, array()); $expected = $a; $this->assertEquals($expected, $result); $result = Set::diff(array(), $b); $expected = $b; $this->assertEquals($expected, $result); $b = array( 0 => array('name' => 'me'), 1 => array('name' => 'about') ); $result = Set::diff($a, $b); $expected = array( 0 => array('name' => 'main') ); $this->assertEquals($expected, $result); $a = array(); $b = array('name' => 'bob', 'address' => 'home'); $result = Set::diff($a, $b); $this->assertEquals($b, $result); $a = array('name' => 'bob', 'address' => 'home'); $b = array(); $result = Set::diff($a, $b); $this->assertEquals($a, $result); $a = array('key' => true, 'another' => false, 'name' => 'me'); $b = array('key' => 1, 'another' => 0); $expected = array('name' => 'me'); $result = Set::diff($a, $b); $this->assertEquals($expected, $result); $a = array('key' => 'value', 'another' => null, 'name' => 'me'); $b = array('key' => 'differentValue', 'another' => null); $expected = array('key' => 'value', 'name' => 'me'); $result = Set::diff($a, $b); $this->assertEquals($expected, $result); $a = array('key' => 'value', 'another' => null, 'name' => 'me'); $b = array('key' => 'differentValue', 'another' => 'value'); $expected = array('key' => 'value', 'another' => null, 'name' => 'me'); $result = Set::diff($a, $b); $this->assertEquals($expected, $result); $a = array('key' => 'value', 'another' => null, 'name' => 'me'); $b = array('key' => 'differentValue', 'another' => 'value'); $expected = array('key' => 'differentValue', 'another' => 'value', 'name' => 'me'); $result = Set::diff($b, $a); $this->assertEquals($expected, $result); $a = array('key' => 'value', 'another' => null, 'name' => 'me'); $b = array(0 => 'differentValue', 1 => 'value'); $expected = $a + $b; $result = Set::diff($a, $b); $this->assertEquals($expected, $result); } /** * testContains method * * @return void */ public function testContains() { $a = array( 0 => array('name' => 'main'), 1 => array('name' => 'about') ); $b = array( 0 => array('name' => 'main'), 1 => array('name' => 'about'), 2 => array('name' => 'contact'), 'a' => 'b' ); $this->assertTrue(Set::contains($a, $a)); $this->assertFalse(Set::contains($a, $b)); $this->assertTrue(Set::contains($b, $a)); } /** * testCombine method * * @return void */ public function testCombine() { $result = Set::combine(array(), '{n}.User.id', '{n}.User.Data'); $this->assertTrue(empty($result)); $result = Set::combine('', '{n}.User.id', '{n}.User.Data'); $this->assertTrue(empty($result)); $a = array( array('User' => array('id' => 2, 'group_id' => 1, 'Data' => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'))), array('User' => array('id' => 14, 'group_id' => 2, 'Data' => array('user' => 'phpnut', 'name' => 'Larry E. Masters'))), array('User' => array('id' => 25, 'group_id' => 1, 'Data' => array('user' => 'gwoo', 'name' => 'The Gwoo')))); $result = Set::combine($a, '{n}.User.id'); $expected = array(2 => null, 14 => null, 25 => null); $this->assertEquals($expected, $result); $result = Set::combine($a, '{n}.User.id', '{n}.User.non-existant'); $expected = array(2 => null, 14 => null, 25 => null); $this->assertEquals($expected, $result); $result = Set::combine($a, '{n}.User.id', '{n}.User.Data'); $expected = array( 2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'), 14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters'), 25 => array('user' => 'gwoo', 'name' => 'The Gwoo')); $this->assertEquals($expected, $result); $result = Set::combine($a, '{n}.User.id', '{n}.User.Data.name'); $expected = array( 2 => 'Mariano Iglesias', 14 => 'Larry E. Masters', 25 => 'The Gwoo'); $this->assertEquals($expected, $result); $result = Set::combine($a, '{n}.User.id', '{n}.User.Data', '{n}.User.group_id'); $expected = array( 1 => array( 2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'), 25 => array('user' => 'gwoo', 'name' => 'The Gwoo')), 2 => array( 14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters'))); $this->assertEquals($expected, $result); $result = Set::combine($a, '{n}.User.id', '{n}.User.Data.name', '{n}.User.group_id'); $expected = array( 1 => array( 2 => 'Mariano Iglesias', 25 => 'The Gwoo'), 2 => array( 14 => 'Larry E. Masters')); $this->assertEquals($expected, $result); $result = Set::combine($a, '{n}.User.id'); $expected = array(2 => null, 14 => null, 25 => null); $this->assertEquals($expected, $result); $result = Set::combine($a, '{n}.User.id', '{n}.User.Data'); $expected = array( 2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'), 14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters'), 25 => array('user' => 'gwoo', 'name' => 'The Gwoo')); $this->assertEquals($expected, $result); $result = Set::combine($a, '{n}.User.id', '{n}.User.Data.name'); $expected = array(2 => 'Mariano Iglesias', 14 => 'Larry E. Masters', 25 => 'The Gwoo'); $this->assertEquals($expected, $result); $result = Set::combine($a, '{n}.User.id', '{n}.User.Data', '{n}.User.group_id'); $expected = array( 1 => array( 2 => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'), 25 => array('user' => 'gwoo', 'name' => 'The Gwoo')), 2 => array( 14 => array('user' => 'phpnut', 'name' => 'Larry E. Masters'))); $this->assertEquals($expected, $result); $result = Set::combine($a, '{n}.User.id', '{n}.User.Data.name', '{n}.User.group_id'); $expected = array( 1 => array( 2 => 'Mariano Iglesias', 25 => 'The Gwoo'), 2 => array( 14 => 'Larry E. Masters')); $this->assertEquals($expected, $result); $result = Set::combine($a, '{n}.User.id', array('{0}: {1}', '{n}.User.Data.user', '{n}.User.Data.name'), '{n}.User.group_id'); $expected = array( 1 => array( 2 => 'mariano.iglesias: Mariano Iglesias', 25 => 'gwoo: The Gwoo'), 2 => array(14 => 'phpnut: Larry E. Masters')); $this->assertEquals($expected, $result); $result = Set::combine($a, array('{0}: {1}', '{n}.User.Data.user', '{n}.User.Data.name'), '{n}.User.id'); $expected = array('mariano.iglesias: Mariano Iglesias' => 2, 'phpnut: Larry E. Masters' => 14, 'gwoo: The Gwoo' => 25); $this->assertEquals($expected, $result); $result = Set::combine($a, array('{1}: {0}', '{n}.User.Data.user', '{n}.User.Data.name'), '{n}.User.id'); $expected = array('Mariano Iglesias: mariano.iglesias' => 2, 'Larry E. Masters: phpnut' => 14, 'The Gwoo: gwoo' => 25); $this->assertEquals($expected, $result); $result = Set::combine($a, array('%1$s: %2$d', '{n}.User.Data.user', '{n}.User.id'), '{n}.User.Data.name'); $expected = array('mariano.iglesias: 2' => 'Mariano Iglesias', 'phpnut: 14' => 'Larry E. Masters', 'gwoo: 25' => 'The Gwoo'); $this->assertEquals($expected, $result); $result = Set::combine($a, array('%2$d: %1$s', '{n}.User.Data.user', '{n}.User.id'), '{n}.User.Data.name'); $expected = array('2: mariano.iglesias' => 'Mariano Iglesias', '14: phpnut' => 'Larry E. Masters', '25: gwoo' => 'The Gwoo'); $this->assertEquals($expected, $result); $b = new stdClass(); $b->users = array( array('User' => array('id' => 2, 'group_id' => 1, 'Data' => array('user' => 'mariano.iglesias', 'name' => 'Mariano Iglesias'))), array('User' => array('id' => 14, 'group_id' => 2, 'Data' => array('user' => 'phpnut', 'name' => 'Larry E. Masters'))), array('User' => array('id' => 25, 'group_id' => 1, 'Data' => array('user' => 'gwoo', 'name' => 'The Gwoo')))); $result = Set::combine($b, 'users.{n}.User.id'); $expected = array(2 => null, 14 => null, 25 => null); $this->assertEquals($expected, $result); $result = Set::combine($b, 'users.{n}.User.id', 'users.{n}.User.non-existant'); $expected = array(2 => null, 14 => null, 25 => null); $this->assertEquals($expected, $result); $result = Set::combine($a, 'fail', 'fail'); $this->assertSame(array(), $result); } /** * testMapReverse method * * @return void */ public function testMapReverse() { $result = Set::reverse(null); $this->assertEquals(null, $result); $result = Set::reverse(false); $this->assertEquals(false, $result); $expected = array( 'Array1' => array( 'Array1Data1' => 'Array1Data1 value 1', 'Array1Data2' => 'Array1Data2 value 2'), 'Array2' => array( 0 => array('Array2Data1' => 1, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4'), 1 => array('Array2Data1' => 2, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4'), 2 => array('Array2Data1' => 3, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4'), 3 => array('Array2Data1' => 4, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4'), 4 => array('Array2Data1' => 5, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4')), 'Array3' => array( 0 => array('Array3Data1' => 1, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'), 1 => array('Array3Data1' => 2, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'), 2 => array('Array3Data1' => 3, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'), 3 => array('Array3Data1' => 4, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'), 4 => array('Array3Data1' => 5, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'))); $map = Set::map($expected, true); $this->assertEquals($expected['Array1']['Array1Data1'], $map->Array1->Array1Data1); $this->assertEquals($expected['Array2'][0]['Array2Data1'], $map->Array2[0]->Array2Data1); $result = Set::reverse($map); $this->assertEquals($expected, $result); $expected = array( 'Post' => array('id' => 1, 'title' => 'First Post'), 'Comment' => array( array('id' => 1, 'title' => 'First Comment'), array('id' => 2, 'title' => 'Second Comment') ), 'Tag' => array( array('id' => 1, 'title' => 'First Tag'), array('id' => 2, 'title' => 'Second Tag') ), ); $map = Set::map($expected); $this->assertEquals($expected['Post']['title'], $map->title); foreach ($map->Comment as $comment) { $ids[] = $comment->id; } $this->assertEquals(array(1, 2), $ids); $expected = array( 'Array1' => array( 'Array1Data1' => 'Array1Data1 value 1', 'Array1Data2' => 'Array1Data2 value 2', 'Array1Data3' => 'Array1Data3 value 3', 'Array1Data4' => 'Array1Data4 value 4', 'Array1Data5' => 'Array1Data5 value 5', 'Array1Data6' => 'Array1Data6 value 6', 'Array1Data7' => 'Array1Data7 value 7', 'Array1Data8' => 'Array1Data8 value 8'), 'string' => 1, 'another' => 'string', 'some' => 'thing else', 'Array2' => array( 0 => array('Array2Data1' => 1, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4'), 1 => array('Array2Data1' => 2, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4'), 2 => array('Array2Data1' => 3, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4'), 3 => array('Array2Data1' => 4, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4'), 4 => array('Array2Data1' => 5, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4')), 'Array3' => array( 0 => array('Array3Data1' => 1, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'), 1 => array('Array3Data1' => 2, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'), 2 => array('Array3Data1' => 3, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'), 3 => array('Array3Data1' => 4, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'), 4 => array('Array3Data1' => 5, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'))); $map = Set::map($expected, true); $result = Set::reverse($map); $this->assertEquals($expected, $result); $expected = array( 'Array1' => array( 'Array1Data1' => 'Array1Data1 value 1', 'Array1Data2' => 'Array1Data2 value 2', 'Array1Data3' => 'Array1Data3 value 3', 'Array1Data4' => 'Array1Data4 value 4', 'Array1Data5' => 'Array1Data5 value 5', 'Array1Data6' => 'Array1Data6 value 6', 'Array1Data7' => 'Array1Data7 value 7', 'Array1Data8' => 'Array1Data8 value 8'), 'string' => 1, 'another' => 'string', 'some' => 'thing else', 'Array2' => array( 0 => array('Array2Data1' => 1, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4'), 1 => array('Array2Data1' => 2, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4'), 2 => array('Array2Data1' => 3, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4'), 3 => array('Array2Data1' => 4, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4'), 4 => array('Array2Data1' => 5, 'Array2Data2' => 'Array2Data2 value 2', 'Array2Data3' => 'Array2Data3 value 2', 'Array2Data4' => 'Array2Data4 value 4')), 'string2' => 1, 'another2' => 'string', 'some2' => 'thing else', 'Array3' => array( 0 => array('Array3Data1' => 1, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'), 1 => array('Array3Data1' => 2, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'), 2 => array('Array3Data1' => 3, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'), 3 => array('Array3Data1' => 4, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4'), 4 => array('Array3Data1' => 5, 'Array3Data2' => 'Array3Data2 value 2', 'Array3Data3' => 'Array3Data3 value 2', 'Array3Data4' => 'Array3Data4 value 4')), 'string3' => 1, 'another3' => 'string', 'some3' => 'thing else'); $map = Set::map($expected, true); $result = Set::reverse($map); $this->assertEquals($expected, $result); $expected = array('User' => array('psword' => 'whatever', 'Icon' => array('id' => 851))); $map = Set::map($expected); $result = Set::reverse($map); $this->assertEquals($expected, $result); $expected = array('User' => array('psword' => 'whatever', 'Icon' => array('id' => 851))); $class = new stdClass; $class->User = new stdClass; $class->User->psword = 'whatever'; $class->User->Icon = new stdClass; $class->User->Icon->id = 851; $result = Set::reverse($class); $this->assertEquals($expected, $result); $expected = array('User' => array('psword' => 'whatever', 'Icon' => array('id' => 851), 'Profile' => array('name' => 'Some Name', 'address' => 'Some Address'))); $class = new stdClass; $class->User = new stdClass; $class->User->psword = 'whatever'; $class->User->Icon = new stdClass; $class->User->Icon->id = 851; $class->User->Profile = new stdClass; $class->User->Profile->name = 'Some Name'; $class->User->Profile->address = 'Some Address'; $result = Set::reverse($class); $this->assertEquals($expected, $result); $expected = array('User' => array('psword' => 'whatever', 'Icon' => array('id' => 851), 'Profile' => array('name' => 'Some Name', 'address' => 'Some Address'), 'Comment' => array( array('id' => 1, 'article_id' => 1, 'user_id' => 1, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31'), array('id' => 2, 'article_id' => 1, 'user_id' => 2, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31')))); $class = new stdClass; $class->User = new stdClass; $class->User->psword = 'whatever'; $class->User->Icon = new stdClass; $class->User->Icon->id = 851; $class->User->Profile = new stdClass; $class->User->Profile->name = 'Some Name'; $class->User->Profile->address = 'Some Address'; $class->User->Comment = new stdClass; $class->User->Comment->{'0'} = new stdClass; $class->User->Comment->{'0'}->id = 1; $class->User->Comment->{'0'}->article_id = 1; $class->User->Comment->{'0'}->user_id = 1; $class->User->Comment->{'0'}->comment = 'First Comment for First Article'; $class->User->Comment->{'0'}->published = 'Y'; $class->User->Comment->{'0'}->created = '2007-03-18 10:47:23'; $class->User->Comment->{'0'}->updated = '2007-03-18 10:49:31'; $class->User->Comment->{'1'} = new stdClass; $class->User->Comment->{'1'}->id = 2; $class->User->Comment->{'1'}->article_id = 1; $class->User->Comment->{'1'}->user_id = 2; $class->User->Comment->{'1'}->comment = 'Second Comment for First Article'; $class->User->Comment->{'1'}->published = 'Y'; $class->User->Comment->{'1'}->created = '2007-03-18 10:47:23'; $class->User->Comment->{'1'}->updated = '2007-03-18 10:49:31'; $result = Set::reverse($class); $this->assertEquals($expected, $result); $expected = array('User' => array('psword' => 'whatever', 'Icon' => array('id' => 851), 'Profile' => array('name' => 'Some Name', 'address' => 'Some Address'), 'Comment' => array( array('id' => 1, 'article_id' => 1, 'user_id' => 1, 'comment' => 'First Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31'), array('id' => 2, 'article_id' => 1, 'user_id' => 2, 'comment' => 'Second Comment for First Article', 'published' => 'Y', 'created' => '2007-03-18 10:47:23', 'updated' => '2007-03-18 10:49:31')))); // @codingStandardsIgnoreStart $class = new stdClass; $class->User = new stdClass; $class->User->psword = 'whatever'; $class->User->Icon = new stdClass; $class->User->Icon->id = 851; $class->User->Profile = new stdClass; $class->User->Profile->name = 'Some Name'; $class->User->Profile->address = 'Some Address'; $class->User->Comment = array(); $comment = new stdClass; $comment->id = 1; $comment->article_id = 1; $comment->user_id = 1; $comment->comment = 'First Comment for First Article'; $comment->published = 'Y'; $comment->created = '2007-03-18 10:47:23'; $comment->updated = '2007-03-18 10:49:31'; $comment2 = new stdClass; $comment2->id = 2; $comment2->article_id = 1; $comment2->user_id = 2; $comment2->comment = 'Second Comment for First Article'; $comment2->published = 'Y'; $comment2->created = '2007-03-18 10:47:23'; $comment2->updated = '2007-03-18 10:49:31'; // @codingStandardsIgnoreEnd $class->User->Comment = array($comment, $comment2); $result = Set::reverse($class); $this->assertEquals($expected, $result); $class = new stdClass; $class->User = new stdClass; $class->User->id = 100; $class->someString = 'this is some string'; $class->Profile = new stdClass; $class->Profile->name = 'Joe Mamma'; $result = Set::reverse($class); $expected = array( 'User' => array('id' => '100'), 'someString' => 'this is some string', 'Profile' => array('name' => 'Joe Mamma') ); $this->assertEquals($expected, $result); // @codingStandardsIgnoreStart $class = new stdClass; $class->User = new stdClass; $class->User->id = 100; $class->User->_name_ = 'User'; $class->Profile = new stdClass; $class->Profile->name = 'Joe Mamma'; $class->Profile->_name_ = 'Profile'; // @codingStandardsIgnoreEnd $result = Set::reverse($class); $expected = array('User' => array('id' => '100'), 'Profile' => array('name' => 'Joe Mamma')); $this->assertEquals($expected, $result); } /** * testFormatting method * * @return void */ public function testFormatting() { $data = array( array('Person' => array('first_name' => 'Nate', 'last_name' => 'Abele', 'city' => 'Boston', 'state' => 'MA', 'something' => '42')), array('Person' => array('first_name' => 'Larry', 'last_name' => 'Masters', 'city' => 'Boondock', 'state' => 'TN', 'something' => '{0}')), array('Person' => array('first_name' => 'Garrett', 'last_name' => 'Woodworth', 'city' => 'Venice Beach', 'state' => 'CA', 'something' => '{1}'))); $result = Set::format($data, '{1}, {0}', array('{n}.Person.first_name', '{n}.Person.last_name')); $expected = array('Abele, Nate', 'Masters, Larry', 'Woodworth, Garrett'); $this->assertEquals($expected, $result); $result = Set::format($data, '{0}, {1}', array('{n}.Person.last_name', '{n}.Person.first_name')); $this->assertEquals($expected, $result); $result = Set::format($data, '{0}, {1}', array('{n}.Person.city', '{n}.Person.state')); $expected = array('Boston, MA', 'Boondock, TN', 'Venice Beach, CA'); $this->assertEquals($expected, $result); $result = Set::format($data, '{{0}, {1}}', array('{n}.Person.city', '{n}.Person.state')); $expected = array('{Boston, MA}', '{Boondock, TN}', '{Venice Beach, CA}'); $this->assertEquals($expected, $result); $result = Set::format($data, '{{0}, {1}}', array('{n}.Person.something', '{n}.Person.something')); $expected = array('{42, 42}', '{{0}, {0}}', '{{1}, {1}}'); $this->assertEquals($expected, $result); $result = Set::format($data, '{%2$d, %1$s}', array('{n}.Person.something', '{n}.Person.something')); $expected = array('{42, 42}', '{0, {0}}', '{0, {1}}'); $this->assertEquals($expected, $result); $result = Set::format($data, '{%1$s, %1$s}', array('{n}.Person.something', '{n}.Person.something')); $expected = array('{42, 42}', '{{0}, {0}}', '{{1}, {1}}'); $this->assertEquals($expected, $result); $result = Set::format($data, '%2$d, %1$s', array('{n}.Person.first_name', '{n}.Person.something')); $expected = array('42, Nate', '0, Larry', '0, Garrett'); $this->assertEquals($expected, $result); $result = Set::format($data, '%1$s, %2$d', array('{n}.Person.first_name', '{n}.Person.something')); $expected = array('Nate, 42', 'Larry, 0', 'Garrett, 0'); $this->assertEquals($expected, $result); } /** * testFormattingNullValues method * * @return void */ public function testFormattingNullValues() { $data = array( array('Person' => array('first_name' => 'Nate', 'last_name' => 'Abele', 'city' => 'Boston', 'state' => 'MA', 'something' => '42')), array('Person' => array('first_name' => 'Larry', 'last_name' => 'Masters', 'city' => 'Boondock', 'state' => 'TN', 'something' => null)), array('Person' => array('first_name' => 'Garrett', 'last_name' => 'Woodworth', 'city' => 'Venice Beach', 'state' => 'CA', 'something' => null))); $result = Set::format($data, '%s', array('{n}.Person.something')); $expected = array('42', '', ''); $this->assertEquals($expected, $result); $result = Set::format($data, '{0}, {1}', array('{n}.Person.city', '{n}.Person.something')); $expected = array('Boston, 42', 'Boondock, ', 'Venice Beach, '); $this->assertEquals($expected, $result); } /** * testCountDim method * * @return void */ public function testCountDim() { $data = array('one', '2', 'three'); $result = Set::countDim($data); $this->assertEquals(1, $result); $data = array('1' => '1.1', '2', '3'); $result = Set::countDim($data); $this->assertEquals(1, $result); $data = array('1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => '3.1.1')); $result = Set::countDim($data); $this->assertEquals(2, $result); $data = array('1' => '1.1', '2', '3' => array('3.1' => '3.1.1')); $result = Set::countDim($data); $this->assertEquals(1, $result); $data = array('1' => '1.1', '2', '3' => array('3.1' => '3.1.1')); $result = Set::countDim($data, true); $this->assertEquals(2, $result); $data = array('1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => array('3.1.1' => '3.1.1.1'))); $result = Set::countDim($data); $this->assertEquals(2, $result); $data = array('1' => array('1.1' => '1.1.1'), '2', '3' => array('3.1' => array('3.1.1' => '3.1.1.1'))); $result = Set::countDim($data, true); $this->assertEquals(3, $result); $data = array('1' => array('1.1' => '1.1.1'), array('2' => array('2.1' => array('2.1.1' => '2.1.1.1'))), '3' => array('3.1' => array('3.1.1' => '3.1.1.1'))); $result = Set::countDim($data, true); $this->assertEquals(4, $result); $data = array('1' => array('1.1' => '1.1.1'), array('2' => array('2.1' => array('2.1.1' => array('2.1.1.1')))), '3' => array('3.1' => array('3.1.1' => '3.1.1.1'))); $result = Set::countDim($data, true); $this->assertEquals(5, $result); $data = array('1' => array('1.1' => '1.1.1'), array('2' => array('2.1' => array('2.1.1' => array('2.1.1.1' => '2.1.1.1.1')))), '3' => array('3.1' => array('3.1.1' => '3.1.1.1'))); $result = Set::countDim($data, true); $this->assertEquals(5, $result); $set = array('1' => array('1.1' => '1.1.1'), array('2' => array('2.1' => array('2.1.1' => array('2.1.1.1' => '2.1.1.1.1')))), '3' => array('3.1' => array('3.1.1' => '3.1.1.1'))); $result = Set::countDim($set, false, 0); $this->assertEquals(2, $result); $result = Set::countDim($set, true); $this->assertEquals(5, $result); } /** * testMapNesting method * * @return void */ public function testMapNesting() { $expected = array( array( "IndexedPage" => array( "id" => 1, "url" => 'http://blah.com/', 'hash' => '68a9f053b19526d08e36c6a9ad150737933816a5', 'headers' => array( 'Date' => "Wed, 14 Nov 2007 15:51:42 GMT", 'Server' => "Apache", 'Expires' => "Thu, 19 Nov 1981 08:52:00 GMT", 'Cache-Control' => "private", 'Pragma' => "no-cache", 'Content-Type' => "text/html; charset=UTF-8", 'X-Original-Transfer-Encoding' => "chunked", 'Content-Length' => "50210", ), 'meta' => array( 'keywords' => array('testing', 'tests'), 'description' => 'describe me', ), 'get_vars' => '', 'post_vars' => array(), 'cookies' => array('PHPSESSID' => "dde9896ad24595998161ffaf9e0dbe2d"), 'redirect' => '', 'created' => "1195055503", 'updated' => "1195055503", ) ), array( "IndexedPage" => array( "id" => 2, "url" => 'http://blah.com/', 'hash' => '68a9f053b19526d08e36c6a9ad150737933816a5', 'headers' => array( 'Date' => "Wed, 14 Nov 2007 15:51:42 GMT", 'Server' => "Apache", 'Expires' => "Thu, 19 Nov 1981 08:52:00 GMT", 'Cache-Control' => "private", 'Pragma' => "no-cache", 'Content-Type' => "text/html; charset=UTF-8", 'X-Original-Transfer-Encoding' => "chunked", 'Content-Length' => "50210", ), 'meta' => array( 'keywords' => array('testing', 'tests'), 'description' => 'describe me', ), 'get_vars' => '', 'post_vars' => array(), 'cookies' => array('PHPSESSID' => "dde9896ad24595998161ffaf9e0dbe2d"), 'redirect' => '', 'created' => "1195055503", 'updated' => "1195055503", ), ) ); $mapped = Set::map($expected); $ids = array(); foreach ($mapped as $object) { $ids[] = $object->id; } $this->assertEquals(array(1, 2), $ids); $this->assertEquals($expected[0]['IndexedPage']['headers'], get_object_vars($mapped[0]->headers)); $result = Set::reverse($mapped); $this->assertEquals($expected, $result); $data = array( array( "IndexedPage" => array( "id" => 1, "url" => 'http://blah.com/', 'hash' => '68a9f053b19526d08e36c6a9ad150737933816a5', 'get_vars' => '', 'redirect' => '', 'created' => "1195055503", 'updated' => "1195055503", ) ), array( "IndexedPage" => array( "id" => 2, "url" => 'http://blah.com/', 'hash' => '68a9f053b19526d08e36c6a9ad150737933816a5', 'get_vars' => '', 'redirect' => '', 'created' => "1195055503", 'updated' => "1195055503", ), ) ); $mapped = Set::map($data); // @codingStandardsIgnoreStart $expected = new stdClass(); $expected->_name_ = 'IndexedPage'; $expected->id = 2; $expected->url = 'http://blah.com/'; $expected->hash = '68a9f053b19526d08e36c6a9ad150737933816a5'; $expected->get_vars = ''; $expected->redirect = ''; $expected->created = '1195055503'; $expected->updated = '1195055503'; // @codingStandardsIgnoreEnd $this->assertEquals($expected, $mapped[1]); $ids = array(); foreach ($mapped as $object) { $ids[] = $object->id; } $this->assertEquals(array(1, 2), $ids); $result = Set::map(null); $expected = null; $this->assertEquals($expected, $result); } /** * testNestedMappedData method * * @return void */ public function testNestedMappedData() { $result = Set::map(array( array( 'Post' => array('id' => '1', 'author_id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'), 'Author' => array('id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'test' => 'working'), ), array( 'Post' => array('id' => '2', 'author_id' => '3', 'title' => 'Second Post', 'body' => 'Second Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:41:23', 'updated' => '2007-03-18 10:43:31'), 'Author' => array('id' => '3', 'user' => 'larry', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:20:23', 'updated' => '2007-03-17 01:22:31', 'test' => 'working'), ) )); // @codingStandardsIgnoreStart $expected = new stdClass; $expected->_name_ = 'Post'; $expected->id = '1'; $expected->author_id = '1'; $expected->title = 'First Post'; $expected->body = 'First Post Body'; $expected->published = 'Y'; $expected->created = "2007-03-18 10:39:23"; $expected->updated = "2007-03-18 10:41:31"; $expected->Author = new stdClass; $expected->Author->id = '1'; $expected->Author->user = 'mariano'; $expected->Author->password = '5f4dcc3b5aa765d61d8327deb882cf99'; $expected->Author->created = '2007-03-17 01:16:23'; $expected->Author->updated = '2007-03-17 01:18:31'; $expected->Author->test = 'working'; $expected->Author->_name_ = 'Author'; $expected2 = new stdClass; $expected2->_name_ = 'Post'; $expected2->id = '2'; $expected2->author_id = '3'; $expected2->title = 'Second Post'; $expected2->body = 'Second Post Body'; $expected2->published = 'Y'; $expected2->created = "2007-03-18 10:41:23"; $expected2->updated = "2007-03-18 10:43:31"; $expected2->Author = new stdClass; $expected2->Author->id = '3'; $expected2->Author->user = 'larry'; $expected2->Author->password = '5f4dcc3b5aa765d61d8327deb882cf99'; $expected2->Author->created = '2007-03-17 01:20:23'; $expected2->Author->updated = '2007-03-17 01:22:31'; $expected2->Author->test = 'working'; $expected2->Author->_name_ = 'Author'; // @codingStandardsIgnoreEnd $test = array(); $test[0] = $expected; $test[1] = $expected2; $this->assertEquals($test, $result); $result = Set::map( array( 'Post' => array('id' => '1', 'author_id' => '1', 'title' => 'First Post', 'body' => 'First Post Body', 'published' => 'Y', 'created' => '2007-03-18 10:39:23', 'updated' => '2007-03-18 10:41:31'), 'Author' => array('id' => '1', 'user' => 'mariano', 'password' => '5f4dcc3b5aa765d61d8327deb882cf99', 'created' => '2007-03-17 01:16:23', 'updated' => '2007-03-17 01:18:31', 'test' => 'working'), ) ); // @codingStandardsIgnoreStart $expected = new stdClass; $expected->_name_ = 'Post'; $expected->id = '1'; $expected->author_id = '1'; $expected->title = 'First Post'; $expected->body = 'First Post Body'; $expected->published = 'Y'; $expected->created = "2007-03-18 10:39:23"; $expected->updated = "2007-03-18 10:41:31"; $expected->Author = new stdClass; $expected->Author->id = '1'; $expected->Author->user = 'mariano'; $expected->Author->password = '5f4dcc3b5aa765d61d8327deb882cf99'; $expected->Author->created = "2007-03-17 01:16:23"; $expected->Author->updated = "2007-03-17 01:18:31"; $expected->Author->test = 'working'; $expected->Author->_name_ = 'Author'; // @codingStandardsIgnoreEnd $this->assertEquals($expected, $result); //Case where extra HABTM fields come back in a result $data = array( 'User' => array( 'id' => 1, 'email' => 'user@example.com', 'first_name' => 'John', 'last_name' => 'Smith', ), 'Piece' => array( array( 'id' => 1, 'title' => 'Moonlight Sonata', 'composer' => 'Ludwig van Beethoven', 'PiecesUser' => array( 'id' => 1, 'created' => '2008-01-01 00:00:00', 'modified' => '2008-01-01 00:00:00', 'piece_id' => 1, 'user_id' => 2, ) ), array( 'id' => 2, 'title' => 'Moonlight Sonata 2', 'composer' => 'Ludwig van Beethoven', 'PiecesUser' => array( 'id' => 2, 'created' => '2008-01-01 00:00:00', 'modified' => '2008-01-01 00:00:00', 'piece_id' => 2, 'user_id' => 2, ) ) ) ); $result = Set::map($data); // @codingStandardsIgnoreStart $expected = new stdClass(); $expected->_name_ = 'User'; $expected->id = 1; $expected->email = 'user@example.com'; $expected->first_name = 'John'; $expected->last_name = 'Smith'; $piece = new stdClass(); $piece->id = 1; $piece->title = 'Moonlight Sonata'; $piece->composer = 'Ludwig van Beethoven'; $piece->PiecesUser = new stdClass(); $piece->PiecesUser->id = 1; $piece->PiecesUser->created = '2008-01-01 00:00:00'; $piece->PiecesUser->modified = '2008-01-01 00:00:00'; $piece->PiecesUser->piece_id = 1; $piece->PiecesUser->user_id = 2; $piece->PiecesUser->_name_ = 'PiecesUser'; $piece->_name_ = 'Piece'; $piece2 = new stdClass(); $piece2->id = 2; $piece2->title = 'Moonlight Sonata 2'; $piece2->composer = 'Ludwig van Beethoven'; $piece2->PiecesUser = new stdClass(); $piece2->PiecesUser->id = 2; $piece2->PiecesUser->created = '2008-01-01 00:00:00'; $piece2->PiecesUser->modified = '2008-01-01 00:00:00'; $piece2->PiecesUser->piece_id = 2; $piece2->PiecesUser->user_id = 2; $piece2->PiecesUser->_name_ = 'PiecesUser'; $piece2->_name_ = 'Piece'; // @codingStandardsIgnoreEnd $expected->Piece = array($piece, $piece2); $this->assertEquals($expected, $result); //Same data, but should work if _name_ has been manually defined: $data = array( 'User' => array( 'id' => 1, 'email' => 'user@example.com', 'first_name' => 'John', 'last_name' => 'Smith', '_name_' => 'FooUser', ), 'Piece' => array( array( 'id' => 1, 'title' => 'Moonlight Sonata', 'composer' => 'Ludwig van Beethoven', '_name_' => 'FooPiece', 'PiecesUser' => array( 'id' => 1, 'created' => '2008-01-01 00:00:00', 'modified' => '2008-01-01 00:00:00', 'piece_id' => 1, 'user_id' => 2, '_name_' => 'FooPiecesUser', ) ), array( 'id' => 2, 'title' => 'Moonlight Sonata 2', 'composer' => 'Ludwig van Beethoven', '_name_' => 'FooPiece', 'PiecesUser' => array( 'id' => 2, 'created' => '2008-01-01 00:00:00', 'modified' => '2008-01-01 00:00:00', 'piece_id' => 2, 'user_id' => 2, '_name_' => 'FooPiecesUser', ) ) ) ); $result = Set::map($data); // @codingStandardsIgnoreStart $expected = new stdClass(); $expected->_name_ = 'FooUser'; $expected->id = 1; $expected->email = 'user@example.com'; $expected->first_name = 'John'; $expected->last_name = 'Smith'; $piece = new stdClass(); $piece->id = 1; $piece->title = 'Moonlight Sonata'; $piece->composer = 'Ludwig van Beethoven'; $piece->_name_ = 'FooPiece'; $piece->PiecesUser = new stdClass(); $piece->PiecesUser->id = 1; $piece->PiecesUser->created = '2008-01-01 00:00:00'; $piece->PiecesUser->modified = '2008-01-01 00:00:00'; $piece->PiecesUser->piece_id = 1; $piece->PiecesUser->user_id = 2; $piece->PiecesUser->_name_ = 'FooPiecesUser'; $piece2 = new stdClass(); $piece2->id = 2; $piece2->title = 'Moonlight Sonata 2'; $piece2->composer = 'Ludwig van Beethoven'; $piece2->_name_ = 'FooPiece'; $piece2->PiecesUser = new stdClass(); $piece2->PiecesUser->id = 2; $piece2->PiecesUser->created = '2008-01-01 00:00:00'; $piece2->PiecesUser->modified = '2008-01-01 00:00:00'; $piece2->PiecesUser->piece_id = 2; $piece2->PiecesUser->user_id = 2; $piece2->PiecesUser->_name_ = 'FooPiecesUser'; // @codingStandardsIgnoreEnd $expected->Piece = array($piece, $piece2); $this->assertEquals($expected, $result); } /** * testPushDiff method * * @return void */ public function testPushDiff() { $array1 = array('ModelOne' => array('id' => 1001, 'field_one' => 'a1.m1.f1', 'field_two' => 'a1.m1.f2')); $array2 = array('ModelTwo' => array('id' => 1002, 'field_one' => 'a2.m2.f1', 'field_two' => 'a2.m2.f2')); $result = Set::pushDiff($array1, $array2); $this->assertEquals($array1 + $array2, $result); $array3 = array('ModelOne' => array('id' => 1003, 'field_one' => 'a3.m1.f1', 'field_two' => 'a3.m1.f2', 'field_three' => 'a3.m1.f3')); $result = Set::pushDiff($array1, $array3); $expected = array('ModelOne' => array('id' => 1001, 'field_one' => 'a1.m1.f1', 'field_two' => 'a1.m1.f2', 'field_three' => 'a3.m1.f3')); $this->assertEquals($expected, $result); $array1 = array( 0 => array('ModelOne' => array('id' => 1001, 'field_one' => 's1.0.m1.f1', 'field_two' => 's1.0.m1.f2')), 1 => array('ModelTwo' => array('id' => 1002, 'field_one' => 's1.1.m2.f2', 'field_two' => 's1.1.m2.f2'))); $array2 = array( 0 => array('ModelOne' => array('id' => 1001, 'field_one' => 's2.0.m1.f1', 'field_two' => 's2.0.m1.f2')), 1 => array('ModelTwo' => array('id' => 1002, 'field_one' => 's2.1.m2.f2', 'field_two' => 's2.1.m2.f2'))); $result = Set::pushDiff($array1, $array2); $this->assertEquals($array1, $result); $array3 = array(0 => array('ModelThree' => array('id' => 1003, 'field_one' => 's3.0.m3.f1', 'field_two' => 's3.0.m3.f2'))); $result = Set::pushDiff($array1, $array3); $expected = array( 0 => array('ModelOne' => array('id' => 1001, 'field_one' => 's1.0.m1.f1', 'field_two' => 's1.0.m1.f2'), 'ModelThree' => array('id' => 1003, 'field_one' => 's3.0.m3.f1', 'field_two' => 's3.0.m3.f2')), 1 => array('ModelTwo' => array('id' => 1002, 'field_one' => 's1.1.m2.f2', 'field_two' => 's1.1.m2.f2'))); $this->assertEquals($expected, $result); $result = Set::pushDiff($array1, null); $this->assertEquals($array1, $result); $result = Set::pushDiff($array1, $array2); $this->assertEquals($array1 + $array2, $result); } /** * testSetApply method * @return void */ public function testApply() { $data = array( array('Movie' => array('id' => 1, 'title' => 'movie 3', 'rating' => 5)), array('Movie' => array('id' => 1, 'title' => 'movie 1', 'rating' => 1)), array('Movie' => array('id' => 1, 'title' => 'movie 2', 'rating' => 3)) ); $result = Set::apply('/Movie/rating', $data, 'array_sum'); $expected = 9; $this->assertEquals($expected, $result); $result = Set::apply('/Movie/rating', $data, 'array_product'); $expected = 15; $this->assertEquals($expected, $result); $result = Set::apply('/Movie/title', $data, 'ucfirst', array('type' => 'map')); $expected = array('Movie 3', 'Movie 1', 'Movie 2'); $this->assertEquals($expected, $result); $result = Set::apply('/Movie/title', $data, 'strtoupper', array('type' => 'map')); $expected = array('MOVIE 3', 'MOVIE 1', 'MOVIE 2'); $this->assertEquals($expected, $result); $result = Set::apply('/Movie/rating', $data, array('SetTest', 'method'), array('type' => 'reduce')); $expected = 9; $this->assertEquals($expected, $result); $result = Set::apply('/Movie/rating', $data, 'strtoupper', array('type' => 'non existing type')); $expected = null; $this->assertEquals($expected, $result); } /** * Helper method to test Set::apply() * * @return void */ public static function method($val1, $val2) { $val1 += $val2; return $val1; } /** * testXmlSetReverse method * * @return void */ public function testXmlSetReverse() { App::uses('Xml', 'Utility'); $string = ' Cake PHP Google Group http://groups.google.com/group/cake-php Search this group before posting anything. There are over 20,000 posts and it&#39;s very likely your question was answered before. Visit the IRC channel #cakephp at irc.freenode.net for live chat with users and developers of Cake. If you post, tell us the version of Cake, PHP, and database. en constructng result array when using findall http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f i'm using cakephp to construct a logical data model array that will be <br> passed to a flex app. I have the following model association: <br> ServiceDay-&gt;(hasMany)ServiceTi me-&gt;(hasMany)ServiceTimePrice. So what <br> the current output from my findall is something like this example: <br> <p>Array( <br> [0] =&gt; Array( http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f bmil...@gmail.com(bpscrugs) Fri, 28 Dec 2007 00:44:14 UT Re: share views between actions? http://groups.google.com/group/cake-php/msg/8b350d898707dad8 Then perhaps you might do us all a favour and refrain from replying to <br> things you do not understand. That goes especially for asinine comments. <br> Indeed. <br> To sum up: <br> No comment. <br> In my day, a simple &quot;RTFM&quot; would suffice. I'll keep in mind to ignore any <br> further responses from you. <br> You (and I) were referring to the *online documentation*, not other http://groups.google.com/group/cake-php/msg/8b350d898707dad8 subtropolis.z...@gmail.com(subtropolis zijn) Fri, 28 Dec 2007 00:45:01 UT '; $xml = Xml::build($string); $result = Set::reverse($xml); $expected = array('rss' => array( '@version' => '2.0', 'channel' => array( 'title' => 'Cake PHP Google Group', 'link' => 'http://groups.google.com/group/cake-php', 'description' => 'Search this group before posting anything. There are over 20,000 posts and it's very likely your question was answered before. Visit the IRC channel #cakephp at irc.freenode.net for live chat with users and developers of Cake. If you post, tell us the version of Cake, PHP, and database.', 'language' => 'en', 'item' => array( array( 'title' => 'constructng result array when using findall', 'link' => 'http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f', 'description' => "i'm using cakephp to construct a logical data model array that will be
passed to a flex app. I have the following model association:
ServiceDay->(hasMany)ServiceTi me->(hasMany)ServiceTimePrice. So what
the current output from my findall is something like this example:

Array(
[0] => Array(", 'guid' => array('@isPermaLink' => 'true', '@' => 'http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f'), 'author' => 'bmil...@gmail.com(bpscrugs)', 'pubDate' => 'Fri, 28 Dec 2007 00:44:14 UT', ), array( 'title' => 'Re: share views between actions?', 'link' => 'http://groups.google.com/group/cake-php/msg/8b350d898707dad8', 'description' => 'Then perhaps you might do us all a favour and refrain from replying to
things you do not understand. That goes especially for asinine comments.
Indeed.
To sum up:
No comment.
In my day, a simple "RTFM" would suffice. I\'ll keep in mind to ignore any
further responses from you.
You (and I) were referring to the *online documentation*, not other', 'guid' => array('@isPermaLink' => 'true', '@' => 'http://groups.google.com/group/cake-php/msg/8b350d898707dad8'), 'author' => 'subtropolis.z...@gmail.com(subtropolis zijn)', 'pubDate' => 'Fri, 28 Dec 2007 00:45:01 UT' ) ) ) )); $this->assertEquals($expected, $result); $string = ''; $xml = Xml::build($string); $result = Set::reverse($xml); $expected = array('data' => array('post' => array('@title' => 'Title of this post', '@description' => 'cool'))); $this->assertEquals($expected, $result); $xml = Xml::build('An example of a correctly reversed SimpleXMLElement'); $result = Set::reverse($xml); $expected = array('example' => array( 'item' => array( 'title' => 'An example of a correctly reversed SimpleXMLElement', 'desc' => '', ) ) ); $this->assertEquals($expected, $result); $xml = Xml::build('title1title2'); $result = Set::reverse($xml); $expected = array('example' => array( 'item' => array( '@attr' => '123', 'titles' => array( 'title' => array('title1', 'title2') ) ) ) ); $this->assertEquals($expected, $result); $xml = Xml::build('listtextforitems'); $result = Set::reverse($xml); $expected = array('example' => array( '@attr' => 'ex_attr', 'item' => array( '@attr' => '123', 'titles' => 'list', '@' => 'textforitems' ) ) ); $this->assertEquals($expected, $result); $string = ' Cake PHP Google Group http://groups.google.com/group/cake-php Search this group before posting anything. There are over 20,000 posts and it&#39;s very likely your question was answered before. Visit the IRC channel #cakephp at irc.freenode.net for live chat with users and developers of Cake. If you post, tell us the version of Cake, PHP, and database. en constructng result array when using findall http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f i'm using cakephp to construct a logical data model array that will be <br> passed to a flex app. I have the following model association: <br> ServiceDay-&gt;(hasMany)ServiceTi me-&gt;(hasMany)ServiceTimePrice. So what <br> the current output from my findall is something like this example: <br> <p>Array( <br> [0] =&gt; Array( cakephp http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f bmil...@gmail.com(bpscrugs) Fri, 28 Dec 2007 00:44:14 UT Re: share views between actions? http://groups.google.com/group/cake-php/msg/8b350d898707dad8 Then perhaps you might do us all a favour and refrain from replying to <br> things you do not understand. That goes especially for asinine comments. <br> Indeed. <br> To sum up: <br> No comment. <br> In my day, a simple &quot;RTFM&quot; would suffice. I'll keep in mind to ignore any <br> further responses from you. <br> You (and I) were referring to the *online documentation*, not other cakephp http://groups.google.com/group/cake-php/msg/8b350d898707dad8 subtropolis.z...@gmail.com(subtropolis zijn) Fri, 28 Dec 2007 00:45:01 UT '; $xml = Xml::build($string); $result = Set::reverse($xml); $expected = array('rss' => array( '@version' => '2.0', 'channel' => array( 'title' => 'Cake PHP Google Group', 'link' => 'http://groups.google.com/group/cake-php', 'description' => 'Search this group before posting anything. There are over 20,000 posts and it's very likely your question was answered before. Visit the IRC channel #cakephp at irc.freenode.net for live chat with users and developers of Cake. If you post, tell us the version of Cake, PHP, and database.', 'language' => 'en', 'item' => array( array( 'title' => 'constructng result array when using findall', 'link' => 'http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f', 'description' => "i'm using cakephp to construct a logical data model array that will be
passed to a flex app. I have the following model association:
ServiceDay->(hasMany)ServiceTi me->(hasMany)ServiceTimePrice. So what
the current output from my findall is something like this example:

Array(
[0] => Array(", 'dc:creator' => 'cakephp', 'category' => array('cakephp', 'model'), 'guid' => array('@isPermaLink' => 'true', '@' => 'http://groups.google.com/group/cake-php/msg/49bc00f3bc651b4f'), 'author' => 'bmil...@gmail.com(bpscrugs)', 'pubDate' => 'Fri, 28 Dec 2007 00:44:14 UT', ), array( 'title' => 'Re: share views between actions?', 'link' => 'http://groups.google.com/group/cake-php/msg/8b350d898707dad8', 'description' => 'Then perhaps you might do us all a favour and refrain from replying to
things you do not understand. That goes especially for asinine comments.
Indeed.
To sum up:
No comment.
In my day, a simple "RTFM" would suffice. I\'ll keep in mind to ignore any
further responses from you.
You (and I) were referring to the *online documentation*, not other', 'dc:creator' => 'cakephp', 'category' => array('cakephp', 'model'), 'guid' => array('@isPermaLink' => 'true', '@' => 'http://groups.google.com/group/cake-php/msg/8b350d898707dad8'), 'author' => 'subtropolis.z...@gmail.com(subtropolis zijn)', 'pubDate' => 'Fri, 28 Dec 2007 00:45:01 UT' ) ) ) )); $this->assertEquals($expected, $result); $text = ' xri://$xrds*simple 2008-04-13T07:34:58Z http://oauth.net/core/1.0/endpoint/authorize http://oauth.net/core/1.0/parameters/auth-header http://oauth.net/core/1.0/parameters/uri-query https://ma.gnolia.com/oauth/authorize http://ma.gnolia.com/oauth/authorize xri://$xrds*simple http://oauth.net/discovery/1.0 #oauth '; $xml = Xml::build($text); $result = Set::reverse($xml); $expected = array('XRDS' => array( 'XRD' => array( array( '@xml:id' => 'oauth', '@version' => '2.0', 'Type' => 'xri://$xrds*simple', 'Expires' => '2008-04-13T07:34:58Z', 'Service' => array( 'Type' => array( 'http://oauth.net/core/1.0/endpoint/authorize', 'http://oauth.net/core/1.0/parameters/auth-header', 'http://oauth.net/core/1.0/parameters/uri-query' ), 'URI' => array( array( '@' => 'https://ma.gnolia.com/oauth/authorize', '@priority' => '10', ), array( '@' => 'http://ma.gnolia.com/oauth/authorize', '@priority' => '20' ) ) ) ), array( '@version' => '2.0', 'Type' => 'xri://$xrds*simple', 'Service' => array( '@priority' => '10', 'Type' => 'http://oauth.net/discovery/1.0', 'URI' => '#oauth' ) ) ) )); $this->assertEquals($expected, $result); } /** * testStrictKeyCheck method * * @return void */ public function testStrictKeyCheck() { $set = array('a' => 'hi'); $this->assertFalse(Set::check($set, 'a.b')); } /** * Tests Set::flatten * * @see Hash test cases, as Set::flatten() is just a proxy. * @return void */ public function testFlatten() { $data = array('Larry', 'Curly', 'Moe'); $result = Set::flatten($data); $this->assertEquals($data, $result); $data[9] = 'Shemp'; $result = Set::flatten($data); $this->assertEquals($data, $result); $data = array( array( 'Post' => array('id' => '1', 'author_id' => null, 'title' => 'First Post'), 'Author' => array(), ) ); $result = Set::flatten($data); $expected = array( '0.Post.id' => '1', '0.Post.author_id' => null, '0.Post.title' => 'First Post', '0.Author' => array() ); $this->assertEquals($expected, $result); } /** * Tests Set::expand * * @return void */ public function testExpand() { $data = array('My', 'Array', 'To', 'Flatten'); $flat = Set::flatten($data); $result = Set::expand($flat); $this->assertEquals($data, $result); } /** * test normalization * * @return void */ public function testNormalizeStrings() { $result = Set::normalize('one,two,three'); $expected = array('one' => null, 'two' => null, 'three' => null); $this->assertEquals($expected, $result); $result = Set::normalize('one two three', true, ' '); $expected = array('one' => null, 'two' => null, 'three' => null); $this->assertEquals($expected, $result); $result = Set::normalize('one , two , three ', true, ',', true); $expected = array('one' => null, 'two' => null, 'three' => null); $this->assertEquals($expected, $result); } /** * test normalizing arrays * * @return void */ public function testNormalizeArrays() { $result = Set::normalize(array('one', 'two', 'three')); $expected = array('one' => null, 'two' => null, 'three' => null); $this->assertEquals($expected, $result); $result = Set::normalize(array('one', 'two', 'three'), false); $expected = array('one', 'two', 'three'); $this->assertEquals($expected, $result); $result = Set::normalize(array('one' => 1, 'two' => 2, 'three' => 3, 'four'), false); $expected = array('one' => 1, 'two' => 2, 'three' => 3, 'four' => null); $this->assertEquals($expected, $result); $result = Set::normalize(array('one' => 1, 'two' => 2, 'three' => 3, 'four')); $expected = array('one' => 1, 'two' => 2, 'three' => 3, 'four' => null); $this->assertEquals($expected, $result); $result = Set::normalize(array('one' => array('a', 'b', 'c' => 'cee'), 'two' => 2, 'three')); $expected = array('one' => array('a', 'b', 'c' => 'cee'), 'two' => 2, 'three' => null); $this->assertEquals($expected, $result); } /** * test Set nest with a normal model result set. For kicks rely on Set nest detecting the key names * automatically * * @return void */ public function testNestModel() { $input = array( array( 'ModelName' => array( 'id' => 1, 'parent_id' => null ), ), array( 'ModelName' => array( 'id' => 2, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 3, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 4, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 5, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 6, 'parent_id' => null ), ), array( 'ModelName' => array( 'id' => 7, 'parent_id' => 6 ), ), array( 'ModelName' => array( 'id' => 8, 'parent_id' => 6 ), ), array( 'ModelName' => array( 'id' => 9, 'parent_id' => 6 ), ), array( 'ModelName' => array( 'id' => 10, 'parent_id' => 6 ) ) ); $expected = array( array( 'ModelName' => array( 'id' => 1, 'parent_id' => null ), 'children' => array( array( 'ModelName' => array( 'id' => 2, 'parent_id' => 1 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 3, 'parent_id' => 1 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 4, 'parent_id' => 1 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 5, 'parent_id' => 1 ), 'children' => array() ), ) ), array( 'ModelName' => array( 'id' => 6, 'parent_id' => null ), 'children' => array( array( 'ModelName' => array( 'id' => 7, 'parent_id' => 6 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 8, 'parent_id' => 6 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 9, 'parent_id' => 6 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 10, 'parent_id' => 6 ), 'children' => array() ) ) ) ); $result = Set::nest($input); $this->assertEquals($expected, $result); } /** * test Set nest with a normal model result set, and a nominated root id * * @return void */ public function testNestModelExplicitRoot() { $input = array( array( 'ModelName' => array( 'id' => 1, 'parent_id' => null ), ), array( 'ModelName' => array( 'id' => 2, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 3, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 4, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 5, 'parent_id' => 1 ), ), array( 'ModelName' => array( 'id' => 6, 'parent_id' => null ), ), array( 'ModelName' => array( 'id' => 7, 'parent_id' => 6 ), ), array( 'ModelName' => array( 'id' => 8, 'parent_id' => 6 ), ), array( 'ModelName' => array( 'id' => 9, 'parent_id' => 6 ), ), array( 'ModelName' => array( 'id' => 10, 'parent_id' => 6 ) ) ); $expected = array( array( 'ModelName' => array( 'id' => 6, 'parent_id' => null ), 'children' => array( array( 'ModelName' => array( 'id' => 7, 'parent_id' => 6 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 8, 'parent_id' => 6 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 9, 'parent_id' => 6 ), 'children' => array() ), array( 'ModelName' => array( 'id' => 10, 'parent_id' => 6 ), 'children' => array() ) ) ) ); $result = Set::nest($input, array('root' => 6)); $this->assertEquals($expected, $result); } /** * test Set nest with a 1d array - this method should be able to handle any type of array input * * @return void */ public function testNest1Dimensional() { $input = array( array( 'id' => 1, 'parent_id' => null ), array( 'id' => 2, 'parent_id' => 1 ), array( 'id' => 3, 'parent_id' => 1 ), array( 'id' => 4, 'parent_id' => 1 ), array( 'id' => 5, 'parent_id' => 1 ), array( 'id' => 6, 'parent_id' => null ), array( 'id' => 7, 'parent_id' => 6 ), array( 'id' => 8, 'parent_id' => 6 ), array( 'id' => 9, 'parent_id' => 6 ), array( 'id' => 10, 'parent_id' => 6 ) ); $expected = array( array( 'id' => 1, 'parent_id' => null, 'children' => array( array( 'id' => 2, 'parent_id' => 1, 'children' => array() ), array( 'id' => 3, 'parent_id' => 1, 'children' => array() ), array( 'id' => 4, 'parent_id' => 1, 'children' => array() ), array( 'id' => 5, 'parent_id' => 1, 'children' => array() ), ) ), array( 'id' => 6, 'parent_id' => null, 'children' => array( array( 'id' => 7, 'parent_id' => 6, 'children' => array() ), array( 'id' => 8, 'parent_id' => 6, 'children' => array() ), array( 'id' => 9, 'parent_id' => 6, 'children' => array() ), array( 'id' => 10, 'parent_id' => 6, 'children' => array() ) ) ) ); $result = Set::nest($input, array('idPath' => '/id', 'parentPath' => '/parent_id')); $this->assertEquals($expected, $result); } /** * test Set nest with no specified parent data. * * The result should be the same as the input. * For an easier comparison, unset all the empty children arrays from the result * * @return void */ public function testMissingParent() { $input = array( array( 'id' => 1, ), array( 'id' => 2, ), array( 'id' => 3, ), array( 'id' => 4, ), array( 'id' => 5, ), array( 'id' => 6, ), array( 'id' => 7, ), array( 'id' => 8, ), array( 'id' => 9, ), array( 'id' => 10, ) ); $result = Set::nest($input, array('idPath' => '/id', 'parentPath' => '/parent_id')); foreach ($result as &$row) { if (empty($row['children'])) { unset($row['children']); } } $this->assertEquals($input, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/Utility/ValidationTest.php000066400000000000000000003352041265552240500234620ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice. * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Utility * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Validation', 'Utility'); /** * CustomValidator class * * @package Cake.Test.Case.Utility */ class CustomValidator { /** * Makes sure that a given $email address is valid and unique * * @param string $check Email to check. * @return bool */ public static function customValidate($check) { return (bool)preg_match('/^[0-9]{3}$/', $check); } } /** * TestNlValidation class * * Used to test pass through of Validation * * @package Cake.Test.Case.Utility */ class TestNlValidation { /** * postal function, for testing postal pass through. * * @param string $check * @return void */ public static function postal($check) { return true; } /** * ssn function for testing ssn pass through * * @return void */ public static function ssn($check) { return true; } } /** * TestDeValidation class * * Used to test pass through of Validation * * @package Cake.Test.Case.Utility */ class TestDeValidation { /** * phone function, for testing phone pass through. * * @param string $check * @return void */ public static function phone($check) { return true; } } /** * Test Case for Validation Class * * @package Cake.Test.Case.Utility */ class ValidationTest extends CakeTestCase { /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->_appEncoding = Configure::read('App.encoding'); $this->_appLocale = array(); foreach (array(LC_MONETARY, LC_NUMERIC, LC_TIME) as $category) { $this->_appLocale[$category] = setlocale($category, 0); setlocale($category, 'en_US'); } } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); Configure::write('App.encoding', $this->_appEncoding); foreach ($this->_appLocale as $category => $locale) { setlocale($category, $locale); } } /** * Test notBlank method * * @return void */ public function testNotBlank() { $this->assertTrue(Validation::notBlank('abcdefg')); $this->assertTrue(Validation::notBlank('fasdf ')); $this->assertTrue(Validation::notBlank('fooo' . chr(243) . 'blabla')); $this->assertTrue(Validation::notBlank('abรงฤฤ•ส‘ส˜ฯ€ะน')); $this->assertTrue(Validation::notBlank('Josรฉ')); $this->assertTrue(Validation::notBlank('รฉ')); $this->assertTrue(Validation::notBlank('ฯ€')); $this->assertFalse(Validation::notBlank("\t ")); $this->assertFalse(Validation::notBlank("")); } /** * Test notBlank method with ISO88591 encoding * * @return void */ public function testNotBlankISO88591AppEncoding() { Configure::write('App.encoding', 'ISO-8859-1'); $this->assertTrue(Validation::notBlank('abcdefg')); $this->assertTrue(Validation::notBlank('fasdf ')); $this->assertTrue(Validation::notBlank('fooo' . chr(243) . 'blabla')); $this->assertTrue(Validation::notBlank('abรงฤฤ•ส‘ส˜ฯ€ะน')); $this->assertTrue(Validation::notBlank('Josรฉ')); $this->assertTrue(Validation::notBlank(utf8_decode('Josรฉ'))); $this->assertFalse(Validation::notBlank("\t ")); $this->assertFalse(Validation::notBlank("")); } /** * testAlphaNumeric method * * @return void */ public function testAlphaNumeric() { $this->assertTrue(Validation::alphaNumeric('frferrf')); $this->assertTrue(Validation::alphaNumeric('12234')); $this->assertTrue(Validation::alphaNumeric('1w2e2r3t4y')); $this->assertTrue(Validation::alphaNumeric('0')); $this->assertTrue(Validation::alphaNumeric('abรงฤฤ•ส‘ส˜ฯ€ะน')); $this->assertTrue(Validation::alphaNumeric('ห‡ห†เน†ใ‚ž')); $this->assertTrue(Validation::alphaNumeric('ืเธใ‚ใ‚ข๊€€่ฑˆ')); $this->assertTrue(Validation::alphaNumeric('ว…แพˆแพจ')); $this->assertTrue(Validation::alphaNumeric('ร†ฮ”ฮฉะ–ร‡')); $this->assertFalse(Validation::alphaNumeric('12 234')); $this->assertFalse(Validation::alphaNumeric('dfd 234')); $this->assertFalse(Validation::alphaNumeric("0\n")); $this->assertFalse(Validation::alphaNumeric("\n")); $this->assertFalse(Validation::alphaNumeric("\t")); $this->assertFalse(Validation::alphaNumeric("\r")); $this->assertFalse(Validation::alphaNumeric(' ')); $this->assertFalse(Validation::alphaNumeric('')); } /** * testLengthBetween method * * @return void */ public function testLengthBetween() { $this->assertTrue(Validation::lengthBetween('abcdefg', 1, 7)); $this->assertTrue(Validation::lengthBetween('', 0, 7)); $this->assertTrue(Validation::lengthBetween('ืเธใ‚ใ‚ข๊€€่ฑˆ', 1, 7)); $this->assertFalse(Validation::lengthBetween('abcdefg', 1, 6)); $this->assertFalse(Validation::lengthBetween('ร†ฮ”ฮฉะ–ร‡', 1, 3)); } /** * testBlank method * * @return void */ public function testBlank() { $this->assertTrue(Validation::blank('')); $this->assertTrue(Validation::blank(' ')); $this->assertTrue(Validation::blank("\n")); $this->assertTrue(Validation::blank("\t")); $this->assertTrue(Validation::blank("\r")); $this->assertFalse(Validation::blank(' Blank')); $this->assertFalse(Validation::blank('Blank')); } /** * testcc method * * @return void */ public function testCc() { //American Express $this->assertTrue(Validation::cc('370482756063980', array('amex'))); $this->assertTrue(Validation::cc('349106433773483', array('amex'))); $this->assertTrue(Validation::cc('344671486204764', array('amex'))); $this->assertTrue(Validation::cc('344042544509943', array('amex'))); $this->assertTrue(Validation::cc('377147515754475', array('amex'))); $this->assertTrue(Validation::cc('375239372816422', array('amex'))); $this->assertTrue(Validation::cc('376294341957707', array('amex'))); $this->assertTrue(Validation::cc('341779292230411', array('amex'))); $this->assertTrue(Validation::cc('341646919853372', array('amex'))); $this->assertTrue(Validation::cc('348498616319346', array('amex'))); //BankCard $this->assertTrue(Validation::cc('5610745867413420', array('bankcard'))); $this->assertTrue(Validation::cc('5610376649499352', array('bankcard'))); $this->assertTrue(Validation::cc('5610091936000694', array('bankcard'))); $this->assertTrue(Validation::cc('5602248780118788', array('bankcard'))); $this->assertTrue(Validation::cc('5610631567676765', array('bankcard'))); $this->assertTrue(Validation::cc('5602238211270795', array('bankcard'))); $this->assertTrue(Validation::cc('5610173951215470', array('bankcard'))); $this->assertTrue(Validation::cc('5610139705753702', array('bankcard'))); $this->assertTrue(Validation::cc('5602226032150551', array('bankcard'))); $this->assertTrue(Validation::cc('5602223993735777', array('bankcard'))); //Diners Club 14 $this->assertTrue(Validation::cc('30155483651028', array('diners'))); $this->assertTrue(Validation::cc('36371312803821', array('diners'))); $this->assertTrue(Validation::cc('38801277489875', array('diners'))); $this->assertTrue(Validation::cc('30348560464296', array('diners'))); $this->assertTrue(Validation::cc('30349040317708', array('diners'))); $this->assertTrue(Validation::cc('36567413559978', array('diners'))); $this->assertTrue(Validation::cc('36051554732702', array('diners'))); $this->assertTrue(Validation::cc('30391842198191', array('diners'))); $this->assertTrue(Validation::cc('30172682197745', array('diners'))); $this->assertTrue(Validation::cc('30162056566641', array('diners'))); $this->assertTrue(Validation::cc('30085066927745', array('diners'))); $this->assertTrue(Validation::cc('36519025221976', array('diners'))); $this->assertTrue(Validation::cc('30372679371044', array('diners'))); $this->assertTrue(Validation::cc('38913939150124', array('diners'))); $this->assertTrue(Validation::cc('36852899094637', array('diners'))); $this->assertTrue(Validation::cc('30138041971120', array('diners'))); $this->assertTrue(Validation::cc('36184047836838', array('diners'))); $this->assertTrue(Validation::cc('30057460264462', array('diners'))); $this->assertTrue(Validation::cc('38980165212050', array('diners'))); $this->assertTrue(Validation::cc('30356516881240', array('diners'))); $this->assertTrue(Validation::cc('38744810033182', array('diners'))); $this->assertTrue(Validation::cc('30173638706621', array('diners'))); $this->assertTrue(Validation::cc('30158334709185', array('diners'))); $this->assertTrue(Validation::cc('30195413721186', array('diners'))); $this->assertTrue(Validation::cc('38863347694793', array('diners'))); $this->assertTrue(Validation::cc('30275627009113', array('diners'))); $this->assertTrue(Validation::cc('30242860404971', array('diners'))); $this->assertTrue(Validation::cc('30081877595151', array('diners'))); $this->assertTrue(Validation::cc('38053196067461', array('diners'))); $this->assertTrue(Validation::cc('36520379984870', array('diners'))); //2004 MasterCard/Diners Club Alliance International 14 $this->assertTrue(Validation::cc('36747701998969', array('diners'))); $this->assertTrue(Validation::cc('36427861123159', array('diners'))); $this->assertTrue(Validation::cc('36150537602386', array('diners'))); $this->assertTrue(Validation::cc('36582388820610', array('diners'))); $this->assertTrue(Validation::cc('36729045250216', array('diners'))); //2004 MasterCard/Diners Club Alliance US & Canada 16 $this->assertTrue(Validation::cc('5597511346169950', array('diners'))); $this->assertTrue(Validation::cc('5526443162217562', array('diners'))); $this->assertTrue(Validation::cc('5577265786122391', array('diners'))); $this->assertTrue(Validation::cc('5534061404676989', array('diners'))); $this->assertTrue(Validation::cc('5545313588374502', array('diners'))); //Discover $this->assertTrue(Validation::cc('6011802876467237', array('disc'))); $this->assertTrue(Validation::cc('6506432777720955', array('disc'))); $this->assertTrue(Validation::cc('6011126265283942', array('disc'))); $this->assertTrue(Validation::cc('6502187151579252', array('disc'))); $this->assertTrue(Validation::cc('6506600836002298', array('disc'))); $this->assertTrue(Validation::cc('6504376463615189', array('disc'))); $this->assertTrue(Validation::cc('6011440907005377', array('disc'))); $this->assertTrue(Validation::cc('6509735979634270', array('disc'))); $this->assertTrue(Validation::cc('6011422366775856', array('disc'))); $this->assertTrue(Validation::cc('6500976374623323', array('disc'))); //enRoute $this->assertTrue(Validation::cc('201496944158937', array('enroute'))); $this->assertTrue(Validation::cc('214945833739665', array('enroute'))); $this->assertTrue(Validation::cc('214982692491187', array('enroute'))); $this->assertTrue(Validation::cc('214901395949424', array('enroute'))); $this->assertTrue(Validation::cc('201480676269187', array('enroute'))); $this->assertTrue(Validation::cc('214911922887807', array('enroute'))); $this->assertTrue(Validation::cc('201485025457250', array('enroute'))); $this->assertTrue(Validation::cc('201402662758866', array('enroute'))); $this->assertTrue(Validation::cc('214981579370225', array('enroute'))); $this->assertTrue(Validation::cc('201447595859877', array('enroute'))); //JCB 15 digit $this->assertTrue(Validation::cc('210034762247893', array('jcb'))); $this->assertTrue(Validation::cc('180078671678892', array('jcb'))); $this->assertTrue(Validation::cc('180010559353736', array('jcb'))); $this->assertTrue(Validation::cc('210095474464258', array('jcb'))); $this->assertTrue(Validation::cc('210006675562188', array('jcb'))); $this->assertTrue(Validation::cc('210063299662662', array('jcb'))); $this->assertTrue(Validation::cc('180032506857825', array('jcb'))); $this->assertTrue(Validation::cc('210057919192738', array('jcb'))); $this->assertTrue(Validation::cc('180031358949367', array('jcb'))); $this->assertTrue(Validation::cc('180033802147846', array('jcb'))); //JCB 16 digit $this->assertTrue(Validation::cc('3096806857839939', array('jcb'))); $this->assertTrue(Validation::cc('3158699503187091', array('jcb'))); $this->assertTrue(Validation::cc('3112549607186579', array('jcb'))); $this->assertTrue(Validation::cc('3112332922425604', array('jcb'))); $this->assertTrue(Validation::cc('3112001541159239', array('jcb'))); $this->assertTrue(Validation::cc('3112162495317841', array('jcb'))); $this->assertTrue(Validation::cc('3337562627732768', array('jcb'))); $this->assertTrue(Validation::cc('3337107161330775', array('jcb'))); $this->assertTrue(Validation::cc('3528053736003621', array('jcb'))); $this->assertTrue(Validation::cc('3528915255020360', array('jcb'))); $this->assertTrue(Validation::cc('3096786059660921', array('jcb'))); $this->assertTrue(Validation::cc('3528264799292320', array('jcb'))); $this->assertTrue(Validation::cc('3096469164130136', array('jcb'))); $this->assertTrue(Validation::cc('3112127443822853', array('jcb'))); $this->assertTrue(Validation::cc('3096849995802328', array('jcb'))); $this->assertTrue(Validation::cc('3528090735127407', array('jcb'))); $this->assertTrue(Validation::cc('3112101006819234', array('jcb'))); $this->assertTrue(Validation::cc('3337444428040784', array('jcb'))); $this->assertTrue(Validation::cc('3088043154151061', array('jcb'))); $this->assertTrue(Validation::cc('3088295969414866', array('jcb'))); $this->assertTrue(Validation::cc('3158748843158575', array('jcb'))); $this->assertTrue(Validation::cc('3158709206148538', array('jcb'))); $this->assertTrue(Validation::cc('3158365159575324', array('jcb'))); $this->assertTrue(Validation::cc('3158671691305165', array('jcb'))); $this->assertTrue(Validation::cc('3528523028771093', array('jcb'))); $this->assertTrue(Validation::cc('3096057126267870', array('jcb'))); $this->assertTrue(Validation::cc('3158514047166834', array('jcb'))); $this->assertTrue(Validation::cc('3528274546125962', array('jcb'))); $this->assertTrue(Validation::cc('3528890967705733', array('jcb'))); $this->assertTrue(Validation::cc('3337198811307545', array('jcb'))); //Maestro (debit card) $this->assertTrue(Validation::cc('5020147409985219', array('maestro'))); $this->assertTrue(Validation::cc('5020931809905616', array('maestro'))); $this->assertTrue(Validation::cc('5020412965470224', array('maestro'))); $this->assertTrue(Validation::cc('5020129740944022', array('maestro'))); $this->assertTrue(Validation::cc('5020024696747943', array('maestro'))); $this->assertTrue(Validation::cc('5020581514636509', array('maestro'))); $this->assertTrue(Validation::cc('5020695008411987', array('maestro'))); $this->assertTrue(Validation::cc('5020565359718977', array('maestro'))); $this->assertTrue(Validation::cc('6339931536544062', array('maestro'))); $this->assertTrue(Validation::cc('6465028615704406', array('maestro'))); //Mastercard $this->assertTrue(Validation::cc('5580424361774366', array('mc'))); $this->assertTrue(Validation::cc('5589563059318282', array('mc'))); $this->assertTrue(Validation::cc('5387558333690047', array('mc'))); $this->assertTrue(Validation::cc('5163919215247175', array('mc'))); $this->assertTrue(Validation::cc('5386742685055055', array('mc'))); $this->assertTrue(Validation::cc('5102303335960674', array('mc'))); $this->assertTrue(Validation::cc('5526543403964565', array('mc'))); $this->assertTrue(Validation::cc('5538725892618432', array('mc'))); $this->assertTrue(Validation::cc('5119543573129778', array('mc'))); $this->assertTrue(Validation::cc('5391174753915767', array('mc'))); $this->assertTrue(Validation::cc('5510994113980714', array('mc'))); $this->assertTrue(Validation::cc('5183720260418091', array('mc'))); $this->assertTrue(Validation::cc('5488082196086704', array('mc'))); $this->assertTrue(Validation::cc('5484645164161834', array('mc'))); $this->assertTrue(Validation::cc('5171254350337031', array('mc'))); $this->assertTrue(Validation::cc('5526987528136452', array('mc'))); $this->assertTrue(Validation::cc('5504148941409358', array('mc'))); $this->assertTrue(Validation::cc('5240793507243615', array('mc'))); $this->assertTrue(Validation::cc('5162114693017107', array('mc'))); $this->assertTrue(Validation::cc('5163104807404753', array('mc'))); $this->assertTrue(Validation::cc('5590136167248365', array('mc'))); $this->assertTrue(Validation::cc('5565816281038948', array('mc'))); $this->assertTrue(Validation::cc('5467639122779531', array('mc'))); $this->assertTrue(Validation::cc('5297350261550024', array('mc'))); $this->assertTrue(Validation::cc('5162739131368058', array('mc'))); //Solo 16 $this->assertTrue(Validation::cc('6767432107064987', array('solo'))); $this->assertTrue(Validation::cc('6334667758225411', array('solo'))); $this->assertTrue(Validation::cc('6767037421954068', array('solo'))); $this->assertTrue(Validation::cc('6767823306394854', array('solo'))); $this->assertTrue(Validation::cc('6334768185398134', array('solo'))); $this->assertTrue(Validation::cc('6767286729498589', array('solo'))); $this->assertTrue(Validation::cc('6334972104431261', array('solo'))); $this->assertTrue(Validation::cc('6334843427400616', array('solo'))); $this->assertTrue(Validation::cc('6767493947881311', array('solo'))); $this->assertTrue(Validation::cc('6767194235798817', array('solo'))); //Solo 18 $this->assertTrue(Validation::cc('676714834398858593', array('solo'))); $this->assertTrue(Validation::cc('676751666435130857', array('solo'))); $this->assertTrue(Validation::cc('676781908573924236', array('solo'))); $this->assertTrue(Validation::cc('633488724644003240', array('solo'))); $this->assertTrue(Validation::cc('676732252338067316', array('solo'))); $this->assertTrue(Validation::cc('676747520084495821', array('solo'))); $this->assertTrue(Validation::cc('633465488901381957', array('solo'))); $this->assertTrue(Validation::cc('633487484858610484', array('solo'))); $this->assertTrue(Validation::cc('633453764680740694', array('solo'))); $this->assertTrue(Validation::cc('676768613295414451', array('solo'))); //Solo 19 $this->assertTrue(Validation::cc('6767838565218340113', array('solo'))); $this->assertTrue(Validation::cc('6767760119829705181', array('solo'))); $this->assertTrue(Validation::cc('6767265917091593668', array('solo'))); $this->assertTrue(Validation::cc('6767938856947440111', array('solo'))); $this->assertTrue(Validation::cc('6767501945697390076', array('solo'))); $this->assertTrue(Validation::cc('6334902868716257379', array('solo'))); $this->assertTrue(Validation::cc('6334922127686425532', array('solo'))); $this->assertTrue(Validation::cc('6334933119080706440', array('solo'))); $this->assertTrue(Validation::cc('6334647959628261714', array('solo'))); $this->assertTrue(Validation::cc('6334527312384101382', array('solo'))); //Switch 16 $this->assertTrue(Validation::cc('5641829171515733', array('switch'))); $this->assertTrue(Validation::cc('5641824852820809', array('switch'))); $this->assertTrue(Validation::cc('6759129648956909', array('switch'))); $this->assertTrue(Validation::cc('6759626072268156', array('switch'))); $this->assertTrue(Validation::cc('5641822698388957', array('switch'))); $this->assertTrue(Validation::cc('5641827123105470', array('switch'))); $this->assertTrue(Validation::cc('5641823755819553', array('switch'))); $this->assertTrue(Validation::cc('5641821939587682', array('switch'))); $this->assertTrue(Validation::cc('4936097148079186', array('switch'))); $this->assertTrue(Validation::cc('5641829739125009', array('switch'))); $this->assertTrue(Validation::cc('5641822860725507', array('switch'))); $this->assertTrue(Validation::cc('4936717688865831', array('switch'))); $this->assertTrue(Validation::cc('6759487613615441', array('switch'))); $this->assertTrue(Validation::cc('5641821346840617', array('switch'))); $this->assertTrue(Validation::cc('5641825793417126', array('switch'))); $this->assertTrue(Validation::cc('5641821302759595', array('switch'))); $this->assertTrue(Validation::cc('6759784969918837', array('switch'))); $this->assertTrue(Validation::cc('5641824910667036', array('switch'))); $this->assertTrue(Validation::cc('6759139909636173', array('switch'))); $this->assertTrue(Validation::cc('6333425070638022', array('switch'))); $this->assertTrue(Validation::cc('5641823910382067', array('switch'))); $this->assertTrue(Validation::cc('4936295218139423', array('switch'))); $this->assertTrue(Validation::cc('6333031811316199', array('switch'))); $this->assertTrue(Validation::cc('4936912044763198', array('switch'))); $this->assertTrue(Validation::cc('4936387053303824', array('switch'))); $this->assertTrue(Validation::cc('6759535838760523', array('switch'))); $this->assertTrue(Validation::cc('6333427174594051', array('switch'))); $this->assertTrue(Validation::cc('5641829037102700', array('switch'))); $this->assertTrue(Validation::cc('5641826495463046', array('switch'))); $this->assertTrue(Validation::cc('6333480852979946', array('switch'))); $this->assertTrue(Validation::cc('5641827761302876', array('switch'))); $this->assertTrue(Validation::cc('5641825083505317', array('switch'))); $this->assertTrue(Validation::cc('6759298096003991', array('switch'))); $this->assertTrue(Validation::cc('4936119165483420', array('switch'))); $this->assertTrue(Validation::cc('4936190990500993', array('switch'))); $this->assertTrue(Validation::cc('4903356467384927', array('switch'))); $this->assertTrue(Validation::cc('6333372765092554', array('switch'))); $this->assertTrue(Validation::cc('5641821330950570', array('switch'))); $this->assertTrue(Validation::cc('6759841558826118', array('switch'))); $this->assertTrue(Validation::cc('4936164540922452', array('switch'))); //Switch 18 $this->assertTrue(Validation::cc('493622764224625174', array('switch'))); $this->assertTrue(Validation::cc('564182823396913535', array('switch'))); $this->assertTrue(Validation::cc('675917308304801234', array('switch'))); $this->assertTrue(Validation::cc('675919890024220298', array('switch'))); $this->assertTrue(Validation::cc('633308376862556751', array('switch'))); $this->assertTrue(Validation::cc('564182377633208779', array('switch'))); $this->assertTrue(Validation::cc('564182870014926787', array('switch'))); $this->assertTrue(Validation::cc('675979788553829819', array('switch'))); $this->assertTrue(Validation::cc('493668394358130935', array('switch'))); $this->assertTrue(Validation::cc('493637431790930965', array('switch'))); $this->assertTrue(Validation::cc('633321438601941513', array('switch'))); $this->assertTrue(Validation::cc('675913800898840986', array('switch'))); $this->assertTrue(Validation::cc('564182592016841547', array('switch'))); $this->assertTrue(Validation::cc('564182428380440899', array('switch'))); $this->assertTrue(Validation::cc('493696376827623463', array('switch'))); $this->assertTrue(Validation::cc('675977939286485757', array('switch'))); $this->assertTrue(Validation::cc('490302699502091579', array('switch'))); $this->assertTrue(Validation::cc('564182085013662230', array('switch'))); $this->assertTrue(Validation::cc('493693054263310167', array('switch'))); $this->assertTrue(Validation::cc('633321755966697525', array('switch'))); $this->assertTrue(Validation::cc('675996851719732811', array('switch'))); $this->assertTrue(Validation::cc('493699211208281028', array('switch'))); $this->assertTrue(Validation::cc('493697817378356614', array('switch'))); $this->assertTrue(Validation::cc('675968224161768150', array('switch'))); $this->assertTrue(Validation::cc('493669416873337627', array('switch'))); $this->assertTrue(Validation::cc('564182439172549714', array('switch'))); $this->assertTrue(Validation::cc('675926914467673598', array('switch'))); $this->assertTrue(Validation::cc('564182565231977809', array('switch'))); $this->assertTrue(Validation::cc('675966282607849002', array('switch'))); $this->assertTrue(Validation::cc('493691609704348548', array('switch'))); $this->assertTrue(Validation::cc('675933118546065120', array('switch'))); $this->assertTrue(Validation::cc('493631116677238592', array('switch'))); $this->assertTrue(Validation::cc('675921142812825938', array('switch'))); $this->assertTrue(Validation::cc('633338311815675113', array('switch'))); $this->assertTrue(Validation::cc('633323539867338621', array('switch'))); $this->assertTrue(Validation::cc('675964912740845663', array('switch'))); $this->assertTrue(Validation::cc('633334008833727504', array('switch'))); $this->assertTrue(Validation::cc('493631941273687169', array('switch'))); $this->assertTrue(Validation::cc('564182971729706785', array('switch'))); $this->assertTrue(Validation::cc('633303461188963496', array('switch'))); //Switch 19 $this->assertTrue(Validation::cc('6759603460617628716', array('switch'))); $this->assertTrue(Validation::cc('4936705825268647681', array('switch'))); $this->assertTrue(Validation::cc('5641829846600479183', array('switch'))); $this->assertTrue(Validation::cc('6759389846573792530', array('switch'))); $this->assertTrue(Validation::cc('4936189558712637603', array('switch'))); $this->assertTrue(Validation::cc('5641822217393868189', array('switch'))); $this->assertTrue(Validation::cc('4903075563780057152', array('switch'))); $this->assertTrue(Validation::cc('4936510653566569547', array('switch'))); $this->assertTrue(Validation::cc('4936503083627303364', array('switch'))); $this->assertTrue(Validation::cc('4936777334398116272', array('switch'))); $this->assertTrue(Validation::cc('5641823876900554860', array('switch'))); $this->assertTrue(Validation::cc('6759619236903407276', array('switch'))); $this->assertTrue(Validation::cc('6759011470269978117', array('switch'))); $this->assertTrue(Validation::cc('6333175833997062502', array('switch'))); $this->assertTrue(Validation::cc('6759498728789080439', array('switch'))); $this->assertTrue(Validation::cc('4903020404168157841', array('switch'))); $this->assertTrue(Validation::cc('6759354334874804313', array('switch'))); $this->assertTrue(Validation::cc('6759900856420875115', array('switch'))); $this->assertTrue(Validation::cc('5641827269346868860', array('switch'))); $this->assertTrue(Validation::cc('5641828995047453870', array('switch'))); $this->assertTrue(Validation::cc('6333321884754806543', array('switch'))); $this->assertTrue(Validation::cc('6333108246283715901', array('switch'))); $this->assertTrue(Validation::cc('6759572372800700102', array('switch'))); $this->assertTrue(Validation::cc('4903095096797974933', array('switch'))); $this->assertTrue(Validation::cc('6333354315797920215', array('switch'))); $this->assertTrue(Validation::cc('6759163746089433755', array('switch'))); $this->assertTrue(Validation::cc('6759871666634807647', array('switch'))); $this->assertTrue(Validation::cc('5641827883728575248', array('switch'))); $this->assertTrue(Validation::cc('4936527975051407847', array('switch'))); $this->assertTrue(Validation::cc('5641823318396882141', array('switch'))); $this->assertTrue(Validation::cc('6759123772311123708', array('switch'))); $this->assertTrue(Validation::cc('4903054736148271088', array('switch'))); $this->assertTrue(Validation::cc('4936477526808883952', array('switch'))); $this->assertTrue(Validation::cc('4936433964890967966', array('switch'))); $this->assertTrue(Validation::cc('6333245128906049344', array('switch'))); $this->assertTrue(Validation::cc('4936321036970553134', array('switch'))); $this->assertTrue(Validation::cc('4936111816358702773', array('switch'))); $this->assertTrue(Validation::cc('4936196077254804290', array('switch'))); $this->assertTrue(Validation::cc('6759558831206830183', array('switch'))); $this->assertTrue(Validation::cc('5641827998830403137', array('switch'))); //VISA 13 digit $this->assertTrue(Validation::cc('4024007174754', array('visa'))); $this->assertTrue(Validation::cc('4104816460717', array('visa'))); $this->assertTrue(Validation::cc('4716229700437', array('visa'))); $this->assertTrue(Validation::cc('4539305400213', array('visa'))); $this->assertTrue(Validation::cc('4728260558665', array('visa'))); $this->assertTrue(Validation::cc('4929100131792', array('visa'))); $this->assertTrue(Validation::cc('4024007117308', array('visa'))); $this->assertTrue(Validation::cc('4539915491024', array('visa'))); $this->assertTrue(Validation::cc('4539790901139', array('visa'))); $this->assertTrue(Validation::cc('4485284914909', array('visa'))); $this->assertTrue(Validation::cc('4782793022350', array('visa'))); $this->assertTrue(Validation::cc('4556899290685', array('visa'))); $this->assertTrue(Validation::cc('4024007134774', array('visa'))); $this->assertTrue(Validation::cc('4333412341316', array('visa'))); $this->assertTrue(Validation::cc('4539534204543', array('visa'))); $this->assertTrue(Validation::cc('4485640373626', array('visa'))); $this->assertTrue(Validation::cc('4929911445746', array('visa'))); $this->assertTrue(Validation::cc('4539292550806', array('visa'))); $this->assertTrue(Validation::cc('4716523014030', array('visa'))); $this->assertTrue(Validation::cc('4024007125152', array('visa'))); $this->assertTrue(Validation::cc('4539758883311', array('visa'))); $this->assertTrue(Validation::cc('4024007103258', array('visa'))); $this->assertTrue(Validation::cc('4916933155767', array('visa'))); $this->assertTrue(Validation::cc('4024007159672', array('visa'))); $this->assertTrue(Validation::cc('4716935544871', array('visa'))); $this->assertTrue(Validation::cc('4929415177779', array('visa'))); $this->assertTrue(Validation::cc('4929748547896', array('visa'))); $this->assertTrue(Validation::cc('4929153468612', array('visa'))); $this->assertTrue(Validation::cc('4539397132104', array('visa'))); $this->assertTrue(Validation::cc('4485293435540', array('visa'))); $this->assertTrue(Validation::cc('4485799412720', array('visa'))); $this->assertTrue(Validation::cc('4916744757686', array('visa'))); $this->assertTrue(Validation::cc('4556475655426', array('visa'))); $this->assertTrue(Validation::cc('4539400441625', array('visa'))); $this->assertTrue(Validation::cc('4485437129173', array('visa'))); $this->assertTrue(Validation::cc('4716253605320', array('visa'))); $this->assertTrue(Validation::cc('4539366156589', array('visa'))); $this->assertTrue(Validation::cc('4916498061392', array('visa'))); $this->assertTrue(Validation::cc('4716127163779', array('visa'))); $this->assertTrue(Validation::cc('4024007183078', array('visa'))); $this->assertTrue(Validation::cc('4041553279654', array('visa'))); $this->assertTrue(Validation::cc('4532380121960', array('visa'))); $this->assertTrue(Validation::cc('4485906062491', array('visa'))); $this->assertTrue(Validation::cc('4539365115149', array('visa'))); $this->assertTrue(Validation::cc('4485146516702', array('visa'))); //VISA 16 digit $this->assertTrue(Validation::cc('4916375389940009', array('visa'))); $this->assertTrue(Validation::cc('4929167481032610', array('visa'))); $this->assertTrue(Validation::cc('4485029969061519', array('visa'))); $this->assertTrue(Validation::cc('4485573845281759', array('visa'))); $this->assertTrue(Validation::cc('4485669810383529', array('visa'))); $this->assertTrue(Validation::cc('4929615806560327', array('visa'))); $this->assertTrue(Validation::cc('4556807505609535', array('visa'))); $this->assertTrue(Validation::cc('4532611336232890', array('visa'))); $this->assertTrue(Validation::cc('4532201952422387', array('visa'))); $this->assertTrue(Validation::cc('4485073797976290', array('visa'))); $this->assertTrue(Validation::cc('4024007157580969', array('visa'))); $this->assertTrue(Validation::cc('4053740470212274', array('visa'))); $this->assertTrue(Validation::cc('4716265831525676', array('visa'))); $this->assertTrue(Validation::cc('4024007100222966', array('visa'))); $this->assertTrue(Validation::cc('4539556148303244', array('visa'))); $this->assertTrue(Validation::cc('4532449879689709', array('visa'))); $this->assertTrue(Validation::cc('4916805467840986', array('visa'))); $this->assertTrue(Validation::cc('4532155644440233', array('visa'))); $this->assertTrue(Validation::cc('4467977802223781', array('visa'))); $this->assertTrue(Validation::cc('4539224637000686', array('visa'))); $this->assertTrue(Validation::cc('4556629187064965', array('visa'))); $this->assertTrue(Validation::cc('4532970205932943', array('visa'))); $this->assertTrue(Validation::cc('4821470132041850', array('visa'))); $this->assertTrue(Validation::cc('4916214267894485', array('visa'))); $this->assertTrue(Validation::cc('4024007169073284', array('visa'))); $this->assertTrue(Validation::cc('4716783351296122', array('visa'))); $this->assertTrue(Validation::cc('4556480171913795', array('visa'))); $this->assertTrue(Validation::cc('4929678411034997', array('visa'))); $this->assertTrue(Validation::cc('4682061913519392', array('visa'))); $this->assertTrue(Validation::cc('4916495481746474', array('visa'))); $this->assertTrue(Validation::cc('4929007108460499', array('visa'))); $this->assertTrue(Validation::cc('4539951357838586', array('visa'))); $this->assertTrue(Validation::cc('4716482691051558', array('visa'))); $this->assertTrue(Validation::cc('4916385069917516', array('visa'))); $this->assertTrue(Validation::cc('4929020289494641', array('visa'))); $this->assertTrue(Validation::cc('4532176245263774', array('visa'))); $this->assertTrue(Validation::cc('4556242273553949', array('visa'))); $this->assertTrue(Validation::cc('4481007485188614', array('visa'))); $this->assertTrue(Validation::cc('4716533372139623', array('visa'))); $this->assertTrue(Validation::cc('4929152038152632', array('visa'))); $this->assertTrue(Validation::cc('4539404037310550', array('visa'))); $this->assertTrue(Validation::cc('4532800925229140', array('visa'))); $this->assertTrue(Validation::cc('4916845885268360', array('visa'))); $this->assertTrue(Validation::cc('4394514669078434', array('visa'))); $this->assertTrue(Validation::cc('4485611378115042', array('visa'))); //Visa Electron $this->assertTrue(Validation::cc('4175003346287100', array('electron'))); $this->assertTrue(Validation::cc('4913042516577228', array('electron'))); $this->assertTrue(Validation::cc('4917592325659381', array('electron'))); $this->assertTrue(Validation::cc('4917084924450511', array('electron'))); $this->assertTrue(Validation::cc('4917994610643999', array('electron'))); $this->assertTrue(Validation::cc('4175005933743585', array('electron'))); $this->assertTrue(Validation::cc('4175008373425044', array('electron'))); $this->assertTrue(Validation::cc('4913119763664154', array('electron'))); $this->assertTrue(Validation::cc('4913189017481812', array('electron'))); $this->assertTrue(Validation::cc('4913085104968622', array('electron'))); $this->assertTrue(Validation::cc('4175008803122021', array('electron'))); $this->assertTrue(Validation::cc('4913294453962489', array('electron'))); $this->assertTrue(Validation::cc('4175009797419290', array('electron'))); $this->assertTrue(Validation::cc('4175005028142917', array('electron'))); $this->assertTrue(Validation::cc('4913940802385364', array('electron'))); //Voyager $this->assertTrue(Validation::cc('869940697287073', array('voyager'))); $this->assertTrue(Validation::cc('869934523596112', array('voyager'))); $this->assertTrue(Validation::cc('869958670174621', array('voyager'))); $this->assertTrue(Validation::cc('869921250068209', array('voyager'))); $this->assertTrue(Validation::cc('869972521242198', array('voyager'))); } /** * testLuhn method * * @return void */ public function testLuhn() { //American Express $this->assertTrue(Validation::luhn('370482756063980', true)); //BankCard $this->assertTrue(Validation::luhn('5610745867413420', true)); //Diners Club 14 $this->assertTrue(Validation::luhn('30155483651028', true)); //2004 MasterCard/Diners Club Alliance International 14 $this->assertTrue(Validation::luhn('36747701998969', true)); //2004 MasterCard/Diners Club Alliance US & Canada 16 $this->assertTrue(Validation::luhn('5597511346169950', true)); //Discover $this->assertTrue(Validation::luhn('6011802876467237', true)); //enRoute $this->assertTrue(Validation::luhn('201496944158937', true)); //JCB 15 digit $this->assertTrue(Validation::luhn('210034762247893', true)); //JCB 16 digit $this->assertTrue(Validation::luhn('3096806857839939', true)); //Maestro (debit card) $this->assertTrue(Validation::luhn('5020147409985219', true)); //Mastercard $this->assertTrue(Validation::luhn('5580424361774366', true)); //Solo 16 $this->assertTrue(Validation::luhn('6767432107064987', true)); //Solo 18 $this->assertTrue(Validation::luhn('676714834398858593', true)); //Solo 19 $this->assertTrue(Validation::luhn('6767838565218340113', true)); //Switch 16 $this->assertTrue(Validation::luhn('5641829171515733', true)); //Switch 18 $this->assertTrue(Validation::luhn('493622764224625174', true)); //Switch 19 $this->assertTrue(Validation::luhn('6759603460617628716', true)); //VISA 13 digit $this->assertTrue(Validation::luhn('4024007174754', true)); //VISA 16 digit $this->assertTrue(Validation::luhn('4916375389940009', true)); //Visa Electron $this->assertTrue(Validation::luhn('4175003346287100', true)); //Voyager $this->assertTrue(Validation::luhn('869940697287073', true)); $this->assertFalse(Validation::luhn('0000000000000000', true)); $this->assertFalse(Validation::luhn('869940697287173', true)); } /** * testCustomRegexForCc method * * @return void */ public function testCustomRegexForCc() { $this->assertTrue(Validation::cc('12332105933743585', null, null, '/123321\\d{11}/')); $this->assertFalse(Validation::cc('1233210593374358', null, null, '/123321\\d{11}/')); $this->assertFalse(Validation::cc('12312305933743585', null, null, '/123321\\d{11}/')); } /** * testCustomRegexForCcWithLuhnCheck method * * @return void */ public function testCustomRegexForCcWithLuhnCheck() { $this->assertTrue(Validation::cc('12332110426226941', null, true, '/123321\\d{11}/')); $this->assertFalse(Validation::cc('12332105933743585', null, true, '/123321\\d{11}/')); $this->assertFalse(Validation::cc('12332105933743587', null, true, '/123321\\d{11}/')); $this->assertFalse(Validation::cc('12312305933743585', null, true, '/123321\\d{11}/')); } /** * testFastCc method * * @return void */ public function testFastCc() { // too short $this->assertFalse(Validation::cc('123456789012')); //American Express $this->assertTrue(Validation::cc('370482756063980')); //Diners Club 14 $this->assertTrue(Validation::cc('30155483651028')); //2004 MasterCard/Diners Club Alliance International 14 $this->assertTrue(Validation::cc('36747701998969')); //2004 MasterCard/Diners Club Alliance US & Canada 16 $this->assertTrue(Validation::cc('5597511346169950')); //Discover $this->assertTrue(Validation::cc('6011802876467237')); //Mastercard $this->assertTrue(Validation::cc('5580424361774366')); //VISA 13 digit $this->assertTrue(Validation::cc('4024007174754')); //VISA 16 digit $this->assertTrue(Validation::cc('4916375389940009')); //Visa Electron $this->assertTrue(Validation::cc('4175003346287100')); } /** * testAllCc method * * @return void */ public function testAllCc() { //American Express $this->assertTrue(Validation::cc('370482756063980', 'all')); //BankCard $this->assertTrue(Validation::cc('5610745867413420', 'all')); //Diners Club 14 $this->assertTrue(Validation::cc('30155483651028', 'all')); //2004 MasterCard/Diners Club Alliance International 14 $this->assertTrue(Validation::cc('36747701998969', 'all')); //2004 MasterCard/Diners Club Alliance US & Canada 16 $this->assertTrue(Validation::cc('5597511346169950', 'all')); //Discover $this->assertTrue(Validation::cc('6011802876467237', 'all')); //enRoute $this->assertTrue(Validation::cc('201496944158937', 'all')); //JCB 15 digit $this->assertTrue(Validation::cc('210034762247893', 'all')); //JCB 16 digit $this->assertTrue(Validation::cc('3096806857839939', 'all')); //Maestro (debit card) $this->assertTrue(Validation::cc('5020147409985219', 'all')); //Mastercard $this->assertTrue(Validation::cc('5580424361774366', 'all')); //Solo 16 $this->assertTrue(Validation::cc('6767432107064987', 'all')); //Solo 18 $this->assertTrue(Validation::cc('676714834398858593', 'all')); //Solo 19 $this->assertTrue(Validation::cc('6767838565218340113', 'all')); //Switch 16 $this->assertTrue(Validation::cc('5641829171515733', 'all')); //Switch 18 $this->assertTrue(Validation::cc('493622764224625174', 'all')); //Switch 19 $this->assertTrue(Validation::cc('6759603460617628716', 'all')); //VISA 13 digit $this->assertTrue(Validation::cc('4024007174754', 'all')); //VISA 16 digit $this->assertTrue(Validation::cc('4916375389940009', 'all')); //Visa Electron $this->assertTrue(Validation::cc('4175003346287100', 'all')); //Voyager $this->assertTrue(Validation::cc('869940697287073', 'all')); } /** * testAllCcDeep method * * @return void */ public function testAllCcDeep() { //American Express $this->assertTrue(Validation::cc('370482756063980', 'all', true)); //BankCard $this->assertTrue(Validation::cc('5610745867413420', 'all', true)); //Diners Club 14 $this->assertTrue(Validation::cc('30155483651028', 'all', true)); //2004 MasterCard/Diners Club Alliance International 14 $this->assertTrue(Validation::cc('36747701998969', 'all', true)); //2004 MasterCard/Diners Club Alliance US & Canada 16 $this->assertTrue(Validation::cc('5597511346169950', 'all', true)); //Discover $this->assertTrue(Validation::cc('6011802876467237', 'all', true)); //enRoute $this->assertTrue(Validation::cc('201496944158937', 'all', true)); //JCB 15 digit $this->assertTrue(Validation::cc('210034762247893', 'all', true)); //JCB 16 digit $this->assertTrue(Validation::cc('3096806857839939', 'all', true)); //Maestro (debit card) $this->assertTrue(Validation::cc('5020147409985219', 'all', true)); //Mastercard $this->assertTrue(Validation::cc('5580424361774366', 'all', true)); //Solo 16 $this->assertTrue(Validation::cc('6767432107064987', 'all', true)); //Solo 18 $this->assertTrue(Validation::cc('676714834398858593', 'all', true)); //Solo 19 $this->assertTrue(Validation::cc('6767838565218340113', 'all', true)); //Switch 16 $this->assertTrue(Validation::cc('5641829171515733', 'all', true)); //Switch 18 $this->assertTrue(Validation::cc('493622764224625174', 'all', true)); //Switch 19 $this->assertTrue(Validation::cc('6759603460617628716', 'all', true)); //VISA 13 digit $this->assertTrue(Validation::cc('4024007174754', 'all', true)); //VISA 16 digit $this->assertTrue(Validation::cc('4916375389940009', 'all', true)); //Visa Electron $this->assertTrue(Validation::cc('4175003346287100', 'all', true)); //Voyager $this->assertTrue(Validation::cc('869940697287073', 'all', true)); } /** * testComparison method * * @return void */ public function testComparison() { $this->assertFalse(Validation::comparison(7, null, 6)); $this->assertTrue(Validation::comparison(7, 'is greater', 6)); $this->assertTrue(Validation::comparison(7, '>', 6)); $this->assertTrue(Validation::comparison(6, 'is less', 7)); $this->assertTrue(Validation::comparison(6, '<', 7)); $this->assertTrue(Validation::comparison(7, 'greater or equal', 7)); $this->assertTrue(Validation::comparison(7, '>=', 7)); $this->assertTrue(Validation::comparison(7, 'greater or equal', 6)); $this->assertTrue(Validation::comparison(7, '>=', 6)); $this->assertTrue(Validation::comparison(6, 'less or equal', 7)); $this->assertTrue(Validation::comparison(6, '<=', 7)); $this->assertTrue(Validation::comparison(7, 'equal to', 7)); $this->assertTrue(Validation::comparison(7, '==', 7)); $this->assertTrue(Validation::comparison(7, 'not equal', 6)); $this->assertTrue(Validation::comparison(7, '!=', 6)); $this->assertFalse(Validation::comparison(6, 'is greater', 7)); $this->assertFalse(Validation::comparison(6, '>', 7)); $this->assertFalse(Validation::comparison(7, 'is less', 6)); $this->assertFalse(Validation::comparison(7, '<', 6)); $this->assertFalse(Validation::comparison(6, 'greater or equal', 7)); $this->assertFalse(Validation::comparison(6, '>=', 7)); $this->assertFalse(Validation::comparison(6, 'greater or equal', 7)); $this->assertFalse(Validation::comparison(6, '>=', 7)); $this->assertFalse(Validation::comparison(7, 'less or equal', 6)); $this->assertFalse(Validation::comparison(7, '<=', 6)); $this->assertFalse(Validation::comparison(7, 'equal to', 6)); $this->assertFalse(Validation::comparison(7, '==', 6)); $this->assertFalse(Validation::comparison(7, 'not equal', 7)); $this->assertFalse(Validation::comparison(7, '!=', 7)); $this->assertTrue(Validation::comparison('6.5', '!=', 6)); $this->assertTrue(Validation::comparison('6.5', '<', 7)); } /** * Test comparison casting values before comparisons. * * @return void */ public function testComparisonTypeChecks() { $this->assertFalse(Validation::comparison('\x028', '>=', 1), 'hexish encoding fails'); $this->assertFalse(Validation::comparison('0b010', '>=', 1), 'binary string data fails'); $this->assertFalse(Validation::comparison('0x01', '>=', 1), 'hex string data fails'); $this->assertFalse(Validation::comparison('0x1', '>=', 1), 'hex string data fails'); $this->assertFalse(Validation::comparison('\x028', '>=', 1.5), 'hexish encoding fails'); $this->assertFalse(Validation::comparison('0b010', '>=', 1.5), 'binary string data fails'); $this->assertFalse(Validation::comparison('0x02', '>=', 1.5), 'hex string data fails'); } /** * testCustom method * * @return void */ public function testCustom() { $this->assertTrue(Validation::custom('12345', '/(?assertFalse(Validation::custom('Text', '/(?assertFalse(Validation::custom('123.45', '/(?assertFalse(Validation::custom('missing regex')); } /** * testDateDdmmyyyy method * * @return void */ public function testDateDdmmyyyy() { $this->assertTrue(Validation::date('27-12-2006', array('dmy'))); $this->assertTrue(Validation::date('27.12.2006', array('dmy'))); $this->assertTrue(Validation::date('27/12/2006', array('dmy'))); $this->assertTrue(Validation::date('27 12 2006', array('dmy'))); $this->assertFalse(Validation::date('00-00-0000', array('dmy'))); $this->assertFalse(Validation::date('00.00.0000', array('dmy'))); $this->assertFalse(Validation::date('00/00/0000', array('dmy'))); $this->assertFalse(Validation::date('00 00 0000', array('dmy'))); $this->assertFalse(Validation::date('31-11-2006', array('dmy'))); $this->assertFalse(Validation::date('31.11.2006', array('dmy'))); $this->assertFalse(Validation::date('31/11/2006', array('dmy'))); $this->assertFalse(Validation::date('31 11 2006', array('dmy'))); } /** * testDateDdmmyyyyLeapYear method * * @return void */ public function testDateDdmmyyyyLeapYear() { $this->assertTrue(Validation::date('29-02-2004', array('dmy'))); $this->assertTrue(Validation::date('29.02.2004', array('dmy'))); $this->assertTrue(Validation::date('29/02/2004', array('dmy'))); $this->assertTrue(Validation::date('29 02 2004', array('dmy'))); $this->assertFalse(Validation::date('29-02-2006', array('dmy'))); $this->assertFalse(Validation::date('29.02.2006', array('dmy'))); $this->assertFalse(Validation::date('29/02/2006', array('dmy'))); $this->assertFalse(Validation::date('29 02 2006', array('dmy'))); } /** * testDateDdmmyy method * * @return void */ public function testDateDdmmyy() { $this->assertTrue(Validation::date('27-12-06', array('dmy'))); $this->assertTrue(Validation::date('27.12.06', array('dmy'))); $this->assertTrue(Validation::date('27/12/06', array('dmy'))); $this->assertTrue(Validation::date('27 12 06', array('dmy'))); $this->assertFalse(Validation::date('00-00-00', array('dmy'))); $this->assertFalse(Validation::date('00.00.00', array('dmy'))); $this->assertFalse(Validation::date('00/00/00', array('dmy'))); $this->assertFalse(Validation::date('00 00 00', array('dmy'))); $this->assertFalse(Validation::date('31-11-06', array('dmy'))); $this->assertFalse(Validation::date('31.11.06', array('dmy'))); $this->assertFalse(Validation::date('31/11/06', array('dmy'))); $this->assertFalse(Validation::date('31 11 06', array('dmy'))); } /** * testDateDdmmyyLeapYear method * * @return void */ public function testDateDdmmyyLeapYear() { $this->assertTrue(Validation::date('29-02-04', array('dmy'))); $this->assertTrue(Validation::date('29.02.04', array('dmy'))); $this->assertTrue(Validation::date('29/02/04', array('dmy'))); $this->assertTrue(Validation::date('29 02 04', array('dmy'))); $this->assertFalse(Validation::date('29-02-06', array('dmy'))); $this->assertFalse(Validation::date('29.02.06', array('dmy'))); $this->assertFalse(Validation::date('29/02/06', array('dmy'))); $this->assertFalse(Validation::date('29 02 06', array('dmy'))); } /** * testDateDmyy method * * @return void */ public function testDateDmyy() { $this->assertTrue(Validation::date('7-2-06', array('dmy'))); $this->assertTrue(Validation::date('7.2.06', array('dmy'))); $this->assertTrue(Validation::date('7/2/06', array('dmy'))); $this->assertTrue(Validation::date('7 2 06', array('dmy'))); $this->assertFalse(Validation::date('0-0-00', array('dmy'))); $this->assertFalse(Validation::date('0.0.00', array('dmy'))); $this->assertFalse(Validation::date('0/0/00', array('dmy'))); $this->assertFalse(Validation::date('0 0 00', array('dmy'))); $this->assertFalse(Validation::date('32-2-06', array('dmy'))); $this->assertFalse(Validation::date('32.2.06', array('dmy'))); $this->assertFalse(Validation::date('32/2/06', array('dmy'))); $this->assertFalse(Validation::date('32 2 06', array('dmy'))); } /** * testDateDmyyLeapYear method * * @return void */ public function testDateDmyyLeapYear() { $this->assertTrue(Validation::date('29-2-04', array('dmy'))); $this->assertTrue(Validation::date('29.2.04', array('dmy'))); $this->assertTrue(Validation::date('29/2/04', array('dmy'))); $this->assertTrue(Validation::date('29 2 04', array('dmy'))); $this->assertFalse(Validation::date('29-2-06', array('dmy'))); $this->assertFalse(Validation::date('29.2.06', array('dmy'))); $this->assertFalse(Validation::date('29/2/06', array('dmy'))); $this->assertFalse(Validation::date('29 2 06', array('dmy'))); } /** * testDateDmyyyy method * * @return void */ public function testDateDmyyyy() { $this->assertTrue(Validation::date('7-2-2006', array('dmy'))); $this->assertTrue(Validation::date('7.2.2006', array('dmy'))); $this->assertTrue(Validation::date('7/2/2006', array('dmy'))); $this->assertTrue(Validation::date('7 2 2006', array('dmy'))); $this->assertFalse(Validation::date('0-0-0000', array('dmy'))); $this->assertFalse(Validation::date('0.0.0000', array('dmy'))); $this->assertFalse(Validation::date('0/0/0000', array('dmy'))); $this->assertFalse(Validation::date('0 0 0000', array('dmy'))); $this->assertFalse(Validation::date('32-2-2006', array('dmy'))); $this->assertFalse(Validation::date('32.2.2006', array('dmy'))); $this->assertFalse(Validation::date('32/2/2006', array('dmy'))); $this->assertFalse(Validation::date('32 2 2006', array('dmy'))); } /** * testDateDmyyyyLeapYear method * * @return void */ public function testDateDmyyyyLeapYear() { $this->assertTrue(Validation::date('29-2-2004', array('dmy'))); $this->assertTrue(Validation::date('29.2.2004', array('dmy'))); $this->assertTrue(Validation::date('29/2/2004', array('dmy'))); $this->assertTrue(Validation::date('29 2 2004', array('dmy'))); $this->assertFalse(Validation::date('29-2-2006', array('dmy'))); $this->assertFalse(Validation::date('29.2.2006', array('dmy'))); $this->assertFalse(Validation::date('29/2/2006', array('dmy'))); $this->assertFalse(Validation::date('29 2 2006', array('dmy'))); } /** * testDateMmddyyyy method * * @return void */ public function testDateMmddyyyy() { $this->assertTrue(Validation::date('12-27-2006', array('mdy'))); $this->assertTrue(Validation::date('12.27.2006', array('mdy'))); $this->assertTrue(Validation::date('12/27/2006', array('mdy'))); $this->assertTrue(Validation::date('12 27 2006', array('mdy'))); $this->assertFalse(Validation::date('00-00-0000', array('mdy'))); $this->assertFalse(Validation::date('00.00.0000', array('mdy'))); $this->assertFalse(Validation::date('00/00/0000', array('mdy'))); $this->assertFalse(Validation::date('00 00 0000', array('mdy'))); $this->assertFalse(Validation::date('11-31-2006', array('mdy'))); $this->assertFalse(Validation::date('11.31.2006', array('mdy'))); $this->assertFalse(Validation::date('11/31/2006', array('mdy'))); $this->assertFalse(Validation::date('11 31 2006', array('mdy'))); } /** * testDateMmddyyyyLeapYear method * * @return void */ public function testDateMmddyyyyLeapYear() { $this->assertTrue(Validation::date('02-29-2004', array('mdy'))); $this->assertTrue(Validation::date('02.29.2004', array('mdy'))); $this->assertTrue(Validation::date('02/29/2004', array('mdy'))); $this->assertTrue(Validation::date('02 29 2004', array('mdy'))); $this->assertFalse(Validation::date('02-29-2006', array('mdy'))); $this->assertFalse(Validation::date('02.29.2006', array('mdy'))); $this->assertFalse(Validation::date('02/29/2006', array('mdy'))); $this->assertFalse(Validation::date('02 29 2006', array('mdy'))); } /** * testDateMmddyy method * * @return void */ public function testDateMmddyy() { $this->assertTrue(Validation::date('12-27-06', array('mdy'))); $this->assertTrue(Validation::date('12.27.06', array('mdy'))); $this->assertTrue(Validation::date('12/27/06', array('mdy'))); $this->assertTrue(Validation::date('12 27 06', array('mdy'))); $this->assertFalse(Validation::date('00-00-00', array('mdy'))); $this->assertFalse(Validation::date('00.00.00', array('mdy'))); $this->assertFalse(Validation::date('00/00/00', array('mdy'))); $this->assertFalse(Validation::date('00 00 00', array('mdy'))); $this->assertFalse(Validation::date('11-31-06', array('mdy'))); $this->assertFalse(Validation::date('11.31.06', array('mdy'))); $this->assertFalse(Validation::date('11/31/06', array('mdy'))); $this->assertFalse(Validation::date('11 31 06', array('mdy'))); } /** * testDateMmddyyLeapYear method * * @return void */ public function testDateMmddyyLeapYear() { $this->assertTrue(Validation::date('02-29-04', array('mdy'))); $this->assertTrue(Validation::date('02.29.04', array('mdy'))); $this->assertTrue(Validation::date('02/29/04', array('mdy'))); $this->assertTrue(Validation::date('02 29 04', array('mdy'))); $this->assertFalse(Validation::date('02-29-06', array('mdy'))); $this->assertFalse(Validation::date('02.29.06', array('mdy'))); $this->assertFalse(Validation::date('02/29/06', array('mdy'))); $this->assertFalse(Validation::date('02 29 06', array('mdy'))); } /** * testDateMdyy method * * @return void */ public function testDateMdyy() { $this->assertTrue(Validation::date('2-7-06', array('mdy'))); $this->assertTrue(Validation::date('2.7.06', array('mdy'))); $this->assertTrue(Validation::date('2/7/06', array('mdy'))); $this->assertTrue(Validation::date('2 7 06', array('mdy'))); $this->assertFalse(Validation::date('0-0-00', array('mdy'))); $this->assertFalse(Validation::date('0.0.00', array('mdy'))); $this->assertFalse(Validation::date('0/0/00', array('mdy'))); $this->assertFalse(Validation::date('0 0 00', array('mdy'))); $this->assertFalse(Validation::date('2-32-06', array('mdy'))); $this->assertFalse(Validation::date('2.32.06', array('mdy'))); $this->assertFalse(Validation::date('2/32/06', array('mdy'))); $this->assertFalse(Validation::date('2 32 06', array('mdy'))); } /** * testDateMdyyLeapYear method * * @return void */ public function testDateMdyyLeapYear() { $this->assertTrue(Validation::date('2-29-04', array('mdy'))); $this->assertTrue(Validation::date('2.29.04', array('mdy'))); $this->assertTrue(Validation::date('2/29/04', array('mdy'))); $this->assertTrue(Validation::date('2 29 04', array('mdy'))); $this->assertFalse(Validation::date('2-29-06', array('mdy'))); $this->assertFalse(Validation::date('2.29.06', array('mdy'))); $this->assertFalse(Validation::date('2/29/06', array('mdy'))); $this->assertFalse(Validation::date('2 29 06', array('mdy'))); } /** * testDateMdyyyy method * * @return void */ public function testDateMdyyyy() { $this->assertTrue(Validation::date('2-7-2006', array('mdy'))); $this->assertTrue(Validation::date('2.7.2006', array('mdy'))); $this->assertTrue(Validation::date('2/7/2006', array('mdy'))); $this->assertTrue(Validation::date('2 7 2006', array('mdy'))); $this->assertFalse(Validation::date('0-0-0000', array('mdy'))); $this->assertFalse(Validation::date('0.0.0000', array('mdy'))); $this->assertFalse(Validation::date('0/0/0000', array('mdy'))); $this->assertFalse(Validation::date('0 0 0000', array('mdy'))); $this->assertFalse(Validation::date('2-32-2006', array('mdy'))); $this->assertFalse(Validation::date('2.32.2006', array('mdy'))); $this->assertFalse(Validation::date('2/32/2006', array('mdy'))); $this->assertFalse(Validation::date('2 32 2006', array('mdy'))); } /** * testDateMdyyyyLeapYear method * * @return void */ public function testDateMdyyyyLeapYear() { $this->assertTrue(Validation::date('2-29-2004', array('mdy'))); $this->assertTrue(Validation::date('2.29.2004', array('mdy'))); $this->assertTrue(Validation::date('2/29/2004', array('mdy'))); $this->assertTrue(Validation::date('2 29 2004', array('mdy'))); $this->assertFalse(Validation::date('2-29-2006', array('mdy'))); $this->assertFalse(Validation::date('2.29.2006', array('mdy'))); $this->assertFalse(Validation::date('2/29/2006', array('mdy'))); $this->assertFalse(Validation::date('2 29 2006', array('mdy'))); } /** * testDateYyyymmdd method * * @return void */ public function testDateYyyymmdd() { $this->assertTrue(Validation::date('2006-12-27', array('ymd'))); $this->assertTrue(Validation::date('2006.12.27', array('ymd'))); $this->assertTrue(Validation::date('2006/12/27', array('ymd'))); $this->assertTrue(Validation::date('2006 12 27', array('ymd'))); $this->assertFalse(Validation::date('2006-11-31', array('ymd'))); $this->assertFalse(Validation::date('2006.11.31', array('ymd'))); $this->assertFalse(Validation::date('2006/11/31', array('ymd'))); $this->assertFalse(Validation::date('2006 11 31', array('ymd'))); } /** * testDateYyyymmddLeapYear method * * @return void */ public function testDateYyyymmddLeapYear() { $this->assertTrue(Validation::date('2004-02-29', array('ymd'))); $this->assertTrue(Validation::date('2004.02.29', array('ymd'))); $this->assertTrue(Validation::date('2004/02/29', array('ymd'))); $this->assertTrue(Validation::date('2004 02 29', array('ymd'))); $this->assertFalse(Validation::date('2006-02-29', array('ymd'))); $this->assertFalse(Validation::date('2006.02.29', array('ymd'))); $this->assertFalse(Validation::date('2006/02/29', array('ymd'))); $this->assertFalse(Validation::date('2006 02 29', array('ymd'))); } /** * testDateYymmdd method * * @return void */ public function testDateYymmdd() { $this->assertTrue(Validation::date('06-12-27', array('ymd'))); $this->assertTrue(Validation::date('06.12.27', array('ymd'))); $this->assertTrue(Validation::date('06/12/27', array('ymd'))); $this->assertTrue(Validation::date('06 12 27', array('ymd'))); $this->assertFalse(Validation::date('12/27/2600', array('ymd'))); $this->assertFalse(Validation::date('12.27.2600', array('ymd'))); $this->assertFalse(Validation::date('12/27/2600', array('ymd'))); $this->assertFalse(Validation::date('12 27 2600', array('ymd'))); $this->assertFalse(Validation::date('06-11-31', array('ymd'))); $this->assertFalse(Validation::date('06.11.31', array('ymd'))); $this->assertFalse(Validation::date('06/11/31', array('ymd'))); $this->assertFalse(Validation::date('06 11 31', array('ymd'))); } /** * testDateYymmddLeapYear method * * @return void */ public function testDateYymmddLeapYear() { $this->assertTrue(Validation::date('2004-02-29', array('ymd'))); $this->assertTrue(Validation::date('2004.02.29', array('ymd'))); $this->assertTrue(Validation::date('2004/02/29', array('ymd'))); $this->assertTrue(Validation::date('2004 02 29', array('ymd'))); $this->assertFalse(Validation::date('2006-02-29', array('ymd'))); $this->assertFalse(Validation::date('2006.02.29', array('ymd'))); $this->assertFalse(Validation::date('2006/02/29', array('ymd'))); $this->assertFalse(Validation::date('2006 02 29', array('ymd'))); } /** * testDateDdMMMMyyyy method * * @return void */ public function testDateDdMMMMyyyy() { $this->assertTrue(Validation::date('27 December 2006', array('dMy'))); $this->assertTrue(Validation::date('27 Dec 2006', array('dMy'))); $this->assertFalse(Validation::date('2006 Dec 27', array('dMy'))); $this->assertFalse(Validation::date('2006 December 27', array('dMy'))); } /** * testDateDdMMMMyyyyLeapYear method * * @return void */ public function testDateDdMMMMyyyyLeapYear() { $this->assertTrue(Validation::date('29 February 2004', array('dMy'))); $this->assertFalse(Validation::date('29 February 2006', array('dMy'))); } /** * testDateMmmmDdyyyy method * * @return void */ public function testDateMmmmDdyyyy() { $this->assertTrue(Validation::date('December 27, 2006', array('Mdy'))); $this->assertTrue(Validation::date('Dec 27, 2006', array('Mdy'))); $this->assertTrue(Validation::date('December 27 2006', array('Mdy'))); $this->assertTrue(Validation::date('Dec 27 2006', array('Mdy'))); $this->assertFalse(Validation::date('27 Dec 2006', array('Mdy'))); $this->assertFalse(Validation::date('2006 December 27', array('Mdy'))); $this->assertTrue(Validation::date('Sep 12, 2011', array('Mdy'))); } /** * testDateMmmmDdyyyyLeapYear method * * @return void */ public function testDateMmmmDdyyyyLeapYear() { $this->assertTrue(Validation::date('February 29, 2004', array('Mdy'))); $this->assertTrue(Validation::date('Feb 29, 2004', array('Mdy'))); $this->assertTrue(Validation::date('February 29 2004', array('Mdy'))); $this->assertTrue(Validation::date('Feb 29 2004', array('Mdy'))); $this->assertFalse(Validation::date('February 29, 2006', array('Mdy'))); } /** * testDateMy method * * @return void */ public function testDateMy() { $this->assertTrue(Validation::date('December 2006', array('My'))); $this->assertTrue(Validation::date('Dec 2006', array('My'))); $this->assertTrue(Validation::date('December/2006', array('My'))); $this->assertTrue(Validation::date('Dec/2006', array('My'))); } /** * testDateMyNumeric method * * @return void */ public function testDateMyNumeric() { $this->assertTrue(Validation::date('01/2006', array('my'))); $this->assertTrue(Validation::date('12-2006', array('my'))); $this->assertTrue(Validation::date('12.2006', array('my'))); $this->assertTrue(Validation::date('12 2006', array('my'))); $this->assertTrue(Validation::date('01/06', array('my'))); $this->assertTrue(Validation::date('12-06', array('my'))); $this->assertTrue(Validation::date('12.06', array('my'))); $this->assertTrue(Validation::date('12 06', array('my'))); $this->assertFalse(Validation::date('13 06', array('my'))); $this->assertFalse(Validation::date('13 2006', array('my'))); } /** * testDateYmNumeric method * * @return void */ public function testDateYmNumeric() { $this->assertTrue(Validation::date('2006/12', array('ym'))); $this->assertTrue(Validation::date('2006-12', array('ym'))); $this->assertTrue(Validation::date('2006-12', array('ym'))); $this->assertTrue(Validation::date('2006 12', array('ym'))); $this->assertTrue(Validation::date('2006 12', array('ym'))); $this->assertTrue(Validation::date('1900-01', array('ym'))); $this->assertTrue(Validation::date('2153-01', array('ym'))); $this->assertTrue(Validation::date('06/12', array('ym'))); $this->assertTrue(Validation::date('06-12', array('ym'))); $this->assertTrue(Validation::date('06-12', array('ym'))); $this->assertTrue(Validation::date('06 12', array('ym'))); $this->assertFalse(Validation::date('2006/12 ', array('ym'))); $this->assertFalse(Validation::date('2006/12/', array('ym'))); $this->assertFalse(Validation::date('06/12 ', array('ym'))); $this->assertFalse(Validation::date('06/13 ', array('ym'))); } /** * testDateY method * * @return void */ public function testDateY() { $this->assertTrue(Validation::date('1900', array('y'))); $this->assertTrue(Validation::date('1984', array('y'))); $this->assertTrue(Validation::date('2006', array('y'))); $this->assertTrue(Validation::date('2008', array('y'))); $this->assertTrue(Validation::date('2013', array('y'))); $this->assertTrue(Validation::date('2104', array('y'))); $this->assertTrue(Validation::date('1899', array('y'))); $this->assertFalse(Validation::date('20009', array('y'))); $this->assertFalse(Validation::date(' 2012', array('y'))); $this->assertFalse(Validation::date('3000', array('y'))); $this->assertFalse(Validation::date('1799', array('y'))); } /** * Test validating dates with multiple formats * * @return void */ public function testDateMultiple() { $this->assertTrue(Validation::date('2011-12-31', array('ymd', 'dmy'))); $this->assertTrue(Validation::date('31-12-2011', array('ymd', 'dmy'))); } /** * testTime method * * @return void */ public function testTime() { $this->assertTrue(Validation::time('00:00')); $this->assertTrue(Validation::time('23:59')); $this->assertFalse(Validation::time('24:00')); $this->assertTrue(Validation::time('12:00')); $this->assertTrue(Validation::time('12:01')); $this->assertTrue(Validation::time('12:01am')); $this->assertTrue(Validation::time('12:01pm')); $this->assertTrue(Validation::time('1pm')); $this->assertTrue(Validation::time('1 pm')); $this->assertTrue(Validation::time('1 PM')); $this->assertTrue(Validation::time('01:00')); $this->assertFalse(Validation::time('1:00')); $this->assertTrue(Validation::time('1:00pm')); $this->assertFalse(Validation::time('13:00pm')); $this->assertFalse(Validation::time('9:00')); } /** * testBoolean method * * @return void */ public function testBoolean() { $this->assertTrue(Validation::boolean('0')); $this->assertTrue(Validation::boolean('1')); $this->assertTrue(Validation::boolean(0)); $this->assertTrue(Validation::boolean(1)); $this->assertTrue(Validation::boolean(true)); $this->assertTrue(Validation::boolean(false)); $this->assertFalse(Validation::boolean('true')); $this->assertFalse(Validation::boolean('false')); $this->assertFalse(Validation::boolean('-1')); $this->assertFalse(Validation::boolean('2')); $this->assertFalse(Validation::boolean('Boo!')); } /** * testDateCustomRegx method * * @return void */ public function testDateCustomRegx() { $this->assertTrue(Validation::date('2006-12-27', null, '%^(19|20)[0-9]{2}[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$%')); $this->assertFalse(Validation::date('12-27-2006', null, '%^(19|20)[0-9]{2}[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$%')); } /** * Test numbers with any number of decimal places, including none. * * @return void */ public function testDecimalWithPlacesNull() { $this->assertTrue(Validation::decimal('+1234.54321', null)); $this->assertTrue(Validation::decimal('-1234.54321', null)); $this->assertTrue(Validation::decimal('1234.54321', null)); $this->assertTrue(Validation::decimal('+0123.45e6', null)); $this->assertTrue(Validation::decimal('-0123.45e6', null)); $this->assertTrue(Validation::decimal('0123.45e6', null)); $this->assertTrue(Validation::decimal(1234.56, null)); $this->assertTrue(Validation::decimal(1234.00, null)); $this->assertTrue(Validation::decimal(1234., null)); $this->assertTrue(Validation::decimal('1234.00', null)); $this->assertTrue(Validation::decimal(.0, null)); $this->assertTrue(Validation::decimal(.00, null)); $this->assertTrue(Validation::decimal('.00', null)); $this->assertTrue(Validation::decimal(.01, null)); $this->assertTrue(Validation::decimal('.01', null)); $this->assertTrue(Validation::decimal('1234', null)); $this->assertTrue(Validation::decimal('-1234', null)); $this->assertTrue(Validation::decimal('+1234', null)); $this->assertTrue(Validation::decimal((float)1234, null)); $this->assertTrue(Validation::decimal((double)1234, null)); $this->assertTrue(Validation::decimal((int)1234, null)); $this->assertFalse(Validation::decimal('', null)); $this->assertFalse(Validation::decimal('string', null)); $this->assertFalse(Validation::decimal('1234.', null)); } /** * Test numbers with any number of decimal places greater than 0, or a float|double. * * @return void */ public function testDecimalWithPlacesTrue() { $this->assertTrue(Validation::decimal('+1234.54321', true)); $this->assertTrue(Validation::decimal('-1234.54321', true)); $this->assertTrue(Validation::decimal('1234.54321', true)); $this->assertTrue(Validation::decimal('+0123.45e6', true)); $this->assertTrue(Validation::decimal('-0123.45e6', true)); $this->assertTrue(Validation::decimal('0123.45e6', true)); $this->assertTrue(Validation::decimal(1234.56, true)); $this->assertTrue(Validation::decimal(1234.00, true)); $this->assertTrue(Validation::decimal(1234., true)); $this->assertTrue(Validation::decimal('1234.00', true)); $this->assertTrue(Validation::decimal(.0, true)); $this->assertTrue(Validation::decimal(.00, true)); $this->assertTrue(Validation::decimal('.00', true)); $this->assertTrue(Validation::decimal(.01, true)); $this->assertTrue(Validation::decimal('.01', true)); $this->assertTrue(Validation::decimal((float)1234, true)); $this->assertTrue(Validation::decimal((double)1234, true)); $this->assertFalse(Validation::decimal('', true)); $this->assertFalse(Validation::decimal('string', true)); $this->assertFalse(Validation::decimal('1234.', true)); $this->assertFalse(Validation::decimal((int)1234, true)); $this->assertFalse(Validation::decimal('1234', true)); $this->assertFalse(Validation::decimal('-1234', true)); $this->assertFalse(Validation::decimal('+1234', true)); } /** * Test numbers with exactly that many number of decimal places. * * @return void */ public function testDecimalWithPlacesNumeric() { $this->assertTrue(Validation::decimal('.27', '2')); $this->assertTrue(Validation::decimal(0.27, 2)); $this->assertTrue(Validation::decimal(-0.27, 2)); $this->assertTrue(Validation::decimal(0.27, 2)); $this->assertTrue(Validation::decimal('0.277', '3')); $this->assertTrue(Validation::decimal(0.277, 3)); $this->assertTrue(Validation::decimal(-0.277, 3)); $this->assertTrue(Validation::decimal(0.277, 3)); $this->assertTrue(Validation::decimal('1234.5678', '4')); $this->assertTrue(Validation::decimal(1234.5678, 4)); $this->assertTrue(Validation::decimal(-1234.5678, 4)); $this->assertTrue(Validation::decimal(1234.5678, 4)); $this->assertTrue(Validation::decimal('.00', 2)); $this->assertTrue(Validation::decimal(.01, 2)); $this->assertTrue(Validation::decimal('.01', 2)); $this->assertFalse(Validation::decimal('', 1)); $this->assertFalse(Validation::decimal('string', 1)); $this->assertFalse(Validation::decimal(1234., 1)); $this->assertFalse(Validation::decimal('1234.', 1)); $this->assertFalse(Validation::decimal(.0, 1)); $this->assertFalse(Validation::decimal(.00, 2)); $this->assertFalse(Validation::decimal((float)1234, 1)); $this->assertFalse(Validation::decimal((double)1234, 1)); $this->assertFalse(Validation::decimal((int)1234, 1)); $this->assertFalse(Validation::decimal('1234.5678', '3')); $this->assertFalse(Validation::decimal(1234.5678, 3)); $this->assertFalse(Validation::decimal(-1234.5678, 3)); $this->assertFalse(Validation::decimal(1234.5678, 3)); } /** * Test decimal() with invalid places parameter. * * @return void */ public function testDecimalWithInvalidPlaces() { $this->assertFalse(Validation::decimal('.27', 'string')); $this->assertFalse(Validation::decimal(1234.5678, (array)true)); $this->assertFalse(Validation::decimal(-1234.5678, (object)true)); } /** * testDecimalCustomRegex method * * @return void */ public function testDecimalCustomRegex() { $this->assertTrue(Validation::decimal('1.54321', null, '/^[-+]?[0-9]+(\\.[0-9]+)?$/s')); $this->assertFalse(Validation::decimal('.54321', null, '/^[-+]?[0-9]+(\\.[0-9]+)?$/s')); } /** * Test localized floats with decimal. * * @return void */ public function testDecimalLocaleSet() { $this->skipIf(DS === '\\', 'The locale is not supported in Windows and affects other tests.'); $restore = setlocale(LC_NUMERIC, 0); $this->skipIf(setlocale(LC_NUMERIC, 'da_DK') === false, "The Danish locale isn't available."); $this->assertTrue(Validation::decimal(1.54), '1.54 should be considered a valid float'); $this->assertTrue(Validation::decimal('1.54'), '"1.54" should be considered a valid float'); $this->assertTrue(Validation::decimal(12345.67), '12345.67 should be considered a valid float'); $this->assertTrue(Validation::decimal('12,345.67'), '"12,345.67" should be considered a valid float'); setlocale(LC_NUMERIC, $restore); } /** * testEmail method * * @return void */ public function testEmail() { $this->assertTrue(Validation::email('abc.efg@domain.com')); $this->assertTrue(Validation::email('efg@domain.com')); $this->assertTrue(Validation::email('abc-efg@domain.com')); $this->assertTrue(Validation::email('abc_efg@domain.com')); $this->assertTrue(Validation::email('raw@test.ra.ru')); $this->assertTrue(Validation::email('abc-efg@domain-hyphened.com')); $this->assertTrue(Validation::email("p.o'malley@domain.com")); $this->assertTrue(Validation::email('abc+efg@domain.com')); $this->assertTrue(Validation::email('abc&efg@domain.com')); $this->assertTrue(Validation::email('abc.efg@12345.com')); $this->assertTrue(Validation::email('abc.efg@12345.co.jp')); $this->assertTrue(Validation::email('abc@g.cn')); $this->assertTrue(Validation::email('abc@x.com')); $this->assertTrue(Validation::email('henrik@sbcglobal.net')); $this->assertTrue(Validation::email('sani@sbcglobal.net')); // all ICANN TLDs $this->assertTrue(Validation::email('abc@example.aero')); $this->assertTrue(Validation::email('abc@example.asia')); $this->assertTrue(Validation::email('abc@example.biz')); $this->assertTrue(Validation::email('abc@example.cat')); $this->assertTrue(Validation::email('abc@example.com')); $this->assertTrue(Validation::email('abc@example.coop')); $this->assertTrue(Validation::email('abc@example.edu')); $this->assertTrue(Validation::email('abc@example.gov')); $this->assertTrue(Validation::email('abc@example.info')); $this->assertTrue(Validation::email('abc@example.int')); $this->assertTrue(Validation::email('abc@example.jobs')); $this->assertTrue(Validation::email('abc@example.mil')); $this->assertTrue(Validation::email('abc@example.mobi')); $this->assertTrue(Validation::email('abc@example.museum')); $this->assertTrue(Validation::email('abc@example.name')); $this->assertTrue(Validation::email('abc@example.net')); $this->assertTrue(Validation::email('abc@example.org')); $this->assertTrue(Validation::email('abc@example.pro')); $this->assertTrue(Validation::email('abc@example.tel')); $this->assertTrue(Validation::email('abc@example.travel')); $this->assertTrue(Validation::email('someone@st.t-com.hr')); // gTLD's $this->assertTrue(Validation::email('example@host.local')); $this->assertTrue(Validation::email('example@x.org')); $this->assertTrue(Validation::email('example@host.xxx')); // strange, but technically valid email addresses $this->assertTrue(Validation::email('S=postmaster/OU=rz/P=uni-frankfurt/A=d400/C=de@gateway.d400.de')); $this->assertTrue(Validation::email('customer/department=shipping@example.com')); $this->assertTrue(Validation::email('$A12345@example.com')); $this->assertTrue(Validation::email('!def!xyz%abc@example.com')); $this->assertTrue(Validation::email('_somename@example.com')); /// Unicode $this->assertTrue(Validation::email('some@erรคume.foo')); $this->assertTrue(Validation::email('รคu@รถe.erรคume.foo')); $this->assertTrue(Validation::email('Nyrรฉe.surname@example.com')); // invalid addresses $this->assertFalse(Validation::email('abc@example')); $this->assertFalse(Validation::email('abc@example.c')); $this->assertFalse(Validation::email('abc@example.com.')); $this->assertFalse(Validation::email('abc.@example.com')); $this->assertFalse(Validation::email('abc@example..com')); $this->assertFalse(Validation::email('abc@example.com.a')); $this->assertFalse(Validation::email('abc;@example.com')); $this->assertFalse(Validation::email('abc@example.com;')); $this->assertFalse(Validation::email('abc@efg@example.com')); $this->assertFalse(Validation::email('abc@@example.com')); $this->assertFalse(Validation::email('abc efg@example.com')); $this->assertFalse(Validation::email('abc,efg@example.com')); $this->assertFalse(Validation::email('abc@sub,example.com')); $this->assertFalse(Validation::email("abc@sub'example.com")); $this->assertFalse(Validation::email('abc@sub/example.com')); $this->assertFalse(Validation::email('abc@yahoo!.com')); $this->assertFalse(Validation::email('abc@example_underscored.com')); $this->assertFalse(Validation::email('raw@test.ra.ru....com')); } /** * testEmailDeep method * * @return void */ public function testEmailDeep() { $this->skipIf(gethostbynamel('example.abcd'), 'Your DNS service responds for non-existant domains, skipping deep email checks.'); $this->assertTrue(Validation::email('abc.efg@cakephp.org', true)); $this->assertFalse(Validation::email('abc.efg@caphpkeinvalid.com', true)); } /** * testEmailCustomRegex method * * @return void */ public function testEmailCustomRegex() { $this->assertTrue(Validation::email('abc.efg@cakephp.org', null, '/^[A-Z0-9._%-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$/i')); $this->assertFalse(Validation::email('abc.efg@com.caphpkeinvalid', null, '/^[A-Z0-9._%-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}$/i')); } /** * testEqualTo method * * @return void */ public function testEqualTo() { $this->assertTrue(Validation::equalTo("1", "1")); $this->assertFalse(Validation::equalTo(1, "1")); $this->assertFalse(Validation::equalTo("", null)); $this->assertFalse(Validation::equalTo("", false)); $this->assertFalse(Validation::equalTo(0, false)); $this->assertFalse(Validation::equalTo(null, false)); } /** * testIpV4 method * * @return void */ public function testIpV4() { $this->assertTrue(Validation::ip('0.0.0.0', 'ipv4')); $this->assertTrue(Validation::ip('192.168.1.156')); $this->assertTrue(Validation::ip('255.255.255.255')); $this->assertFalse(Validation::ip('127.0.0')); $this->assertFalse(Validation::ip('127.0.0.a')); $this->assertFalse(Validation::ip('127.0.0.256')); $this->assertFalse(Validation::ip('2001:0db8:85a3:0000:0000:8a2e:0370:7334', 'ipv4'), 'IPv6 is not valid IPv4'); } /** * testIp v6 * * @return void */ public function testIpv6() { $this->assertTrue(Validation::ip('2001:0db8:85a3:0000:0000:8a2e:0370:7334', 'IPv6')); $this->assertTrue(Validation::ip('2001:db8:85a3:0:0:8a2e:370:7334', 'IPv6')); $this->assertTrue(Validation::ip('2001:db8:85a3::8a2e:370:7334', 'IPv6')); $this->assertTrue(Validation::ip('2001:0db8:0000:0000:0000:0000:1428:57ab', 'IPv6')); $this->assertTrue(Validation::ip('2001:0db8:0000:0000:0000::1428:57ab', 'IPv6')); $this->assertTrue(Validation::ip('2001:0db8:0:0:0:0:1428:57ab', 'IPv6')); $this->assertTrue(Validation::ip('2001:0db8:0:0::1428:57ab', 'IPv6')); $this->assertTrue(Validation::ip('2001:0db8::1428:57ab', 'IPv6')); $this->assertTrue(Validation::ip('2001:db8::1428:57ab', 'IPv6')); $this->assertTrue(Validation::ip('0000:0000:0000:0000:0000:0000:0000:0001', 'IPv6')); $this->assertTrue(Validation::ip('::1', 'IPv6')); $this->assertTrue(Validation::ip('::ffff:12.34.56.78', 'IPv6')); $this->assertTrue(Validation::ip('::ffff:0c22:384e', 'IPv6')); $this->assertTrue(Validation::ip('2001:0db8:1234:0000:0000:0000:0000:0000', 'IPv6')); $this->assertTrue(Validation::ip('2001:0db8:1234:ffff:ffff:ffff:ffff:ffff', 'IPv6')); $this->assertTrue(Validation::ip('2001:db8:a::123', 'IPv6')); $this->assertTrue(Validation::ip('fe80::', 'IPv6')); $this->assertTrue(Validation::ip('::ffff:192.0.2.128', 'IPv6')); $this->assertTrue(Validation::ip('::ffff:c000:280', 'IPv6')); $this->assertFalse(Validation::ip('123', 'IPv6')); $this->assertFalse(Validation::ip('ldkfj', 'IPv6')); $this->assertFalse(Validation::ip('2001::FFD3::57ab', 'IPv6')); $this->assertFalse(Validation::ip('2001:db8:85a3::8a2e:37023:7334', 'IPv6')); $this->assertFalse(Validation::ip('2001:db8:85a3::8a2e:370k:7334', 'IPv6')); $this->assertFalse(Validation::ip('1:2:3:4:5:6:7:8:9', 'IPv6')); $this->assertFalse(Validation::ip('1::2::3', 'IPv6')); $this->assertFalse(Validation::ip('1:::3:4:5', 'IPv6')); $this->assertFalse(Validation::ip('1:2:3::4:5:6:7:8:9', 'IPv6')); $this->assertFalse(Validation::ip('::ffff:2.3.4', 'IPv6')); $this->assertFalse(Validation::ip('::ffff:257.1.2.3', 'IPv6')); $this->assertFalse(Validation::ip('255.255.255.255', 'ipv6'), 'IPv4 is not valid IPv6'); } /** * testMaxLength method * * @return void */ public function testMaxLength() { $this->assertTrue(Validation::maxLength('ab', 3)); $this->assertTrue(Validation::maxLength('abc', 3)); $this->assertTrue(Validation::maxLength('ร†ฮ”ฮฉะ–ร‡', 10)); $this->assertFalse(Validation::maxLength('abcd', 3)); $this->assertFalse(Validation::maxLength('ร†ฮ”ฮฉะ–ร‡', 3)); } /** * testMinLength method * * @return void */ public function testMinLength() { $this->assertFalse(Validation::minLength('ab', 3)); $this->assertFalse(Validation::minLength('ร†ฮ”ฮฉะ–ร‡', 10)); $this->assertTrue(Validation::minLength('abc', 3)); $this->assertTrue(Validation::minLength('abcd', 3)); $this->assertTrue(Validation::minLength('ร†ฮ”ฮฉะ–ร‡', 2)); } /** * testUrl method * * @return void */ public function testUrl() { $this->assertTrue(Validation::url('http://www.cakephp.org')); $this->assertTrue(Validation::url('http://cakephp.org')); $this->assertTrue(Validation::url('http://www.cakephp.org/somewhere#anchor')); $this->assertTrue(Validation::url('http://192.168.0.1')); $this->assertTrue(Validation::url('https://www.cakephp.org')); $this->assertTrue(Validation::url('https://cakephp.org')); $this->assertTrue(Validation::url('https://www.cakephp.org/somewhere#anchor')); $this->assertTrue(Validation::url('https://192.168.0.1')); $this->assertTrue(Validation::url('ftps://www.cakephp.org/pub/cake')); $this->assertTrue(Validation::url('ftps://cakephp.org/pub/cake')); $this->assertTrue(Validation::url('ftps://192.168.0.1/pub/cake')); $this->assertTrue(Validation::url('ftp://www.cakephp.org/pub/cake')); $this->assertTrue(Validation::url('ftp://cakephp.org/pub/cake')); $this->assertTrue(Validation::url('ftp://192.168.0.1/pub/cake')); $this->assertTrue(Validation::url('sftp://192.168.0.1/pub/cake')); $this->assertTrue(Validation::url('https://my.domain.com/gizmo/app?class=MySip;proc=start')); $this->assertTrue(Validation::url('www.domain.tld')); $this->assertTrue(Validation::url('http://123456789112345678921234567893123456789412345678951234567896123.com')); $this->assertTrue(Validation::url('http://www.domain.com/blogs/index.php?blog=6&tempskin=_rss2')); $this->assertTrue(Validation::url('http://www.domain.com/blogs/parenth()eses.php')); $this->assertTrue(Validation::url('http://www.domain.com/index.php?get=params&get2=params')); $this->assertTrue(Validation::url('http://www.domain.com/ndex.php?get=params&get2=params#anchor')); $this->assertTrue(Validation::url('http://www.domain.com/real%20url%20encodeing')); $this->assertTrue(Validation::url('http://en.wikipedia.org/wiki/Architectural_pattern_(computer_science)')); $this->assertTrue(Validation::url('http://www.cakephp.org', true)); $this->assertTrue(Validation::url('http://example.com/~userdir/')); $this->assertTrue(Validation::url('http://underscore_subdomain.example.org')); $this->assertTrue(Validation::url('http://_jabber._tcp.gmail.com')); $this->assertTrue(Validation::url('http://www.domain.longttldnotallowed')); $this->assertFalse(Validation::url('ftps://256.168.0.1/pub/cake')); $this->assertFalse(Validation::url('ftp://256.168.0.1/pub/cake')); $this->assertFalse(Validation::url('http://w_w.domain.co_m')); $this->assertFalse(Validation::url('http://www.domain.12com')); $this->assertFalse(Validation::url('http://www.-invaliddomain.tld')); $this->assertFalse(Validation::url('http://www.domain.-invalidtld')); $this->assertFalse(Validation::url('http://this-domain-is-too-loooooong-by-icann-rules-maximum-length-is-63.com')); $this->assertFalse(Validation::url('http://www.underscore_domain.org')); $this->assertFalse(Validation::url('http://_jabber._tcp.g_mail.com')); $this->assertFalse(Validation::url('http://en.(wikipedia).org/')); $this->assertFalse(Validation::url('http://www.domain.com/fakeenco%ode')); $this->assertFalse(Validation::url('--.example.com')); $this->assertFalse(Validation::url('www.cakephp.org', true)); $this->assertTrue(Validation::url('http://example.com/~userdir/subdir/index.html')); $this->assertTrue(Validation::url('http://www.zwischenraume.de')); $this->assertTrue(Validation::url('http://www.zwischenraume.cz')); $this->assertTrue(Validation::url('http://www.last.fm/music/ๆตœๅดŽใ‚ใ‚†ใฟ'), 'utf8 path failed'); $this->assertTrue(Validation::url('http://www.electrohome.ro/images/239537750-284232-215_300[1].jpg')); $this->assertTrue(Validation::url('http://www.erรคume.foo')); $this->assertTrue(Validation::url('http://รครผรถ.erรคume.foo')); $this->assertTrue(Validation::url('http://cakephp.org:80')); $this->assertTrue(Validation::url('http://cakephp.org:443')); $this->assertTrue(Validation::url('http://cakephp.org:2000')); $this->assertTrue(Validation::url('http://cakephp.org:27000')); $this->assertTrue(Validation::url('http://cakephp.org:65000')); $this->assertTrue(Validation::url('[2001:0db8::1428:57ab]')); $this->assertTrue(Validation::url('[::1]')); $this->assertTrue(Validation::url('[2001:0db8::1428:57ab]:80')); $this->assertTrue(Validation::url('[::1]:80')); $this->assertTrue(Validation::url('http://[2001:0db8::1428:57ab]')); $this->assertTrue(Validation::url('http://[::1]')); $this->assertTrue(Validation::url('http://[2001:0db8::1428:57ab]:80')); $this->assertTrue(Validation::url('http://[::1]:80')); $this->assertFalse(Validation::url('[1::2::3]')); } public function testUuid() { $this->assertTrue(Validation::uuid('00000000-0000-0000-0000-000000000000')); $this->assertTrue(Validation::uuid('550e8400-e29b-11d4-a716-446655440000')); $this->assertFalse(Validation::uuid('BRAP-e29b-11d4-a716-446655440000')); $this->assertTrue(Validation::uuid('550E8400-e29b-11D4-A716-446655440000')); $this->assertFalse(Validation::uuid('550e8400-e29b11d4-a716-446655440000')); $this->assertFalse(Validation::uuid('550e8400-e29b-11d4-a716-4466440000')); $this->assertFalse(Validation::uuid('550e8400-e29b-11d4-a71-446655440000')); $this->assertFalse(Validation::uuid('550e8400-e29b-11d-a716-446655440000')); $this->assertFalse(Validation::uuid('550e8400-e29-11d4-a716-446655440000')); } /** * testInList method * * @return void */ public function testInList() { $this->assertTrue(Validation::inList('one', array('one', 'two'))); $this->assertTrue(Validation::inList('two', array('one', 'two'))); $this->assertFalse(Validation::inList('three', array('one', 'two'))); $this->assertFalse(Validation::inList('1one', array(0, 1, 2, 3))); $this->assertFalse(Validation::inList('one', array(0, 1, 2, 3))); $this->assertTrue(Validation::inList('2', array(1, 2, 3))); $this->assertFalse(Validation::inList('2x', array(1, 2, 3))); $this->assertFalse(Validation::inList(2, array('1', '2x', '3'))); $this->assertFalse(Validation::inList('One', array('one', 'two'))); // No hexadecimal for numbers. $this->assertFalse(Validation::inList('0x7B', array('ABC', '123'))); $this->assertFalse(Validation::inList('0x7B', array('ABC', 123))); // case insensitive $this->assertTrue(Validation::inList('one', array('One', 'Two'), true)); $this->assertTrue(Validation::inList('Two', array('one', 'two'), true)); $this->assertFalse(Validation::inList('three', array('one', 'two'), true)); } /** * testRange method * * @return void */ public function testRange() { $this->assertFalse(Validation::range(20, 100, 1)); $this->assertTrue(Validation::range(20, 1, 100)); $this->assertFalse(Validation::range(.5, 1, 100)); $this->assertTrue(Validation::range(.5, 0, 100)); $this->assertTrue(Validation::range(5)); $this->assertTrue(Validation::range(-5, -10, 1)); $this->assertFalse(Validation::range('word')); } /** * Test range type checks * * @return void */ public function testRangeTypeChecks() { $this->assertFalse(Validation::range('\x028', 1, 5), 'hexish encoding fails'); $this->assertFalse(Validation::range('0b010', 1, 5), 'binary string data fails'); $this->assertFalse(Validation::range('0x01', 1, 5), 'hex string data fails'); $this->assertFalse(Validation::range('0x1', 1, 5), 'hex string data fails'); $this->assertFalse(Validation::range('\x028', 1, 5), 'hexish encoding fails'); $this->assertFalse(Validation::range('0b010', 1, 5), 'binary string data fails'); $this->assertFalse(Validation::range('0x02', 1, 5), 'hex string data fails'); } /** * testExtension method * * @return void */ public function testExtension() { $this->assertTrue(Validation::extension('extension.jpeg')); $this->assertTrue(Validation::extension('extension.JPEG')); $this->assertTrue(Validation::extension('extension.gif')); $this->assertTrue(Validation::extension('extension.GIF')); $this->assertTrue(Validation::extension('extension.png')); $this->assertTrue(Validation::extension('extension.jpg')); $this->assertTrue(Validation::extension('extension.JPG')); $this->assertFalse(Validation::extension('noextension')); $this->assertTrue(Validation::extension('extension.pdf', array('PDF'))); $this->assertFalse(Validation::extension('extension.jpg', array('GIF'))); $this->assertTrue(Validation::extension(array('extension.JPG', 'extension.gif', 'extension.png'))); $this->assertTrue(Validation::extension(array('file' => array('name' => 'file.jpg')))); $this->assertTrue(Validation::extension(array('file1' => array('name' => 'file.jpg'), 'file2' => array('name' => 'file.jpg'), 'file3' => array('name' => 'file.jpg')))); $this->assertFalse(Validation::extension(array('file1' => array('name' => 'file.jpg'), 'file2' => array('name' => 'file.jpg'), 'file3' => array('name' => 'file.jpg')), array('gif'))); $this->assertFalse(Validation::extension(array('noextension', 'extension.JPG', 'extension.gif', 'extension.png'))); $this->assertFalse(Validation::extension(array('extension.pdf', 'extension.JPG', 'extension.gif', 'extension.png'))); } /** * testMoney method * * @return void */ public function testMoney() { $this->assertTrue(Validation::money('100')); $this->assertTrue(Validation::money('100.11')); $this->assertTrue(Validation::money('100.112')); $this->assertTrue(Validation::money('100.1')); $this->assertTrue(Validation::money('100.111,1')); $this->assertTrue(Validation::money('100.111,11')); $this->assertFalse(Validation::money('100.111,111')); $this->assertTrue(Validation::money('$100')); $this->assertTrue(Validation::money('$100.11')); $this->assertTrue(Validation::money('$100.112')); $this->assertTrue(Validation::money('$100.1')); $this->assertFalse(Validation::money('$100.1111')); $this->assertFalse(Validation::money('text')); $this->assertTrue(Validation::money('100', 'right')); $this->assertTrue(Validation::money('100.11$', 'right')); $this->assertTrue(Validation::money('100.112$', 'right')); $this->assertTrue(Validation::money('100.1$', 'right')); $this->assertFalse(Validation::money('100.1111$', 'right')); $this->assertTrue(Validation::money('โ‚ฌ100')); $this->assertTrue(Validation::money('โ‚ฌ100.11')); $this->assertTrue(Validation::money('โ‚ฌ100.112')); $this->assertTrue(Validation::money('โ‚ฌ100.1')); $this->assertFalse(Validation::money('โ‚ฌ100.1111')); $this->assertTrue(Validation::money('100', 'right')); $this->assertTrue(Validation::money('100.11โ‚ฌ', 'right')); $this->assertTrue(Validation::money('100.112โ‚ฌ', 'right')); $this->assertTrue(Validation::money('100.1โ‚ฌ', 'right')); $this->assertFalse(Validation::money('100.1111โ‚ฌ', 'right')); } /** * Test Multiple Select Validation * * @return void */ public function testMultiple() { $this->assertTrue(Validation::multiple(array(0, 1, 2, 3))); $this->assertTrue(Validation::multiple(array(50, 32, 22, 0))); $this->assertTrue(Validation::multiple(array('str', 'var', 'enum', 0))); $this->assertFalse(Validation::multiple('')); $this->assertFalse(Validation::multiple(null)); $this->assertFalse(Validation::multiple(array())); $this->assertTrue(Validation::multiple(array(0))); $this->assertTrue(Validation::multiple(array('0'))); $this->assertFalse(Validation::multiple(array(''))); $this->assertTrue(Validation::multiple(array(0, 3, 4, 5), array('in' => range(0, 10)))); $this->assertFalse(Validation::multiple(array(0, 15, 20, 5), array('in' => range(0, 10)))); $this->assertFalse(Validation::multiple(array(0, 5, 10, 11), array('in' => range(0, 10)))); $this->assertFalse(Validation::multiple(array('boo', 'foo', 'bar'), array('in' => array('foo', 'bar', 'baz')))); $this->assertFalse(Validation::multiple(array('foo', '1bar'), array('in' => range(0, 10)))); $this->assertFalse(Validation::multiple(array(1, 5, 10, 11), array('max' => 3))); $this->assertTrue(Validation::multiple(array(0, 5, 10, 11), array('max' => 4))); $this->assertFalse(Validation::multiple(array(0, 5, 10, 11, 55), array('max' => 4))); $this->assertTrue(Validation::multiple(array('foo', 'bar', 'baz'), array('max' => 3))); $this->assertFalse(Validation::multiple(array('foo', 'bar', 'baz', 'squirrel'), array('max' => 3))); $this->assertTrue(Validation::multiple(array(0, 5, 10, 11), array('min' => 3))); $this->assertTrue(Validation::multiple(array(0, 5, 10, 11, 55), array('min' => 3))); $this->assertFalse(Validation::multiple(array('foo', 'bar', 'baz'), array('min' => 5))); $this->assertFalse(Validation::multiple(array('foo', 'bar', 'baz', 'squirrel'), array('min' => 10))); $this->assertTrue(Validation::multiple(array(0, 5, 9), array('in' => range(0, 10), 'max' => 5))); $this->assertTrue(Validation::multiple(array('0', '5', '9'), array('in' => range(0, 10), 'max' => 5))); $this->assertFalse(Validation::multiple(array(0, 5, 9, 8, 6, 2, 1), array('in' => range(0, 10), 'max' => 5))); $this->assertFalse(Validation::multiple(array(0, 5, 9, 8, 11), array('in' => range(0, 10), 'max' => 5))); $this->assertFalse(Validation::multiple(array(-1, 5, 9), array('in' => range(0, 10), 'max' => 5, 'min' => 3))); $this->assertFalse(Validation::multiple(array(-1, 5, 9, 8, 6, 2, 1), array('in' => range(0, 10), 'max' => 5, 'min' => 2))); $this->assertFalse(Validation::multiple(array(0, 5, 9, 8, 11), array('in' => range(0, 10), 'max' => 5, 'min' => 2))); $this->assertFalse(Validation::multiple(array('2x', '3x'), array('in' => array(1, 2, 3, 4, 5)))); $this->assertFalse(Validation::multiple(array(2, 3), array('in' => array('1x', '2x', '3x', '4x')))); $this->assertFalse(Validation::multiple(array('one'), array('in' => array('One', 'Two')))); $this->assertFalse(Validation::multiple(array('Two'), array('in' => array('one', 'two')))); // case insensitive $this->assertTrue(Validation::multiple(array('one'), array('in' => array('One', 'Two')), true)); $this->assertTrue(Validation::multiple(array('Two'), array('in' => array('one', 'two')), true)); $this->assertFalse(Validation::multiple(array('three'), array('in' => array('one', 'two')), true)); } /** * testNumeric method * * @return void */ public function testNumeric() { $this->assertFalse(Validation::numeric('teststring')); $this->assertFalse(Validation::numeric('1.1test')); $this->assertFalse(Validation::numeric('2test')); $this->assertTrue(Validation::numeric('2')); $this->assertTrue(Validation::numeric(2)); $this->assertTrue(Validation::numeric(2.2)); $this->assertTrue(Validation::numeric('2.2')); } /** * testNaturalNumber method * * @return void */ public function testNaturalNumber() { $this->assertFalse(Validation::naturalNumber('teststring')); $this->assertFalse(Validation::naturalNumber('5.4')); $this->assertFalse(Validation::naturalNumber(99.004)); $this->assertFalse(Validation::naturalNumber('0,05')); $this->assertFalse(Validation::naturalNumber('-2')); $this->assertFalse(Validation::naturalNumber(-2)); $this->assertFalse(Validation::naturalNumber('0')); $this->assertFalse(Validation::naturalNumber('050')); $this->assertTrue(Validation::naturalNumber('2')); $this->assertTrue(Validation::naturalNumber(49)); $this->assertTrue(Validation::naturalNumber('0', true)); $this->assertTrue(Validation::naturalNumber(0, true)); } /** * testPhone method * * @return void */ public function testPhone() { $this->assertFalse(Validation::phone('teststring')); $this->assertFalse(Validation::phone('1-(33)-(333)-(4444)')); $this->assertFalse(Validation::phone('1-(33)-3333-4444')); $this->assertFalse(Validation::phone('1-(33)-33-4444')); $this->assertFalse(Validation::phone('1-(33)-3-44444')); $this->assertFalse(Validation::phone('1-(33)-3-444')); $this->assertFalse(Validation::phone('1-(33)-3-44')); $this->assertFalse(Validation::phone('(055) 999-9999')); $this->assertFalse(Validation::phone('(155) 999-9999')); $this->assertFalse(Validation::phone('(595) 999-9999')); $this->assertFalse(Validation::phone('(213) 099-9999')); $this->assertFalse(Validation::phone('(213) 199-9999')); // invalid area-codes $this->assertFalse(Validation::phone('1-(511)-999-9999')); $this->assertFalse(Validation::phone('1-(555)-999-9999')); // invalid exhange $this->assertFalse(Validation::phone('1-(222)-511-9999')); // invalid phone number $this->assertFalse(Validation::phone('1-(222)-555-0199')); $this->assertFalse(Validation::phone('1-(222)-555-0122')); // valid phone numbers $this->assertTrue(Validation::phone('416-428-1234')); $this->assertTrue(Validation::phone('1-(369)-333-4444')); $this->assertTrue(Validation::phone('1-(973)-333-4444')); $this->assertTrue(Validation::phone('1-(313)-555-9999')); $this->assertTrue(Validation::phone('1-(222)-555-0299')); $this->assertTrue(Validation::phone('508-428-1234')); $this->assertTrue(Validation::phone('1-(508)-232-9651')); $this->assertTrue(Validation::phone('1 (222) 333 4444')); $this->assertTrue(Validation::phone('+1 (222) 333 4444')); $this->assertTrue(Validation::phone('(222) 333 4444')); $this->assertTrue(Validation::phone('1-(333)-333-4444')); $this->assertTrue(Validation::phone('1.(333)-333-4444')); $this->assertTrue(Validation::phone('1.(333).333-4444')); $this->assertTrue(Validation::phone('1.(333).333.4444')); $this->assertTrue(Validation::phone('1-333-333-4444')); } /** * testPostal method * * @return void */ public function testPostal() { $this->assertFalse(Validation::postal('111', null, 'de')); $this->assertFalse(Validation::postal('1111', null, 'de')); $this->assertTrue(Validation::postal('13089', null, 'de')); $this->assertFalse(Validation::postal('111', null, 'be')); $this->assertFalse(Validation::postal('0123', null, 'be')); $this->assertTrue(Validation::postal('1204', null, 'be')); $this->assertFalse(Validation::postal('111', null, 'it')); $this->assertFalse(Validation::postal('1111', null, 'it')); $this->assertTrue(Validation::postal('13089', null, 'it')); $this->assertFalse(Validation::postal('111', null, 'uk')); $this->assertFalse(Validation::postal('1111', null, 'uk')); $this->assertFalse(Validation::postal('AZA 0AB', null, 'uk')); $this->assertFalse(Validation::postal('X0A 0ABC', null, 'uk')); $this->assertTrue(Validation::postal('X0A 0AB', null, 'uk')); $this->assertTrue(Validation::postal('AZ0A 0AA', null, 'uk')); $this->assertTrue(Validation::postal('A89 2DD', null, 'uk')); $this->assertFalse(Validation::postal('111', null, 'ca')); $this->assertFalse(Validation::postal('1111', null, 'ca')); $this->assertFalse(Validation::postal('D2A 0A0', null, 'ca')); $this->assertFalse(Validation::postal('BAA 0ABC', null, 'ca')); $this->assertFalse(Validation::postal('B2A AABC', null, 'ca')); $this->assertFalse(Validation::postal('B2A 2AB', null, 'ca')); $this->assertFalse(Validation::postal('K1A 1D1', null, 'ca')); $this->assertFalse(Validation::postal('K1O 1Q1', null, 'ca')); $this->assertFalse(Validation::postal('A1A 1U1', null, 'ca')); $this->assertFalse(Validation::postal('A1F 1B1', null, 'ca')); $this->assertTrue(Validation::postal('X0A 0A2', null, 'ca')); $this->assertTrue(Validation::postal('G4V 4C3', null, 'ca')); $this->assertFalse(Validation::postal('111', null, 'us')); $this->assertFalse(Validation::postal('1111', null, 'us')); $this->assertFalse(Validation::postal('130896', null, 'us')); $this->assertFalse(Validation::postal('13089-33333', null, 'us')); $this->assertFalse(Validation::postal('13089-333', null, 'us')); $this->assertFalse(Validation::postal('13A89-4333', null, 'us')); $this->assertTrue(Validation::postal('13089-3333', null, 'us')); $this->assertFalse(Validation::postal('111')); $this->assertFalse(Validation::postal('1111')); $this->assertFalse(Validation::postal('130896')); $this->assertFalse(Validation::postal('13089-33333')); $this->assertFalse(Validation::postal('13089-333')); $this->assertFalse(Validation::postal('13A89-4333')); $this->assertTrue(Validation::postal('13089-3333')); } /** * test that phone and postal pass to other classes. * * @return void */ public function testPhonePostalSsnPass() { $this->assertTrue(Validation::postal('text', null, 'testNl')); $this->assertTrue(Validation::phone('text', null, 'testDe')); $this->assertTrue(Validation::ssn('text', null, 'testNl')); } /** * test pass through failure on postal * * @expectedException PHPUnit_Framework_Error * @return void */ public function testPassThroughMethodFailure() { Validation::phone('text', null, 'testNl'); } /** * test the pass through calling of an alternate locale with postal() * * @expectedException PHPUnit_Framework_Error * @return void */ public function testPassThroughClassFailure() { Validation::postal('text', null, 'AUTOFAIL'); } /** * test pass through method * * @return void */ public function testPassThroughMethod() { $this->assertTrue(Validation::postal('text', null, 'testNl')); } /** * testSsn method * * @return void */ public function testSsn() { $this->assertFalse(Validation::ssn('111-333', null, 'dk')); $this->assertFalse(Validation::ssn('111111-333', null, 'dk')); $this->assertTrue(Validation::ssn('111111-3334', null, 'dk')); $this->assertFalse(Validation::ssn('1118333', null, 'nl')); $this->assertFalse(Validation::ssn('1234567890', null, 'nl')); $this->assertFalse(Validation::ssn('12345A789', null, 'nl')); $this->assertTrue(Validation::ssn('123456789', null, 'nl')); $this->assertFalse(Validation::ssn('11-33-4333', null, 'us')); $this->assertFalse(Validation::ssn('113-3-4333', null, 'us')); $this->assertFalse(Validation::ssn('111-33-333', null, 'us')); $this->assertTrue(Validation::ssn('111-33-4333', null, 'us')); } /** * testUserDefined method * * @return void */ public function testUserDefined() { $validator = new CustomValidator; $this->assertFalse(Validation::userDefined('33', $validator, 'customValidate')); $this->assertFalse(Validation::userDefined('3333', $validator, 'customValidate')); $this->assertTrue(Validation::userDefined('333', $validator, 'customValidate')); } /** * testDatetime method * * @return void */ public function testDatetime() { $this->assertTrue(Validation::datetime('27-12-2006 01:00', 'dmy')); $this->assertTrue(Validation::datetime('27-12-2006 01:00', array('dmy'))); $this->assertFalse(Validation::datetime('27-12-2006 1:00', 'dmy')); $this->assertTrue(Validation::datetime('27.12.2006 1:00pm', 'dmy')); $this->assertFalse(Validation::datetime('27.12.2006 13:00pm', 'dmy')); $this->assertTrue(Validation::datetime('27/12/2006 1:00pm', 'dmy')); $this->assertFalse(Validation::datetime('27/12/2006 9:00', 'dmy')); $this->assertTrue(Validation::datetime('27 12 2006 1:00pm', 'dmy')); $this->assertFalse(Validation::datetime('27 12 2006 24:00', 'dmy')); $this->assertFalse(Validation::datetime('00-00-0000 1:00pm', 'dmy')); $this->assertFalse(Validation::datetime('00.00.0000 1:00pm', 'dmy')); $this->assertFalse(Validation::datetime('00/00/0000 1:00pm', 'dmy')); $this->assertFalse(Validation::datetime('00 00 0000 1:00pm', 'dmy')); $this->assertFalse(Validation::datetime('31-11-2006 1:00pm', 'dmy')); $this->assertFalse(Validation::datetime('31.11.2006 1:00pm', 'dmy')); $this->assertFalse(Validation::datetime('31/11/2006 1:00pm', 'dmy')); $this->assertFalse(Validation::datetime('31 11 2006 1:00pm', 'dmy')); } /** * testMimeType method * * @return void */ public function testMimeType() { $image = CORE_PATH . 'Cake' . DS . 'Test' . DS . 'test_app' . DS . 'webroot' . DS . 'img' . DS . 'cake.power.gif'; $File = new File($image, false); $this->skipIf(!$File->mime(), 'Cannot determine mimeType'); $this->assertTrue(Validation::mimeType($image, array('image/gif'))); $this->assertTrue(Validation::mimeType(array('tmp_name' => $image), array('image/gif'))); $this->assertTrue(Validation::mimeType(array('tmp_name' => $image), '#image/.+#')); $this->assertTrue(Validation::mimeType($image, array('image/GIF'))); $this->assertFalse(Validation::mimeType($image, array('image/png'))); $this->assertFalse(Validation::mimeType(array('tmp_name' => $image), array('image/png'))); } /** * testMimeTypeFalse method * * @expectedException CakeException * @return void */ public function testMimeTypeFalse() { $image = CORE_PATH . 'Cake' . DS . 'Test' . DS . 'test_app' . DS . 'webroot' . DS . 'img' . DS . 'cake.power.gif'; $File = new File($image, false); $this->skipIf($File->mime(), 'mimeType can be determined, no Exception will be thrown'); Validation::mimeType($image, array('image/gif')); } /** * testUploadError method * * @return void */ public function testUploadError() { $this->assertTrue(Validation::uploadError(0)); $this->assertTrue(Validation::uploadError(array('error' => 0))); $this->assertTrue(Validation::uploadError(array('error' => '0'))); $this->assertFalse(Validation::uploadError(2)); $this->assertFalse(Validation::uploadError(array('error' => 2))); $this->assertFalse(Validation::uploadError(array('error' => '2'))); $this->assertFalse(Validation::uploadError(UPLOAD_ERR_NO_FILE)); $this->assertFalse(Validation::uploadError(UPLOAD_ERR_FORM_SIZE, true)); $this->assertFalse(Validation::uploadError(UPLOAD_ERR_INI_SIZE, true)); $this->assertFalse(Validation::uploadError(UPLOAD_ERR_NO_TMP_DIR, true)); $this->assertTrue(Validation::uploadError(UPLOAD_ERR_NO_FILE, true)); } /** * testFileSize method * * @return void */ public function testFileSize() { $image = CORE_PATH . 'Cake' . DS . 'Test' . DS . 'test_app' . DS . 'webroot' . DS . 'img' . DS . 'cake.power.gif'; $this->assertTrue(Validation::fileSize($image, '<', 1024)); $this->assertTrue(Validation::fileSize(array('tmp_name' => $image), 'isless', 1024)); $this->assertTrue(Validation::fileSize($image, '<', '1KB')); $this->assertTrue(Validation::fileSize($image, '>=', 200)); $this->assertTrue(Validation::fileSize($image, '==', 201)); $this->assertTrue(Validation::fileSize($image, '==', '201B')); $this->assertFalse(Validation::fileSize($image, 'isgreater', 1024)); $this->assertFalse(Validation::fileSize(array('tmp_name' => $image), '>', '1KB')); } /** * Test uploaded file validation. * * @return void */ public function testUploadedFileErrorCode() { $this->assertFalse(Validation::uploadedFile('derp')); $invalid = array( 'name' => 'testing' ); $this->assertFalse(Validation::uploadedFile($invalid)); $file = array( 'name' => 'cake.power.gif', 'tmp_name' => CORE_PATH . 'Cake' . DS . 'Test' . DS . 'test_app' . DS . 'webroot/img/cake.power.gif', 'error' => UPLOAD_ERR_OK, 'type' => 'image/gif', 'size' => 201 ); $this->assertTrue(Validation::uploadedFile($file)); $file['error'] = UPLOAD_ERR_NO_FILE; $this->assertFalse(Validation::uploadedFile($file), 'Error upload should fail.'); } /** * Test uploaded file validation. * * @return void */ public function testUploadedFileMimeType() { $file = array( 'name' => 'cake.power.gif', 'tmp_name' => CORE_PATH . 'Cake' . DS . 'Test' . DS . 'test_app' . DS . 'webroot/img/cake.power.gif', 'error' => UPLOAD_ERR_OK, 'type' => 'text/plain', 'size' => 201 ); $options = array( 'types' => array('text/plain') ); $this->assertFalse(Validation::uploadedFile($file, $options), 'Incorrect mimetype.'); $options = array( 'types' => array('image/gif', 'image/png') ); $this->assertTrue(Validation::uploadedFile($file, $options)); } /** * Test uploaded file validation. * * @return void */ public function testUploadedFileSize() { $file = array( 'name' => 'cake.power.gif', 'tmp_name' => CORE_PATH . 'Cake' . DS . 'Test' . DS . 'test_app' . DS . 'webroot/img/cake.power.gif', 'error' => UPLOAD_ERR_OK, 'type' => 'text/plain', 'size' => 201 ); $options = array( 'minSize' => 500 ); $this->assertFalse(Validation::uploadedFile($file, $options), 'Too small'); $options = array( 'maxSize' => 100 ); $this->assertFalse(Validation::uploadedFile($file, $options), 'Too big'); $options = array( 'minSize' => 100, ); $this->assertTrue(Validation::uploadedFile($file, $options)); $options = array( 'maxSize' => 500, ); $this->assertTrue(Validation::uploadedFile($file, $options)); $options = array( 'minSize' => 100, 'maxSize' => 500 ); $this->assertTrue(Validation::uploadedFile($file, $options)); } /** * Test uploaded file validation. * * @return void */ public function testUploadedFileNoFile() { $file = array( 'name' => '', 'tmp_name' => CORE_PATH . 'Cake' . DS . 'Test' . DS . 'test_app' . DS . 'webroot/img/cake.power.gif', 'error' => UPLOAD_ERR_NO_FILE, 'type' => '', 'size' => 0 ); $options = array( 'optional' => true, 'minSize' => 500, 'types' => array('image/gif', 'image/png') ); $this->assertTrue(Validation::uploadedFile($file, $options), 'No file should be ok.'); $options = array( 'optional' => false ); $this->assertFalse(Validation::uploadedFile($file, $options), 'File is required.'); } } cakephp-2.8.0/lib/Cake/Test/Case/Utility/XmlTest.php000066400000000000000000000731071265552240500221310ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.Utility * @since CakePHP(tm) v 1.2.0.5432 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Xml', 'Utility'); App::uses('CakeTestModel', 'TestSuite/Fixture'); /** * Article class * * @package Cake.Test.Case.Utility */ class XmlArticle extends CakeTestModel { /** * name property * * @var string */ public $name = 'Article'; /** * belongsTo property * * @var array */ public $belongsTo = array( 'User' => array( 'className' => 'XmlUser', 'foreignKey' => 'user_id' ) ); } /** * User class * * @package Cake.Test.Case.Utility */ class XmlUser extends CakeTestModel { /** * name property * * @var string */ public $name = 'User'; /** * hasMany property * * @var array */ public $hasMany = array( 'Article' => array( 'className' => 'XmlArticle' ) ); } /** * XmlTest class * * @package Cake.Test.Case.Utility */ class XmlTest extends CakeTestCase { /** * autoFixtures property * * @var bool */ public $autoFixtures = false; /** * fixtures property * @var array */ public $fixtures = array( 'core.article', 'core.user' ); /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $this->_appEncoding = Configure::read('App.encoding'); Configure::write('App.encoding', 'UTF-8'); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); Configure::write('App.encoding', $this->_appEncoding); } /** * testBuild method * * @return void */ public function testBuild() { $xml = 'value'; $obj = Xml::build($xml); $this->assertTrue($obj instanceof SimpleXMLElement); $this->assertEquals('tag', (string)$obj->getName()); $this->assertEquals('value', (string)$obj); $xml = 'value'; $this->assertEquals($obj, Xml::build($xml)); $obj = Xml::build($xml, array('return' => 'domdocument')); $this->assertTrue($obj instanceof DOMDocument); $this->assertEquals('tag', $obj->firstChild->nodeName); $this->assertEquals('value', $obj->firstChild->nodeValue); $xml = CAKE . 'Test' . DS . 'Fixture' . DS . 'sample.xml'; $obj = Xml::build($xml); $this->assertEquals('tags', $obj->getName()); $this->assertEquals(2, count($obj)); $this->assertEquals(Xml::build($xml), Xml::build(file_get_contents($xml))); $obj = Xml::build($xml, array('return' => 'domdocument')); $this->assertEquals('tags', $obj->firstChild->nodeName); $this->assertEquals( Xml::build($xml, array('return' => 'domdocument')), Xml::build(file_get_contents($xml), array('return' => 'domdocument')) ); $this->assertEquals( Xml::build($xml, array('return' => 'simplexml')), Xml::build($xml, 'simplexml') ); $xml = array('tag' => 'value'); $obj = Xml::build($xml); $this->assertEquals('tag', $obj->getName()); $this->assertEquals('value', (string)$obj); $obj = Xml::build($xml, array('return' => 'domdocument')); $this->assertEquals('tag', $obj->firstChild->nodeName); $this->assertEquals('value', $obj->firstChild->nodeValue); $obj = Xml::build($xml, array('return' => 'domdocument', 'encoding' => null)); $this->assertNotRegExp('/encoding/', $obj->saveXML()); } /** * Test that the readFile option disables local file parsing. * * @expectedException XmlException * @return void */ public function testBuildFromFileWhenDisabled() { $xml = CAKE . 'Test' . DS . 'Fixture' . DS . 'sample.xml'; Xml::build($xml, array('readFile' => false)); } /** * Test that the readFile option disables local file parsing. * * @expectedException XmlException * @return void */ public function testBuildFromUrlWhenDisabled() { $xml = 'http://www.google.com'; Xml::build($xml, array('readFile' => false)); } /** * data provider function for testBuildInvalidData * * @return array */ public static function invalidDataProvider() { return array( array(null), array(false), array(''), array('http://localhost/notthere.xml'), ); } /** * testBuildInvalidData * * @dataProvider invalidDataProvider * @expectedException XmlException * @return void */ public function testBuildInvalidData($value) { Xml::build($value); } /** * Test that building SimpleXmlElement with invalid XML causes the right exception. * * @expectedException XmlException * @return void */ public function testBuildInvalidDataSimpleXml() { $input = ' 'simplexml')); } /** * test build with a single empty tag * * @return void */ public function testBuildEmptyTag() { try { Xml::build(''); $this->fail('No exception'); } catch (Exception $e) { $this->assertTrue(true, 'An exception was raised'); } } /** * testFromArray method * * @return void */ public function testFromArray() { $xml = array('tag' => 'value'); $obj = Xml::fromArray($xml); $this->assertEquals('tag', $obj->getName()); $this->assertEquals('value', (string)$obj); $xml = array('tag' => null); $obj = Xml::fromArray($xml); $this->assertEquals('tag', $obj->getName()); $this->assertEquals('', (string)$obj); $xml = array('tag' => array('@' => 'value')); $obj = Xml::fromArray($xml); $this->assertEquals('tag', $obj->getName()); $this->assertEquals('value', (string)$obj); $xml = array( 'tags' => array( 'tag' => array( array( 'id' => '1', 'name' => 'defect' ), array( 'id' => '2', 'name' => 'enhancement' ) ) ) ); $obj = Xml::fromArray($xml, 'attributes'); $this->assertTrue($obj instanceof SimpleXMLElement); $this->assertEquals('tags', $obj->getName()); $this->assertEquals(2, count($obj)); $xmlText = << XML; $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML()); $obj = Xml::fromArray($xml); $this->assertTrue($obj instanceof SimpleXMLElement); $this->assertEquals('tags', $obj->getName()); $this->assertEquals(2, count($obj)); $xmlText = << 1 defect 2 enhancement XML; $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML()); $xml = array( 'tags' => array( ) ); $obj = Xml::fromArray($xml); $this->assertEquals('tags', $obj->getName()); $this->assertEquals('', (string)$obj); $xml = array( 'tags' => array( 'bool' => true, 'int' => 1, 'float' => 10.2, 'string' => 'ok', 'null' => null, 'array' => array() ) ); $obj = Xml::fromArray($xml, 'tags'); $this->assertEquals(6, count($obj)); $this->assertSame((string)$obj->bool, '1'); $this->assertSame((string)$obj->int, '1'); $this->assertSame((string)$obj->float, '10.2'); $this->assertSame((string)$obj->string, 'ok'); $this->assertSame((string)$obj->null, ''); $this->assertSame((string)$obj->array, ''); $xml = array( 'tags' => array( 'tag' => array( array( '@id' => '1', 'name' => 'defect' ), array( '@id' => '2', 'name' => 'enhancement' ) ) ) ); $obj = Xml::fromArray($xml, 'tags'); $xmlText = << defect enhancement XML; $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML()); $xml = array( 'tags' => array( 'tag' => array( array( '@id' => '1', 'name' => 'defect', '@' => 'Tag 1' ), array( '@id' => '2', 'name' => 'enhancement' ), ), '@' => 'All tags' ) ); $obj = Xml::fromArray($xml, 'tags'); $xmlText = << All tagsTag 1defectenhancement XML; $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML()); $xml = array( 'tags' => array( 'tag' => array( 'id' => 1, '@' => 'defect' ) ) ); $obj = Xml::fromArray($xml, 'attributes'); $xmlText = '<' . '?xml version="1.0" encoding="UTF-8"?>defect'; $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML()); $xml = array( 'tag' => array( '@' => 0, '@test' => 'A test' ) ); $obj = Xml::fromArray($xml); $xmlText = << 0 XML; $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML()); } /** * Test non-sequential keys in list types. * * @return void */ public function testFromArrayNonSequentialKeys() { $xmlArray = array( 'Event' => array( array( 'id' => '235', 'Attribute' => array( 0 => array( 'id' => '9646', ), 2 => array( 'id' => '9647', ) ) ) ) ); $obj = Xml::fromArray($xmlArray); $expected = << 235 9646 9647 XML; $this->assertXmlStringEqualsXmlString($expected, $obj->asXML()); } /** * testFromArrayPretty method * * @return void */ public function testFromArrayPretty() { $xml = array( 'tags' => array( 'tag' => array( array( 'id' => '1', 'name' => 'defect' ), array( 'id' => '2', 'name' => 'enhancement' ) ) ) ); $expected = << 1defect2enhancement XML; $xmlResponse = Xml::fromArray($xml, array('pretty' => false)); $this->assertTextEquals($expected, $xmlResponse->asXML()); $expected = << 1 defect 2 enhancement XML; $xmlResponse = Xml::fromArray($xml, array('pretty' => true)); $this->assertTextEquals($expected, $xmlResponse->asXML()); $xml = array( 'tags' => array( 'tag' => array( array( 'id' => '1', 'name' => 'defect' ), array( 'id' => '2', 'name' => 'enhancement' ) ) ) ); $expected = << XML; $xmlResponse = Xml::fromArray($xml, array('pretty' => false, 'format' => 'attributes')); $this->assertTextEquals($expected, $xmlResponse->asXML()); $expected = << XML; $xmlResponse = Xml::fromArray($xml, array('pretty' => true, 'format' => 'attributes')); $this->assertTextEquals($expected, $xmlResponse->asXML()); } /** * data provider for fromArray() failures * * @return array */ public static function invalidArrayDataProvider() { return array( array(''), array(null), array(false), array(array()), array(array('numeric key as root')), array(array('item1' => '', 'item2' => '')), array(array('items' => array('item1', 'item2'))), array(array( 'tags' => array( 'tag' => array( array( array( 'string' ) ) ) ) )), array(array( 'tags' => array( '@tag' => array( array( '@id' => '1', 'name' => 'defect' ), array( '@id' => '2', 'name' => 'enhancement' ) ) ) )), array(new DateTime()) ); } /** * testFromArrayFail method * * @dataProvider invalidArrayDataProvider * @return void */ public function testFromArrayFail($value) { try { Xml::fromArray($value); $this->fail('No exception.'); } catch (Exception $e) { $this->assertTrue(true, 'Caught exception.'); } } /** * Test that there are not unterminated errors when building xml * * @return void */ public function testFromArrayUnterminatedError() { $data = array( 'product_ID' => 'GENERT-DL', 'deeplink' => 'http://example.com/deep', 'image_URL' => 'http://example.com/image', 'thumbnail_image_URL' => 'http://example.com/thumb', 'brand' => 'Malte Lange & Co', 'availability' => 'in stock', 'authors' => array( 'author' => array('Malte Lange & Co') ) ); $xml = Xml::fromArray(array('products' => $data), 'tags'); $expected = << GENERT-DL http://example.com/deep http://example.com/image http://example.com/thumb Malte Lange & Co in stock Malte Lange & Co XML; $this->assertXmlStringEqualsXmlString($expected, $xml->asXML()); } /** * testToArray method * * @return void */ public function testToArray() { $xml = 'name'; $obj = Xml::build($xml); $this->assertEquals(array('tag' => 'name'), Xml::toArray($obj)); $xml = CAKE . 'Test' . DS . 'Fixture' . DS . 'sample.xml'; $obj = Xml::build($xml); $expected = array( 'tags' => array( 'tag' => array( array( '@id' => '1', 'name' => 'defect' ), array( '@id' => '2', 'name' => 'enhancement' ) ) ) ); $this->assertEquals($expected, Xml::toArray($obj)); $array = array( 'tags' => array( 'tag' => array( array( 'id' => '1', 'name' => 'defect' ), array( 'id' => '2', 'name' => 'enhancement' ) ) ) ); $this->assertEquals(Xml::toArray(Xml::fromArray($array, 'tags')), $array); $expected = array( 'tags' => array( 'tag' => array( array( '@id' => '1', '@name' => 'defect' ), array( '@id' => '2', '@name' => 'enhancement' ) ) ) ); $this->assertEquals($expected, Xml::toArray(Xml::fromArray($array, 'attributes'))); $this->assertEquals($expected, Xml::toArray(Xml::fromArray($array, array('return' => 'domdocument', 'format' => 'attributes')))); $this->assertEquals(Xml::toArray(Xml::fromArray($array)), $array); $this->assertEquals(Xml::toArray(Xml::fromArray($array, array('return' => 'domdocument'))), $array); $array = array( 'tags' => array( 'tag' => array( 'id' => '1', 'posts' => array( array('id' => '1'), array('id' => '2') ) ), 'tagOther' => array( 'subtag' => array( 'id' => '1' ) ) ) ); $expected = array( 'tags' => array( 'tag' => array( '@id' => '1', 'posts' => array( array('@id' => '1'), array('@id' => '2') ) ), 'tagOther' => array( 'subtag' => array( '@id' => '1' ) ) ) ); $this->assertEquals($expected, Xml::toArray(Xml::fromArray($array, 'attributes'))); $this->assertEquals($expected, Xml::toArray(Xml::fromArray($array, array('format' => 'attributes', 'return' => 'domdocument')))); $xml = << defect XML; $obj = Xml::build($xml); $expected = array( 'root' => array( 'tag' => array( '@id' => 1, '@' => 'defect' ) ) ); $this->assertEquals($expected, Xml::toArray($obj)); $xml = <<
ApplesBananas
CakePHPMIT
The book is on the table.
XML; $obj = Xml::build($xml); $expected = array( 'root' => array( 'table' => array( array('tr' => array('td' => array('Apples', 'Bananas'))), array('name' => 'CakePHP', 'license' => 'MIT'), 'The book is on the table.' ) ) ); $this->assertEquals($expected, Xml::toArray($obj)); $xml = << defect 1 XML; $obj = Xml::build($xml); $expected = array( 'root' => array( 'tag' => 'defect', 'cake:bug' => 1 ) ); $this->assertEquals($expected, Xml::toArray($obj)); $xml = '0'; $obj = Xml::build($xml); $expected = array( 'tag' => array( '@type' => 'myType', '@' => 0 ) ); $this->assertEquals($expected, Xml::toArray($obj)); } /** * testRss * * @return void */ public function testRss() { $rss = file_get_contents(CAKE . 'Test' . DS . 'Fixture' . DS . 'rss.xml'); $rssAsArray = Xml::toArray(Xml::build($rss)); $this->assertEquals('2.0', $rssAsArray['rss']['@version']); $this->assertEquals(2, count($rssAsArray['rss']['channel']['item'])); $atomLink = array('@href' => 'http://bakery.cakephp.org/articles/rss', '@rel' => 'self', '@type' => 'application/rss+xml'); $this->assertEquals($rssAsArray['rss']['channel']['atom:link'], $atomLink); $this->assertEquals('http://bakery.cakephp.org/', $rssAsArray['rss']['channel']['link']); $expected = array( 'title' => 'Alertpay automated sales via IPN', 'link' => 'http://bakery.cakephp.org/articles/view/alertpay-automated-sales-via-ipn', 'description' => 'I\'m going to show you how I implemented a payment module via the Alertpay payment processor.', 'pubDate' => 'Tue, 31 Aug 2010 01:42:00 -0500', 'guid' => 'http://bakery.cakephp.org/articles/view/alertpay-automated-sales-via-ipn' ); $this->assertSame($expected, $rssAsArray['rss']['channel']['item'][1]); $rss = array( 'rss' => array( 'xmlns:atom' => 'http://www.w3.org/2005/Atom', '@version' => '2.0', 'channel' => array( 'atom:link' => array( '@href' => 'http://bakery.cakephp.org/articles/rss', '@rel' => 'self', '@type' => 'application/rss+xml' ), 'title' => 'The Bakery: ', 'link' => 'http://bakery.cakephp.org/', 'description' => 'Recent Articles at The Bakery.', 'pubDate' => 'Sun, 12 Sep 2010 04:18:26 -0500', 'item' => array( array( 'title' => 'CakePHP 1.3.4 released', 'link' => 'http://bakery.cakephp.org/articles/view/cakephp-1-3-4-released' ), array( 'title' => 'Wizard Component 1.2 Tutorial', 'link' => 'http://bakery.cakephp.org/articles/view/wizard-component-1-2-tutorial' ) ) ) ) ); $rssAsSimpleXML = Xml::fromArray($rss); $xmlText = << The Bakery: http://bakery.cakephp.org/ Recent Articles at The Bakery. Sun, 12 Sep 2010 04:18:26 -0500 CakePHP 1.3.4 released http://bakery.cakephp.org/articles/view/cakephp-1-3-4-released Wizard Component 1.2 Tutorial http://bakery.cakephp.org/articles/view/wizard-component-1-2-tutorial XML; $this->assertXmlStringEqualsXmlString($xmlText, $rssAsSimpleXML->asXML()); } /** * testXmlRpc * * @return void */ public function testXmlRpc() { $xml = Xml::build('test'); $expected = array( 'methodCall' => array( 'methodName' => 'test', 'params' => '' ) ); $this->assertSame($expected, Xml::toArray($xml)); $xml = Xml::build('test12Egypt0-31'); $expected = array( 'methodCall' => array( 'methodName' => 'test', 'params' => array( 'param' => array( 'value' => array( 'array' => array( 'data' => array( 'value' => array( array('int' => '12'), array('string' => 'Egypt'), array('boolean' => '0'), array('int' => '-31') ) ) ) ) ) ) ) ); $this->assertSame($expected, Xml::toArray($xml)); $xmlText = << 1 testing XML; $xml = Xml::build($xmlText); $expected = array( 'methodResponse' => array( 'params' => array( 'param' => array( 'value' => array( 'array' => array( 'data' => array( 'value' => array( array('int' => '1'), array('string' => 'testing') ) ) ) ) ) ) ) ); $this->assertSame($expected, Xml::toArray($xml)); $xml = Xml::fromArray($expected, 'tags'); $this->assertXmlStringEqualsXmlString($xmlText, $xml->asXML()); } /** * testSoap * * @return void */ public function testSoap() { $xmlRequest = Xml::build(CAKE . 'Test' . DS . 'Fixture' . DS . 'soap_request.xml'); $expected = array( 'Envelope' => array( '@soap:encodingStyle' => 'http://www.w3.org/2001/12/soap-encoding', 'soap:Body' => array( 'm:GetStockPrice' => array( 'm:StockName' => 'IBM' ) ) ) ); $this->assertEquals($expected, Xml::toArray($xmlRequest)); $xmlResponse = Xml::build(CAKE . 'Test' . DS . 'Fixture' . DS . 'soap_response.xml'); $expected = array( 'Envelope' => array( '@soap:encodingStyle' => 'http://www.w3.org/2001/12/soap-encoding', 'soap:Body' => array( 'm:GetStockPriceResponse' => array( 'm:Price' => '34.5' ) ) ) ); $this->assertEquals($expected, Xml::toArray($xmlResponse)); $xml = array( 'soap:Envelope' => array( 'xmlns:soap' => 'http://www.w3.org/2001/12/soap-envelope', '@soap:encodingStyle' => 'http://www.w3.org/2001/12/soap-encoding', 'soap:Body' => array( 'xmlns:m' => 'http://www.example.org/stock', 'm:GetStockPrice' => array( 'm:StockName' => 'IBM' ) ) ) ); $xmlRequest = Xml::fromArray($xml, array('encoding' => null)); $xmlText = << IBM XML; $this->assertXmlStringEqualsXmlString($xmlText, $xmlRequest->asXML()); } /** * testNamespace * * @return void */ public function testNamespace() { $xml = << good bad Tag without ns XML; $xmlResponse = Xml::build($xml); $expected = array( 'root' => array( 'ns:tag' => array( '@id' => '1', 'child' => 'good', 'otherchild' => 'bad' ), 'tag' => 'Tag without ns' ) ); $this->assertEquals($expected, Xml::toArray($xmlResponse)); $xmlResponse = Xml::build('1'); $expected = array( 'root' => array( 'ns:tag' => array( '@id' => '1' ), 'tag' => array( 'id' => '1' ) ) ); $this->assertEquals($expected, Xml::toArray($xmlResponse)); $xmlResponse = Xml::build('1'); $expected = array( 'root' => array( 'ns:attr' => '1' ) ); $this->assertEquals($expected, Xml::toArray($xmlResponse)); $xmlResponse = Xml::build('1'); $this->assertEquals($expected, Xml::toArray($xmlResponse)); $xml = array( 'root' => array( 'ns:attr' => array( 'xmlns:ns' => 'http://cakephp.org', '@' => 1 ) ) ); $expected = '<' . '?xml version="1.0" encoding="UTF-8"?>1'; $xmlResponse = Xml::fromArray($xml); $this->assertEquals($expected, str_replace(array("\r", "\n"), '', $xmlResponse->asXML())); $xml = array( 'root' => array( 'tag' => array( 'xmlns:pref' => 'http://cakephp.org', 'pref:item' => array( 'item 1', 'item 2' ) ) ) ); $expected = << item 1 item 2 XML; $xmlResponse = Xml::fromArray($xml); $this->assertXmlStringEqualsXmlString($expected, $xmlResponse->asXML()); $xml = array( 'root' => array( 'tag' => array( 'xmlns:' => 'http://cakephp.org' ) ) ); $expected = '<' . '?xml version="1.0" encoding="UTF-8"?>'; $xmlResponse = Xml::fromArray($xml); $this->assertXmlStringEqualsXmlString($expected, $xmlResponse->asXML()); $xml = array( 'root' => array( 'xmlns:' => 'http://cakephp.org' ) ); $expected = '<' . '?xml version="1.0" encoding="UTF-8"?>'; $xmlResponse = Xml::fromArray($xml); $this->assertXmlStringEqualsXmlString($expected, $xmlResponse->asXML()); $xml = array( 'root' => array( 'xmlns:ns' => 'http://cakephp.org' ) ); $expected = '<' . '?xml version="1.0" encoding="UTF-8"?>'; $xmlResponse = Xml::fromArray($xml); $this->assertXmlStringEqualsXmlString($expected, $xmlResponse->asXML()); } /** * test that CDATA blocks don't get screwed up by SimpleXml * * @return void */ public function testCdata() { $xml = '<' . '?xml version="1.0" encoding="UTF-8"?>' . ''; $result = Xml::build($xml); $this->assertEquals(' Mark ', (string)$result->name); } /** * data provider for toArray() failures * * @return array */ public static function invalidToArrayDataProvider() { return array( array(new DateTime()), array(array()) ); } /** * testToArrayFail method * * @dataProvider invalidToArrayDataProvider * @expectedException XmlException * @return void */ public function testToArrayFail($value) { Xml::toArray($value); } /** * testWithModel method * * @return void */ public function testWithModel() { $this->loadFixtures('User', 'Article'); $user = new XmlUser(); $data = $user->read(null, 1); $obj = Xml::build(compact('data')); $expected = << 1mariano5f4dcc3b5aa765d61d8327deb882cf99 2007-03-17 01:16:232007-03-17 01:18:31

11First ArticleFirst Article Body Y2007-03-18 10:39:232007-03-18 10:41:31
31Third ArticleThird Article Body Y2007-03-18 10:43:232007-03-18 10:45:31
XML; $this->assertXmlStringEqualsXmlString($expected, $obj->asXML()); //multiple model results - without a records key it would fatal error $data = $user->find('all', array('limit' => 2)); $data = array('records' => $data); $obj = Xml::build(compact('data')); $expected = << 1mariano5f4dcc3b5aa765d61d8327deb882cf99 2007-03-17 01:16:232007-03-17 01:18:31
11First ArticleFirst Article Body Y2007-03-18 10:39:232007-03-18 10:41:31
31Third ArticleThird Article Body Y2007-03-18 10:43:232007-03-18 10:45:31
2nate5f4dcc3b5aa765d61d8327deb882cf99 2007-03-17 01:18:232007-03-17 01:20:31
XML; $obj->asXML(); $this->assertXmlStringEqualsXmlString($expected, $obj->asXML()); } /** * Test ampersand in text elements. * * @return void */ public function testAmpInText() { $data = array( 'outer' => array( 'inner' => array('name' => 'mark & mark') ) ); $obj = Xml::build($data); $result = $obj->asXml(); $this->assertContains('mark & mark', $result); } /** * Test that entity loading is disabled by default. * * @return void */ public function testNoEntityLoading() { $file = CAKE . 'VERSION.txt'; $xml = <<]> &payload; XML; try { $result = Xml::build($xml); $this->assertEquals('', (string)$result->xxe); } catch (Exception $e) { $this->assertTrue(true, 'A warning was raised meaning external entities were not loaded'); } } } cakephp-2.8.0/lib/Cake/Test/Case/View/000077500000000000000000000000001265552240500172575ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/View/Helper/000077500000000000000000000000001265552240500204765ustar00rootroot00000000000000cakephp-2.8.0/lib/Cake/Test/Case/View/Helper/CacheHelperTest.php000066400000000000000000000457361265552240500242310ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.View.Helper * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('Controller', 'Controller'); App::uses('Model', 'Model'); App::uses('View', 'View'); App::uses('CacheHelper', 'View/Helper'); /** * CacheTestController class * * @package Cake.Test.Case.View.Helper */ class CacheTestController extends Controller { /** * helpers property * * @var array */ public $helpers = array('Html', 'Cache'); /** * cache_parsing method * * @return void */ public function cache_parsing() { $this->viewPath = 'Posts'; $this->layout = 'cache_layout'; $this->set('variable', 'variableValue'); $this->set('superman', 'clark kent'); $this->set('batman', 'bruce wayne'); $this->set('spiderman', 'peter parker'); } } /** * CacheHelperTest class * * @package Cake.Test.Case.View.Helper */ class CacheHelperTest extends CakeTestCase { /** * Checks if TMP/views is writable, and skips the case if it is not. * * @return void */ public function skip() { if (!is_writable(TMP . 'cache' . DS . 'views' . DS)) { $this->markTestSkipped('TMP/views is not writable %s'); } } /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $_GET = array(); $request = new CakeRequest(); $this->Controller = new CacheTestController($request); $View = new View($this->Controller); $this->Cache = new CacheHelper($View); Configure::write('Cache.check', true); Configure::write('Cache.disable', false); App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) ), App::RESET); } /** * tearDown method * * @return void */ public function tearDown() { clearCache(); unset($this->Cache); parent::tearDown(); } /** * test cache parsing with no cake:nocache tags in view file. * * @return void */ public function testLayoutCacheParsingNoTagsInView() { $this->Controller->cache_parsing(); $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array(), 'named' => array() )); $this->Controller->cacheAction = 21600; $this->Controller->request->here = '/cacheTest/cache_parsing'; $this->Controller->request->action = 'cache_parsing'; $View = new View($this->Controller); $result = $View->render('index'); $this->assertNotRegExp('/cake:nocache/', $result); $this->assertNotRegExp('/php echo/', $result); $filename = CACHE . 'views' . DS . 'cachetest_cache_parsing.php'; $this->assertTrue(file_exists($filename)); $contents = file_get_contents($filename); $this->assertRegExp('/php echo \$variable/', $contents); $this->assertRegExp('/php echo microtime()/', $contents); $this->assertRegExp('/clark kent/', $result); unlink($filename); } /** * test cache parsing with non-latin characters in current route * * @return void */ public function testCacheNonLatinCharactersInRoute() { $this->Controller->cache_parsing(); $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array('้ขจ่ก—ใ‚ใพใ‚“'), 'named' => array() )); $this->Controller->cacheAction = 21600; $this->Controller->request->here = '/posts/view/้ขจ่ก—ใ‚ใพใ‚“'; $this->Controller->action = 'view'; $View = new View($this->Controller); $View->render('index'); $filename = CACHE . 'views' . DS . 'posts_view_้ขจ่ก—ใ‚ใพใ‚“.php'; $this->assertTrue(file_exists($filename)); unlink($filename); } /** * Test cache parsing with cake:nocache tags in view file. * * @return void */ public function testLayoutCacheParsingWithTagsInView() { $this->Controller->cache_parsing(); $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array(), 'named' => array() )); $this->Controller->cacheAction = 21600; $this->Controller->request->here = '/cacheTest/cache_parsing'; $this->Controller->action = 'cache_parsing'; $View = new View($this->Controller); $result = $View->render('test_nocache_tags'); $this->assertNotRegExp('/cake:nocache/', $result); $this->assertNotRegExp('/php echo/', $result); $filename = CACHE . 'views' . DS . 'cachetest_cache_parsing.php'; $this->assertTrue(file_exists($filename)); $contents = file_get_contents($filename); $this->assertRegExp('/if \(is_writable\(TMP\)\)\:/', $contents); $this->assertRegExp('/php echo \$variable/', $contents); $this->assertRegExp('/php echo microtime()/', $contents); $this->assertNotRegExp('/cake:nocache/', $contents); unlink($filename); } /** * test that multiple tags function with multiple nocache tags in the layout. * * @return void */ public function testMultipleNoCacheTagsInViewfile() { $this->Controller->cache_parsing(); $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array(), 'named' => array() )); $this->Controller->cacheAction = 21600; $this->Controller->request->here = '/cacheTest/cache_parsing'; $this->Controller->action = 'cache_parsing'; $View = new View($this->Controller); $result = $View->render('multiple_nocache'); $this->assertNotRegExp('/cake:nocache/', $result); $this->assertNotRegExp('/php echo/', $result); $filename = CACHE . 'views' . DS . 'cachetest_cache_parsing.php'; $this->assertTrue(file_exists($filename)); $contents = file_get_contents($filename); $this->assertNotRegExp('/cake:nocache/', $contents); unlink($filename); } /** * testComplexNoCache method * * @return void */ public function testComplexNoCache() { $this->Controller->cache_parsing(); $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_complex', 'pass' => array(), 'named' => array() )); $this->Controller->cacheAction = array('cache_complex' => 21600); $this->Controller->request->here = '/cacheTest/cache_complex'; $this->Controller->action = 'cache_complex'; $this->Controller->layout = 'multi_cache'; $this->Controller->viewPath = 'Posts'; $View = new View($this->Controller); $result = $View->render('sequencial_nocache'); $this->assertNotRegExp('/cake:nocache/', $result); $this->assertNotRegExp('/php echo/', $result); $this->assertRegExp('/A\. Layout Before Content/', $result); $this->assertRegExp('/B\. In Plain Element/', $result); $this->assertRegExp('/C\. Layout After Test Element/', $result); $this->assertRegExp('/D\. In View File/', $result); $this->assertRegExp('/E\. Layout After Content/', $result); $this->assertRegExp('/F\. In Element With No Cache Tags/', $result); $this->assertRegExp('/G\. Layout After Content And After Element With No Cache Tags/', $result); $this->assertNotRegExp('/1\. layout before content/', $result); $this->assertNotRegExp('/2\. in plain element/', $result); $this->assertNotRegExp('/3\. layout after test element/', $result); $this->assertNotRegExp('/4\. in view file/', $result); $this->assertNotRegExp('/5\. layout after content/', $result); $this->assertNotRegExp('/6\. in element with no cache tags/', $result); $this->assertNotRegExp('/7\. layout after content and after element with no cache tags/', $result); $filename = CACHE . 'views' . DS . 'cachetest_cache_complex.php'; $this->assertTrue(file_exists($filename)); $contents = file_get_contents($filename); unlink($filename); $this->assertRegExp('/A\. Layout Before Content/', $contents); $this->assertNotRegExp('/B\. In Plain Element/', $contents); $this->assertRegExp('/C\. Layout After Test Element/', $contents); $this->assertRegExp('/D\. In View File/', $contents); $this->assertRegExp('/E\. Layout After Content/', $contents); $this->assertRegExp('/F\. In Element With No Cache Tags/', $contents); $this->assertRegExp('/G\. Layout After Content And After Element With No Cache Tags/', $contents); $this->assertRegExp('/1\. layout before content/', $contents); $this->assertNotRegExp('/2\. in plain element/', $contents); $this->assertRegExp('/3\. layout after test element/', $contents); $this->assertRegExp('/4\. in view file/', $contents); $this->assertRegExp('/5\. layout after content/', $contents); $this->assertRegExp('/6\. in element with no cache tags/', $contents); $this->assertRegExp('/7\. layout after content and after element with no cache tags/', $contents); } /** * test cache of view vars * * @return void */ public function testCacheViewVars() { $this->Controller->cache_parsing(); $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array(), 'named' => array() )); $this->Controller->request->here = '/cacheTest/cache_parsing'; $this->Controller->cacheAction = 21600; $View = new View($this->Controller); $result = $View->render('index'); $this->assertNotRegExp('/cake:nocache/', $result); $this->assertNotRegExp('/php echo/', $result); $filename = CACHE . 'views' . DS . 'cachetest_cache_parsing.php'; $this->assertTrue(file_exists($filename)); $contents = file_get_contents($filename); $this->assertRegExp('/\$this\-\>viewVars/', $contents); $this->assertRegExp('/extract\(\$this\-\>viewVars, EXTR_SKIP\);/', $contents); $this->assertRegExp('/php echo \$variable/', $contents); unlink($filename); } /** * Test that callback code is generated correctly. * * @return void */ public function testCacheCallbacks() { $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array(), 'named' => array() )); $this->Controller->cacheAction = array( 'cache_parsing' => array( 'duration' => 21600, 'callbacks' => true ) ); $this->Controller->request->here = '/cacheTest/cache_parsing'; $this->Controller->cache_parsing(); $View = new View($this->Controller); $View->render('index'); $filename = CACHE . 'views' . DS . 'cachetest_cache_parsing.php'; $this->assertTrue(file_exists($filename)); $contents = file_get_contents($filename); $this->assertRegExp('/\$controller->startupProcess\(\);/', $contents); unlink($filename); } /** * test cacheAction set to a boolean * * @return void */ public function testCacheActionArray() { $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array(), 'named' => array() )); $this->Controller->request->here = '/cache_test/cache_parsing'; $this->Controller->cacheAction = array( 'cache_parsing' => 21600 ); $this->Controller->cache_parsing(); $View = new View($this->Controller); $result = $View->render('index'); $this->assertNotRegExp('/cake:nocache/', $result); $this->assertNotRegExp('/php echo/', $result); $filename = CACHE . 'views' . DS . 'cache_test_cache_parsing.php'; $this->assertTrue(file_exists($filename)); unlink($filename); } /** * Test that cacheAction works with camelcased controller names. * * @return void */ public function testCacheActionArrayCamelCase() { $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array(), 'named' => array() )); $this->Controller->cacheAction = array( 'cache_parsing' => 21600 ); $this->Controller->request->here = '/cacheTest/cache_parsing'; $this->Controller->cache_parsing(); $View = new View($this->Controller); $result = $View->render('index'); $this->assertNotRegExp('/cake:nocache/', $result); $this->assertNotRegExp('/php echo/', $result); $filename = CACHE . 'views' . DS . 'cachetest_cache_parsing.php'; $this->assertTrue(file_exists($filename)); unlink($filename); } /** * test with named and pass args. * * @return void */ public function testCacheWithNamedAndPassedArgs() { Router::reload(); $this->Controller->cache_parsing(); $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array(1, 2), 'named' => array( 'name' => 'mark', 'ice' => 'cream' ) )); $this->Controller->cacheAction = array( 'cache_parsing' => 21600 ); $this->Controller->request->here = '/cache_test/cache_parsing/1/2/name:mark/ice:cream'; $View = new View($this->Controller); $result = $View->render('index'); $this->assertNotRegExp('/cake:nocache/', $result); $this->assertNotRegExp('/php echo/', $result); $filename = CACHE . 'views' . DS . 'cache_test_cache_parsing_1_2_name_mark_ice_cream.php'; $this->assertTrue(file_exists($filename)); unlink($filename); } /** * Test that query string parameters are included in the cache filename. * * @return void */ public function testCacheWithQueryStringParams() { Router::reload(); $this->Controller->cache_parsing(); $this->Controller->request->addParams(array( 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array(), 'named' => array() )); $this->Controller->request->query = array('q' => 'cakephp'); $this->Controller->cacheAction = array( 'cache_parsing' => 21600 ); $this->Controller->request->here = '/cache_test/cache_parsing'; $View = new View($this->Controller); $result = $View->render('index'); $this->assertNotRegExp('/cake:nocache/', $result); $this->assertNotRegExp('/php echo/', $result); $filename = CACHE . 'views' . DS . 'cache_test_cache_parsing_q_cakephp.php'; $this->assertTrue(file_exists($filename), 'Missing cache file ' . $filename); unlink($filename); } /** * test that custom routes are respected when generating cache files. * * @return void */ public function testCacheWithCustomRoutes() { Router::reload(); Router::connect('/:lang/:controller/:action/*', array(), array('lang' => '[a-z]{3}')); $this->Controller->cache_parsing(); $this->Controller->request->addParams(array( 'lang' => 'en', 'controller' => 'cache_test', 'action' => 'cache_parsing', 'pass' => array(), 'named' => array() )); $this->Controller->cacheAction = array( 'cache_parsing' => 21600 ); $this->Controller->request->here = '/en/cache_test/cache_parsing'; $this->Controller->action = 'cache_parsing'; $View = new View($this->Controller); $result = $View->render('index'); $this->assertNotRegExp('/cake:nocache/', $result); $this->assertNotRegExp('/php echo/', $result); $filename = CACHE . 'views' . DS . 'en_cache_test_cache_parsing.php'; $this->assertTrue(file_exists($filename)); unlink($filename); } /** * test ControllerName contains AppName * * This test verifies view cache is created correctly when the app name is contained in part of the controller name. * (webapp Name) base name is 'cache' controller is 'cacheTest' action is 'cache_name' * apps URL would look something like http://localhost/cache/cacheTest/cache_name * * @return void */ public function testCacheBaseNameControllerName() { $this->Controller->cache_parsing(); $this->Controller->cacheAction = array( 'cache_name' => 21600 ); $this->Controller->params = array( 'controller' => 'cacheTest', 'action' => 'cache_name', 'pass' => array(), 'named' => array() ); $this->Controller->here = '/cache/cacheTest/cache_name'; $this->Controller->action = 'cache_name'; $this->Controller->base = '/cache'; $View = new View($this->Controller); $result = $View->render('index'); $this->assertNotRegExp('/cake:nocache/', $result); $this->assertNotRegExp('/php echo/', $result); $filename = CACHE . 'views' . DS . 'cache_cachetest_cache_name.php'; $this->assertTrue(file_exists($filename)); unlink($filename); } /** * test that afterRender checks the conditions correctly. * * @return void */ public function testAfterRenderConditions() { Configure::write('Cache.check', true); $View = new View($this->Controller); $View->cacheAction = '+1 day'; $View->output = 'test'; $Cache = $this->getMock('CacheHelper', array('_parseContent'), array($View)); $Cache->expects($this->once()) ->method('_parseContent') ->with('posts/index', 'content') ->will($this->returnValue('')); $Cache->afterRenderFile('posts/index', 'content'); Configure::write('Cache.check', false); $Cache->afterRender('posts/index'); Configure::write('Cache.check', true); $View->cacheAction = false; $Cache->afterRender('posts/index'); } /** * test that afterRender checks the conditions correctly. * * @return void */ public function testAfterLayoutConditions() { Configure::write('Cache.check', true); $View = new View($this->Controller); $View->cacheAction = '+1 day'; $View->output = 'test'; $Cache = $this->getMock('CacheHelper', array('cache'), array($View)); $Cache->expects($this->once()) ->method('cache') ->with('posts/index', $View->output) ->will($this->returnValue('')); $Cache->afterLayout('posts/index'); Configure::write('Cache.check', false); $Cache->afterLayout('posts/index'); Configure::write('Cache.check', true); $View->cacheAction = false; $Cache->afterLayout('posts/index'); } /** * testCacheEmptySections method * * This test must be uncommented/fixed in next release (1.2+) * * @return void */ public function testCacheEmptySections() { $this->Controller->cache_parsing(); $this->Controller->params = array( 'controller' => 'cacheTest', 'action' => 'cache_empty_sections', 'pass' => array(), 'named' => array() ); $this->Controller->cacheAction = array('cache_empty_sections' => 21600); $this->Controller->here = '/cacheTest/cache_empty_sections'; $this->Controller->action = 'cache_empty_sections'; $this->Controller->layout = 'cache_empty_sections'; $this->Controller->viewPath = 'Posts'; $View = new View($this->Controller); $result = $View->render('cache_empty_sections'); $this->assertNotRegExp('/nocache/', $result); $this->assertNotRegExp('/php echo/', $result); $this->assertRegExp( '@\s*\s*' . '\s*' . 'View Content\s*' . 'cached count is: 3\s*' . '@', $result); $filename = CACHE . 'views' . DS . 'cachetest_cache_empty_sections.php'; $this->assertTrue(file_exists($filename)); $contents = file_get_contents($filename); $this->assertNotRegExp('/nocache/', $contents); $this->assertRegExp( '@\s*Posts\s*' . '<\?php \$x \= 1; \?>\s*' . '\s*' . '\s*' . '<\?php \$x\+\+; \?>\s*' . '<\?php \$x\+\+; \?>\s*' . 'View Content\s*' . '<\?php \$y = 1; \?>\s*' . '<\?php echo \'cached count is: \' . \$x; \?>\s*' . '@', $contents); unlink($filename); } } cakephp-2.8.0/lib/Cake/Test/Case/View/Helper/FlashHelperTest.php000066400000000000000000000075761265552240500242630ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.View.Helper * @since CakePHP(tm) v 2.7.0-dev * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('FlashHelper', 'View/Helper'); App::uses('View', 'View'); App::uses('CakePlugin', 'Core'); /** * FlashHelperTest class * * @package Cake.Test.Case.View.Helper */ class FlashHelperTest extends CakeTestCase { /** * setupBeforeClass method * * @return void */ public static function setupBeforeClass() { App::build(array( 'View' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS) )); } /** * setUp method * * @return void */ public function setUp() { parent::setUp(); $controller = null; $this->View = new View($controller); $this->Flash = new FlashHelper($this->View); if (!CakeSession::started()) { CakeSession::start(); } CakeSession::write(array( 'Message' => array( 'flash' => array( 'key' => 'flash', 'message' => 'This is a calling', 'element' => 'Flash/default', 'params' => array() ), 'notification' => array( 'key' => 'notification', 'message' => 'Broadcast message testing', 'element' => 'flash_helper', 'params' => array( 'title' => 'Notice!', 'name' => 'Alert!' ) ), 'classy' => array( 'key' => 'classy', 'message' => 'Recorded', 'element' => 'flash_classy', 'params' => array() ) ) )); } /** * tearDown method * * @return void */ public function tearDown() { parent::tearDown(); unset($this->View, $this->Flash); CakeSession::destroy(); } /** * testFlash method * * @return void */ public function testFlash() { $result = $this->Flash->render(); $expected = '
This is a calling
'; $this->assertContains($expected, $result); $expected = '
Recorded
'; $result = $this->Flash->render('classy'); $this->assertContains($expected, $result); $result = $this->Flash->render('notification'); $expected = "
\n\t

Alert!

\n\t

Notice!

\n\t

Broadcast message testing

\n
"; $this->assertContains($expected, $result); $this->assertNull($this->Flash->render('non-existent')); } /** * testFlashThrowsException * * @expectedException UnexpectedValueException */ public function testFlashThrowsException() { CakeSession::write('Message.foo', 'bar'); $this->Flash->render('foo'); } /** * test setting the element from the attrs. * * @return void */ public function testFlashElementInAttrs() { $result = $this->Flash->render('notification', array( 'element' => 'flash_helper', 'params' => array('title' => 'Alert!', 'name' => 'Notice!') )); $expected = "
\n\t

Notice!

\n\t

Alert!

\n\t

Broadcast message testing

\n
"; $this->assertContains($expected, $result); } /** * test using elements in plugins. * * @return void */ public function testFlashWithPluginElement() { App::build(array( 'Plugin' => array(CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS) )); CakePlugin::load('TestPlugin'); $result = $this->Flash->render('flash', array('element' => 'TestPlugin.plugin_element')); $expected = 'this is the plugin element'; $this->assertContains($expected, $result); } } cakephp-2.8.0/lib/Cake/Test/Case/View/Helper/FormHelperTest.php000066400000000000000000012222671265552240500241260ustar00rootroot00000000000000 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * * Licensed under The MIT License * For full copyright and license information, please see the LICENSE.txt * Redistributions of files must retain the above copyright notice * * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests * @package Cake.Test.Case.View.Helper * @since CakePHP(tm) v 1.2.0.4206 * @license http://www.opensource.org/licenses/mit-license.php MIT License */ App::uses('ClassRegistry', 'Utility'); App::uses('Controller', 'Controller'); App::uses('View', 'View'); App::uses('Model', 'Model'); App::uses('Security', 'Utility'); App::uses('CakeRequest', 'Network'); App::uses('HtmlHelper', 'View/Helper'); App::uses('FormHelper', 'View/Helper'); App::uses('Router', 'Routing'); /** * ContactTestController class * * @package Cake.Test.Case.View.Helper */ class ContactTestController extends Controller { /** * uses property * * @var mixed */ public $uses = null; } /** * Contact class * * @package Cake.Test.Case.View.Helper */ class Contact extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; /** * Default schema * * @var array */ protected $_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'email' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'phone' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'password' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'published' => array('type' => 'date', 'null' => true, 'default' => null, 'length' => null), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null), 'age' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => null) ); /** * validate property * * @var array */ public $validate = array( 'non_existing' => array(), 'idontexist' => array(), 'imrequired' => array('rule' => array('between', 5, 30), 'allowEmpty' => false), 'imrequiredonupdate' => array('notBlank' => array('rule' => 'alphaNumeric', 'on' => 'update')), 'imrequiredoncreate' => array('required' => array('rule' => 'alphaNumeric', 'on' => 'create')), 'imrequiredonboth' => array( 'required' => array('rule' => 'alphaNumeric'), ), 'string_required' => 'notBlank', 'imalsorequired' => array('rule' => 'alphaNumeric', 'allowEmpty' => false), 'imrequiredtoo' => array('rule' => 'notBlank'), 'required_one' => array('required' => array('rule' => array('notBlank'))), 'imnotrequired' => array('required' => false, 'rule' => 'alphaNumeric', 'allowEmpty' => true), 'imalsonotrequired' => array( 'alpha' => array('rule' => 'alphaNumeric', 'allowEmpty' => true), 'between' => array('rule' => array('between', 5, 30)), ), 'imalsonotrequired2' => array( 'alpha' => array('rule' => 'alphaNumeric', 'allowEmpty' => true), 'between' => array('rule' => array('between', 5, 30), 'allowEmpty' => true), ), 'imnotrequiredeither' => array('required' => true, 'rule' => array('between', 5, 30), 'allowEmpty' => true), 'iamrequiredalways' => array( 'email' => array('rule' => 'email'), 'rule_on_create' => array('rule' => array('maxLength', 50), 'on' => 'create'), 'rule_on_update' => array('rule' => array('between', 1, 50), 'on' => 'update'), ), 'boolean_field' => array('rule' => 'boolean') ); /** * schema method * * @return void */ public function setSchema($schema) { $this->_schema = $schema; } /** * hasAndBelongsToMany property * * @var array */ public $hasAndBelongsToMany = array('ContactTag' => array('with' => 'ContactTagsContact')); /** * hasAndBelongsToMany property * * @var array */ public $belongsTo = array('User' => array('className' => 'UserForm')); } /** * ContactTagsContact class * * @package Cake.Test.Case.View.Helper */ class ContactTagsContact extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; /** * Default schema * * @var array */ protected $_schema = array( 'contact_id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'contact_tag_id' => array( 'type' => 'integer', 'null' => '', 'default' => '', 'length' => '8' ) ); /** * schema method * * @return void */ public function setSchema($schema) { $this->_schema = $schema; } } /** * ContactNonStandardPk class * * @package Cake.Test.Case.View.Helper */ class ContactNonStandardPk extends Contact { /** * primaryKey property * * @var string */ public $primaryKey = 'pk'; /** * schema method * * @return void */ public function schema($field = false) { $this->_schema = parent::schema(); $this->_schema['pk'] = $this->_schema['id']; unset($this->_schema['id']); return $this->_schema; } } /** * ContactTag class * * @package Cake.Test.Case.View.Helper */ class ContactTag extends Model { /** * useTable property * * @var bool */ public $useTable = false; /** * schema definition * * @var array */ protected $_schema = array( 'id' => array('type' => 'integer', 'null' => false, 'default' => '', 'length' => '8'), 'name' => array('type' => 'string', 'null' => false, 'default' => '', 'length' => '255'), 'created' => array('type' => 'date', 'null' => true, 'default' => '', 'length' => ''), 'modified' => array('type' => 'datetime', 'null' => true, 'default' => '', 'length' => null) ); } /** * UserForm class * * @package Cake.Test.Case.View.Helper */ class UserForm extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; /** * hasMany property * * @var array */ public $hasMany = array( 'OpenidUrl' => array('className' => 'OpenidUrl', 'foreignKey' => 'user_form_id' )); /** * schema definition * * @var array */ protected $_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'published' => array('type' => 'date', 'null' => true, 'default' => null, 'length' => null), 'other' => array('type' => 'text', 'null' => true, 'default' => null, 'length' => null), 'stuff' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 10), 'something' => array('type' => 'string', 'null' => true, 'default' => null, 'length' => 255), 'active' => array('type' => 'boolean', 'null' => false, 'default' => false), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); } /** * OpenidUrl class * * @package Cake.Test.Case.View.Helper */ class OpenidUrl extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; /** * belongsTo property * * @var array */ public $belongsTo = array('UserForm' => array( 'className' => 'UserForm', 'foreignKey' => 'user_form_id' )); /** * validate property * * @var array */ public $validate = array('openid_not_registered' => array()); /** * schema method * * @var array */ protected $_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'user_form_id' => array( 'type' => 'user_form_id', 'null' => '', 'default' => '', 'length' => '8' ), 'url' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), ); /** * beforeValidate method * * @return void */ public function beforeValidate($options = array()) { $this->invalidate('openid_not_registered'); return true; } } /** * ValidateUser class * * @package Cake.Test.Case.View.Helper */ class ValidateUser extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; /** * hasOne property * * @var array */ public $hasOne = array('ValidateProfile' => array( 'className' => 'ValidateProfile', 'foreignKey' => 'user_id' )); /** * schema method * * @var array */ protected $_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'email' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'balance' => array('type' => 'float', 'null' => false, 'length' => '5,2'), 'cost_decimal' => array('type' => 'decimal', 'null' => false, 'length' => '6,3'), 'null_decimal' => array('type' => 'decimal', 'null' => false, 'length' => null), 'ratio' => array('type' => 'decimal', 'null' => false, 'length' => '10,6'), 'population' => array('type' => 'decimal', 'null' => false, 'length' => '15,0'), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); /** * beforeValidate method * * @return void */ public function beforeValidate($options = array()) { $this->invalidate('email'); return false; } } /** * ValidateProfile class * * @package Cake.Test.Case.View.Helper */ class ValidateProfile extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; /** * schema property * * @var array */ protected $_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'user_id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'full_name' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'city' => array('type' => 'string', 'null' => '', 'default' => '', 'length' => '255'), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); /** * hasOne property * * @var array */ public $hasOne = array('ValidateItem' => array( 'className' => 'ValidateItem', 'foreignKey' => 'profile_id' )); /** * belongsTo property * * @var array */ public $belongsTo = array('ValidateUser' => array( 'className' => 'ValidateUser', 'foreignKey' => 'user_id' )); /** * beforeValidate method * * @return void */ public function beforeValidate($options = array()) { $this->invalidate('full_name'); $this->invalidate('city'); return false; } } /** * ValidateItem class * * @package Cake.Test.Case.View.Helper */ class ValidateItem extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; /** * schema property * * @var array */ protected $_schema = array( 'id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'profile_id' => array('type' => 'integer', 'null' => '', 'default' => '', 'length' => '8'), 'name' => array('type' => 'text', 'null' => '', 'default' => '', 'length' => '255'), 'description' => array( 'type' => 'string', 'null' => '', 'default' => '', 'length' => '255' ), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) ); /** * belongsTo property * * @var array */ public $belongsTo = array('ValidateProfile' => array('foreignKey' => 'profile_id')); /** * beforeValidate method * * @return void */ public function beforeValidate($options = array()) { $this->invalidate('description'); return false; } } /** * TestMail class * * @package Cake.Test.Case.View.Helper */ class TestMail extends CakeTestModel { /** * useTable property * * @var bool */ public $useTable = false; } /** * FormHelperTest class * * @package Cake.Test.Case.View.Helper * @property FormHelper $Form */ class FormHelperTest extends CakeTestCase { /** * Fixtures to be used * * @var array */ public $fixtures = array('core.post'); /** * Do not load the fixtures by default * * @var bool */ public $autoFixtures = false; /** * setUp method * * @return void */ public function setUp() { parent::setUp(); Configure::write('Config.language', 'eng'); Configure::write('App.base', ''); Configure::delete('Asset'); $this->Controller = new ContactTestController(); $this->View = new View($this->Controller); $this->Form = new FormHelper($this->View); $this->Form->Html = new HtmlHelper($this->View); $this->Form->request = new CakeRequest('contacts/add', false); $this->Form->request->here = '/contacts/add'; $this->Form->request['action'] = 'add'; $this->Form->request->webroot = ''; $this->Form->request->base = ''; ClassRegistry::addObject('Contact', new Contact()); ClassRegistry::addObject('ContactNonStandardPk', new ContactNonStandardPk()); ClassRegistry::addObject('OpenidUrl', new OpenidUrl()); ClassRegistry::addObject('User', new UserForm()); ClassRegistry::addObject('ValidateItem', new ValidateItem()); ClassRegistry::addObject('ValidateUser', new ValidateUser()); ClassRegistry::addObject('ValidateProfile', new ValidateProfile()); $this->oldSalt = Configure::read('Security.salt'); $this->dateRegex = array( 'daysRegex' => 'preg:/(?:', 'selectoption' => '', 'selectend' => '', 'optiongroup' => '', 'optiongroupend' => '', 'checkboxmultiplestart' => '', 'checkboxmultipleend' => '', 'password' => '', 'file' => '', 'file_no_model' => '', 'submit' => '', 'submitimage' => '', 'button' => '%s', 'image' => '', 'tableheader' => '%s', 'tableheaderrow' => '%s', 'tablecell' => '%s', 'tablerow' => '%s', 'block' => '%s
', 'blockstart' => '', 'blockend' => '
', 'hiddenblock' => '
%s
', 'tag' => '<%s%s>%s', 'tagstart' => '<%s%s>', 'tagend' => '', 'tagselfclosing' => '<%s%s/>', 'para' => '%s

', 'parastart' => '', 'label' => '', 'fieldset' => '%s', 'fieldsetstart' => '
%s', 'fieldsetend' => '
', 'legend' => '%s', 'css' => '', 'style' => '', 'charset' => '', 'ul' => '%s', 'ol' => '%s', 'li' => '%s', 'error' => '%s', 'javascriptblock' => '%s', 'javascriptstart' => '', 'javascriptend' => '' ); /** * Breadcrumbs. * * @var array */ protected $_crumbs = array(); /** * Names of script & css files that have been included once * * @var array */ protected $_includedAssets = array(); /** * Options for the currently opened script block buffer if any. * * @var array */ protected $_scriptBlockOptions = array(); /** * Document type definitions * * @var array */ protected $_docTypes = array( 'html4-strict' => '', 'html4-trans' => '', 'html4-frame' => '', 'html5' => '', 'xhtml-strict' => '', 'xhtml-trans' => '', 'xhtml-frame' => '', 'xhtml11' => '' ); /** * Constructor * * ### Settings * * - `configFile` A file containing an array of tags you wish to redefine. * * ### Customizing tag sets * * Using the `configFile` option you can redefine the tag HtmlHelper will use. * The file named should be compatible with HtmlHelper::loadConfig(). * * @param View $View The View this helper is being attached to. * @param array $settings Configuration settings for the helper. */ public function __construct(View $View, $settings = array()) { parent::__construct($View, $settings); if (is_object($this->_View->response)) { $this->response = $this->_View->response; } else { $this->response = new CakeResponse(); } if (!empty($settings['configFile'])) { $this->loadConfig($settings['configFile']); } } /** * Adds a link to the breadcrumbs array. * * @param string $name Text for link * @param string $link URL for link (if empty it won't be a link) * @param string|array $options Link attributes e.g. array('id' => 'selected') * @return self * @see HtmlHelper::link() for details on $options that can be used. * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#creating-breadcrumb-trails-with-htmlhelper */ public function addCrumb($name, $link = null, $options = null) { $this->_crumbs[] = array($name, $link, $options); return $this; } /** * Returns a doctype string. * * Possible doctypes: * * - html4-strict: HTML4 Strict. * - html4-trans: HTML4 Transitional. * - html4-frame: HTML4 Frameset. * - html5: HTML5. Default value. * - xhtml-strict: XHTML1 Strict. * - xhtml-trans: XHTML1 Transitional. * - xhtml-frame: XHTML1 Frameset. * - xhtml11: XHTML1.1. * * @param string $type Doctype to use. * @return string|null Doctype string * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::docType */ public function docType($type = 'html5') { if (isset($this->_docTypes[$type])) { return $this->_docTypes[$type]; } return null; } /** * Creates a link to an external resource and handles basic meta tags * * Create a meta tag that is output inline: * * `$this->Html->meta('icon', 'favicon.ico'); * * Append the meta tag to `$scripts_for_layout`: * * `$this->Html->meta('description', 'A great page', array('inline' => false));` * * Append the meta tag to custom view block: * * `$this->Html->meta('description', 'A great page', array('block' => 'metaTags'));` * * ### Options * * - `inline` Whether or not the link element should be output inline. Set to false to * have the meta tag included in `$scripts_for_layout`, and appended to the 'meta' view block. * - `block` Choose a custom block to append the meta tag to. Using this option * will override the inline option. * * @param string $type The title of the external resource * @param string|array $url The address of the external resource or string for content attribute * @param array $options Other attributes for the generated tag. If the type attribute is html, * rss, atom, or icon, the mime-type is returned. * @return string A completed `` element. * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::meta */ public function meta($type, $url = null, $options = array()) { $options += array('inline' => true, 'block' => null); if (!$options['inline'] && empty($options['block'])) { $options['block'] = __FUNCTION__; } unset($options['inline']); if (!is_array($type)) { $types = array( 'rss' => array('type' => 'application/rss+xml', 'rel' => 'alternate', 'title' => $type, 'link' => $url), 'atom' => array('type' => 'application/atom+xml', 'title' => $type, 'link' => $url), 'icon' => array('type' => 'image/x-icon', 'rel' => 'icon', 'link' => $url), 'keywords' => array('name' => 'keywords', 'content' => $url), 'description' => array('name' => 'description', 'content' => $url), ); if ($type === 'icon' && $url === null) { $types['icon']['link'] = 'favicon.ico'; } if (isset($types[$type])) { $type = $types[$type]; } elseif (!isset($options['type']) && $url !== null) { if (is_array($url) && isset($url['ext'])) { $type = $types[$url['ext']]; } else { $type = $types['rss']; } } elseif (isset($options['type']) && isset($types[$options['type']])) { $type = $types[$options['type']]; unset($options['type']); } else { $type = array(); } } $options += $type; $out = null; if (isset($options['link'])) { $options['link'] = $this->assetUrl($options['link']); if (isset($options['rel']) && $options['rel'] === 'icon') { $out = sprintf($this->_tags['metalink'], $options['link'], $this->_parseAttributes($options, array('block', 'link'))); $options['rel'] = 'shortcut icon'; } $out .= sprintf($this->_tags['metalink'], $options['link'], $this->_parseAttributes($options, array('block', 'link'))); } else { $out = sprintf($this->_tags['meta'], $this->_parseAttributes($options, array('block', 'type'))); } if (empty($options['block'])) { return $out; } $this->_View->append($options['block'], $out); } /** * Returns a charset META-tag. * * @param string $charset The character set to be used in the meta tag. If empty, * The App.encoding value will be used. Example: "utf-8". * @return string A meta tag containing the specified character set. * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::charset */ public function charset($charset = null) { if (empty($charset)) { $charset = strtolower(Configure::read('App.encoding')); } return sprintf($this->_tags['charset'], (!empty($charset) ? $charset : 'utf-8')); } /** * Creates an HTML link. * * If $url starts with "http://" this is treated as an external link. Else, * it is treated as a path to controller/action and parsed with the * HtmlHelper::url() method. * * If the $url is empty, $title is used instead. * * ### Options * * - `escape` Set to false to disable escaping of title and attributes. * - `escapeTitle` Set to false to disable escaping of title. (Takes precedence over value of `escape`) * - `confirm` JavaScript confirmation message. * * @param string $title The content to be wrapped by tags. * @param string|array $url Cake-relative URL or array of URL parameters, or external URL (starts with http://) * @param array $options Array of options and HTML attributes. * @param string $confirmMessage JavaScript confirmation message. This * argument is deprecated as of 2.6. Use `confirm` key in $options instead. * @return string An `` element. * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/html.html#HtmlHelper::link */ public function link($title, $url = null, $options = array(), $confirmMessage = false) { $escapeTitle = true; if ($url !== null) { $url = $this->url($url); } else { $url = $this->url($title); $title = htmlspecialchars_decode($url, ENT_QUOTES); $title = h(urldecode($title)); $escapeTitle = false; } if (isset($options['escapeTitle'])) { $escapeTitle = $options['escapeTitle']; unset($options['escapeTitle']); } elseif (isset($options['escape'])) { $escapeTitle = $options['escape']; } if ($escapeTitle === true) { $title = h($title); } elseif (is_string($escapeTitle)) { $title = htmlentities($title, ENT_QUOTES, $escapeTitle); } if (!empty($options['confirm'])) { $confirmMessage = $options['confirm']; unset($options['confirm']); } if ($confirmMessage) { $options['onclick'] = $this->_confirm($confirmMessage, 'return true;', 'return false;', $options); } elseif (isset($options['default']) && !$options['default']) { if (isset($options['onclick'])) { $options['onclick'] .= ' '; } else { $options['onclick'] = ''; } $options['onclick'] .= 'event.returnValue = false; return false;'; unset($options['default']); } return sprintf($this->_tags['link'], $url, $this->_parseAttributes($options), $title); } /** * Creates a link element for CSS stylesheets. * * ### Usage * * Include one CSS file: * * `echo $this->Html->css('styles.css');` * * Include multiple CSS files: * * `echo $this->Html->css(array('one.css', 'two.css'));` * * Add the stylesheet to the `$scripts_for_layout` layout var: * * `$this->Html->css('styles.css', array('inline' => false));` * * Add the stylesheet to a custom block: * * `$this->Html->css('styles.css', array('block' => 'layoutCss'));` * * ### Options * * - `inline` If set to false, the generated tag will be appended to the 'css' block, * and included in the `$scripts_for_layout` layout variable. Defaults to true. * - `once` Whether or not the css file should be checked for uniqueness. If true css * files will only be included once, use false to allow the same * css to be included more than once per request. * - `block` Set the name of the block link/style tag will be appended to. * This overrides the `inline` option. * - `plugin` False value will prevent parsing path as a plugin * - `rel` Defaults to 'stylesheet'. If equal to 'import' the stylesheet will be imported. * - `fullBase` If true the URL will get a full address for the css file. * * @param string|array $path The name of a CSS style sheet or an array containing names of * CSS stylesheets. If `$path` is prefixed with '/', the path will be relative to the webroot * of your application. Otherwise, the path will be relative to your CSS path, usually webroot/css. * @param array $options Array of options and HTML arguments. * @return string CSS or