From 5da9751f08b8b498dc5d87b2ce14ea59b9c006b2 Mon Sep 17 00:00:00 2001 From: TSURU Date: Thu, 2 Oct 2025 20:24:40 +0900 Subject: [PATCH 1/9] refactor: Simplify dispatcher files and require Composer installation - Removed manual CAKE_CORE_INCLUDE_PATH detection from dispatcher files - Removed include_path manipulation logic (Composer autoload handles this) - Removed legacy app/Vendor/cakephp/cakephp path detection - Added clear error messages when Composer vendors directory or autoload.php is missing - Added clear error message when CakePHP core is not installed via Composer - Retained PHP built-in server support for development convenience - Updated both app/ and skel/ template files for consistency Breaking Change: Non-Composer installation is no longer supported. Projects must use Composer for dependency management. Migration: Copy updated dispatcher files from vendors/friendsofcake2/cakephp/lib/Cake/Console/Templates/skel/ to your application (webroot/index.php, webroot/test.php, Console/cake). Updated documentation: - Added CHANGELOG entry for dispatcher improvements - Added README installation instructions for copying dispatcher files - Added Composer-only requirement to Breaking Changes section --- .htaccess | 8 -- CHANGELOG.md | 14 +++ README.md | 67 ++++++++++---- app/.htaccess | 8 -- app/Console/cake | 89 +++++++++++-------- app/Console/cake.bat | 31 ------- app/Console/cake.php | 47 ---------- app/index.php | 17 ---- app/webroot/index.php | 59 ++++++------ app/webroot/test.php | 58 ++++++------ composer.json | 10 +-- index.php | 41 --------- lib/Cake/Console/Command/Task/ProjectTask.php | 10 +-- lib/Cake/Console/Templates/skel/.htaccess | 5 -- lib/Cake/Console/Templates/skel/Console/cake | 88 ++++++++++-------- .../Console/Templates/skel/Console/cake.bat | 30 ------- .../Console/Templates/skel/Console/cake.php | 48 ---------- lib/Cake/Console/Templates/skel/index.php | 8 -- .../Console/Templates/skel/webroot/index.php | 61 ++++++------- .../Console/Templates/skel/webroot/test.php | 58 ++++++------ lib/Cake/Console/cake | 77 ++++++++-------- lib/Cake/Console/cake.bat | 28 ------ lib/Cake/Console/cake.php | 53 ----------- .../Console/Command/Task/ProjectTaskTest.php | 2 +- lib/Cake/Test/bootstrap/cake_dot_php.php | 35 +++----- lib/Cake/bootstrap.php | 23 ++--- 26 files changed, 344 insertions(+), 631 deletions(-) delete mode 100644 .htaccess delete mode 100644 app/.htaccess delete mode 100644 app/Console/cake.bat delete mode 100644 app/Console/cake.php delete mode 100644 app/index.php delete mode 100644 index.php delete mode 100644 lib/Cake/Console/Templates/skel/.htaccess delete mode 100644 lib/Cake/Console/Templates/skel/Console/cake.bat delete mode 100644 lib/Cake/Console/Templates/skel/Console/cake.php delete mode 100644 lib/Cake/Console/Templates/skel/index.php delete mode 100644 lib/Cake/Console/cake.bat delete mode 100644 lib/Cake/Console/cake.php diff --git a/.htaccess b/.htaccess deleted file mode 100644 index f13591f2c8..0000000000 --- a/.htaccess +++ /dev/null @@ -1,8 +0,0 @@ - - RewriteEngine on - # Uncomment if you have a .well-known directory in the root folder, e.g. for the Let's Encrypt challenge - # https://tools.ietf.org/html/rfc5785 - #RewriteRule ^(\.well-known/.*)$ $1 [L] - RewriteRule ^$ app/webroot/ [L] - RewriteRule (.*) app/webroot/$1 [L] - \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 4320c1fbcb..2f7f052821 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,20 @@ ## Unreleased +### Dispatcher Improvements + +- **Simplified Dispatcher Entry Points**: Streamlined autoload handling in dispatcher files + - Removed manual `CAKE_CORE_INCLUDE_PATH` detection from dispatcher files (set automatically in bootstrap.php) + - Removed `include_path` manipulation logic (Composer autoload handles this) + - Removed legacy `app/Vendor/cakephp/cakephp` path detection + - Added clear error messages when Composer vendors directory or autoload.php is missing + - Added clear error messages when CakePHP core is not installed via Composer + - **Breaking Change**: Projects must use Composer for installation (non-Composer installation no longer supported) + - **Migration**: If upgrading, copy updated dispatcher files from `vendors/friendsofcake2/cakephp/lib/Cake/Console/Templates/skel/` to your project: + - `skel/webroot/index.php` → `app/webroot/index.php` + - `skel/webroot/test.php` → `app/webroot/test.php` + - `skel/Console/cake` → `app/Console/cake` + ### PHP Support - **PHP 8.5 Support**: Added PHP 8.5 to CI testing matrix ([PR #12](https://github.com/friendsofcake2/cakephp/pull/12)) diff --git a/README.md b/README.md index de7a96c4a5..86e5b9734e 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,9 @@ The original CakePHP 2.x branch [reached End of Life in June 2021](https://baker ## Installation +> [!IMPORTANT] +> This fork requires Composer for installation. Manual installation is not supported. + Install via Composer: ```json @@ -59,9 +62,22 @@ Then run: composer update ``` +After installation, copy dispatcher files from the package to your application: + +```bash +# Copy web dispatcher files +cp vendors/friendsofcake2/cakephp/lib/Cake/Console/Templates/skel/webroot/index.php app/webroot/index.php +cp vendors/friendsofcake2/cakephp/lib/Cake/Console/Templates/skel/webroot/test.php app/webroot/test.php + +# Copy console dispatcher +cp vendors/friendsofcake2/cakephp/lib/Cake/Console/Templates/skel/Console/cake app/Console/cake +chmod +x app/Console/cake +``` + > [!NOTE] -> This package uses Composer's `replace` directive to replace `cakephp/cakephp`. -> This ensures that all plugins and packages that depend on `cakephp/cakephp:^2.x` will continue to work correctly with this fork. +> - This package uses Composer's `replace` directive to replace `cakephp/cakephp`. +> - This ensures that all plugins and packages that depend on `cakephp/cakephp:^2.x` will continue to work correctly with this fork. +> - Dispatcher files provide better error messages and simplified autoload handling. ## Security @@ -97,7 +113,26 @@ Before migrating to this fork, ensure: ### Breaking Changes -#### 1. Cache Engines Removed ([PR #4](https://github.com/friendsofcake2/cakephp/pull/4)) +#### 1. Composer-Only Installation Required + +**Breaking Change:** +- **Non-Composer installation is no longer supported** +- Dispatcher files (`app/webroot/index.php`, `app/webroot/test.php`, `app/Console/cake`) require Composer autoload +- Removed manual `CAKE_CORE_INCLUDE_PATH` detection from dispatcher files +- Removed `include_path` manipulation logic +- Removed legacy `app/Vendor/cakephp/cakephp` path detection + +**Migration:** +1. Ensure you're using Composer for dependency management +2. Copy updated dispatcher files from `vendors/friendsofcake2/cakephp/lib/Cake/Console/Templates/skel/` to your application: + ```bash + cp vendors/friendsofcake2/cakephp/lib/Cake/Console/Templates/skel/webroot/index.php app/webroot/index.php + cp vendors/friendsofcake2/cakephp/lib/Cake/Console/Templates/skel/webroot/test.php app/webroot/test.php + cp vendors/friendsofcake2/cakephp/lib/Cake/Console/Templates/skel/Console/cake app/Console/cake + ``` +3. Run `composer install` to ensure all dependencies are properly loaded + +#### 2. Cache Engines Removed ([PR #4](https://github.com/friendsofcake2/cakephp/pull/4)) **Breaking Change:** - **Xcache** support has been removed (not compatible with PHP 7.0+) @@ -106,7 +141,7 @@ Before migrating to this fork, ensure: **Migration:** - If using these cache engines, migrate to Redis, Memcached, or APCu -#### 2. Database Driver Methods Added ([PR #3](https://github.com/friendsofcake2/cakephp/pull/3)) +#### 3. Database Driver Methods Added ([PR #3](https://github.com/friendsofcake2/cakephp/pull/3)) **Breaking Change:** - New methods added to database drivers (may cause issues if you have custom driver implementations) @@ -123,7 +158,7 @@ Before migrating to this fork, ensure: **Migration:** - If you have custom database drivers extending these classes, implement these methods -#### 3. Database Charset Configuration Changes ([PR #11](https://github.com/friendsofcake2/cakephp/pull/11)) +#### 4. Database Charset Configuration Changes ([PR #11](https://github.com/friendsofcake2/cakephp/pull/11)) **Breaking Change:** - Character set configuration moved from `SET NAMES` to DSN connection options @@ -136,11 +171,11 @@ Before migrating to this fork, ensure: - `setEncoding()` methods still work for runtime changes - More efficient connection setup with charset in DSN -#### 4. SQL Server Driver Updates ([PR #9](https://github.com/friendsofcake2/cakephp/pull/9)) +#### 5. SQL Server Driver Updates ([PR #9](https://github.com/friendsofcake2/cakephp/pull/9)) **Breaking Changes:** -**4.1 Configuration Format** +**5.1 Configuration Format** - **Schema-based configuration**: Use schema mapping instead of multiple databases ```php // Old approach (still works) @@ -165,7 +200,7 @@ Before migrating to this fork, ensure: - **Port configuration**: Specify port separately (automatically appended to server) -**4.2 Method Signature Changes** +**5.2 Method Signature Changes** - `describe($model): array` - Now has explicit return type - `insertMulti()` - Now returns `bool` instead of `void` @@ -174,7 +209,7 @@ Before migrating to this fork, ensure: - Move SSL/TLS options to `options` array if using inline DSN - If extending Sqlserver class, update method signatures to match -#### 5. Mail Function Updates ([PR #10](https://github.com/friendsofcake2/cakephp/pull/10)) +#### 6. Mail Function Updates ([PR #10](https://github.com/friendsofcake2/cakephp/pull/10)) **Breaking Change:** - `MailTransport::_mail()` method signature changed with strict types @@ -185,7 +220,7 @@ Before migrating to this fork, ensure: - No action required unless you've extended `MailTransport` class - If extending, update method signature to match strict types -#### 6. CSRF Token Security Enhancement ([PR #5](https://github.com/friendsofcake2/cakephp/pull/5)) +#### 7. CSRF Token Security Enhancement ([PR #5](https://github.com/friendsofcake2/cakephp/pull/5)) **Breaking Change:** - New CSRF tokens use HMAC-SHA1 signatures (prevents CVE-2020-15400) @@ -196,7 +231,7 @@ Before migrating to this fork, ensure: - Existing tokens continue to work - New tokens generated with enhanced security -#### 7. strftime() Replacement +#### 8. strftime() Replacement **Breaking Change:** - `strftime()` deprecated in PHP 8.1, removed in PHP 8.2 @@ -208,9 +243,9 @@ Before migrating to this fork, ensure: - Edge cases may produce slightly different output - Test date formatting in your application -#### 8. Development Tools Updates +#### 9. Development Tools Updates -**8.1 PHP CodeSniffer ([PR #8](https://github.com/friendsofcake2/cakephp/pull/8))** +**9.1 PHP CodeSniffer ([PR #8](https://github.com/friendsofcake2/cakephp/pull/8))** - Updated from 1.0.0 to 5.3 - Applied automatic formatting fixes @@ -218,14 +253,14 @@ Before migrating to this fork, ensure: - Development-time change only - Update `phpcs.xml` if you have custom coding standards -**8.2 PHPUnit Compatibility** +**9.2 PHPUnit Compatibility** - Framework tests migrated to PHPUnit 9.6 - All deprecated PHPUnit features fixed **Migration:** - Update your tests if using deprecated PHPUnit features -#### 9. PHP 8 Syntax Modernization ([PR #7](https://github.com/friendsofcake2/cakephp/pull/7)) +#### 10. PHP 8 Syntax Modernization ([PR #7](https://github.com/friendsofcake2/cakephp/pull/7)) **Breaking Change:** - Codebase modernized to PHP 8 syntax @@ -241,7 +276,7 @@ Before migrating to this fork, ensure: **Migration:** - **No action required** - syntax changes only, no functionality changes -#### 10. CookieComponent 'cipher' Type - Insecure and Should Be Replaced +#### 11. CookieComponent 'cipher' Type - Insecure and Should Be Replaced **Breaking Change:** - The default `CookieComponent` encryption type `'cipher'` is horribly insecure diff --git a/app/.htaccess b/app/.htaccess deleted file mode 100644 index f7ab0332c3..0000000000 --- a/app/.htaccess +++ /dev/null @@ -1,8 +0,0 @@ - - RewriteEngine on - # Uncomment if you have a .well-known directory in the app folder, e.g. for the Let's Encrypt challenge - # https://tools.ietf.org/html/rfc5785 - #RewriteRule ^(\.well-known/.*)$ $1 [L] - RewriteRule ^$ webroot/ [L] - RewriteRule (.*) webroot/$1 [L] - \ No newline at end of file diff --git a/app/Console/cake b/app/Console/cake index fee8e35a31..305dba76bd 100755 --- a/app/Console/cake +++ b/app/Console/cake @@ -1,41 +1,54 @@ -#!/usr/bin/env bash -################################################################################ -# -# Bake is a shell script for running CakePHP bake script -# -# CakePHP(tm) : Rapid Development Framework (https://cakephp.org) -# Copyright (c) Cake Software Foundation, Inc. (https://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. (https://cakefoundation.org) -# @link https://cakephp.org CakePHP(tm) Project -# @package app.Console -# @since CakePHP(tm) v 1.2.0.5012 -# @license https://opensource.org/licenses/mit-license.php MIT License -# -################################################################################ - -# Canonicalize by following every symlink of the given name recursively -canonicalize() { - NAME="$1" - if [ -f "$NAME" ] - then - DIR=$(dirname -- "$NAME") - NAME=$(cd -P "$DIR" && pwd -P)/$(basename -- "$NAME") - fi - while [ -h "$NAME" ]; do - DIR=$(dirname -- "$NAME") - SYM=$(readlink "$NAME") - NAME=$(cd "$DIR" && cd $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM") - done - echo "$NAME" +#!/usr/bin/env php +consolePath($path) === true) { - $this->out(__d('cake_console', ' * app/Console/cake.php path set.')); + $this->out(__d('cake_console', ' * app/Console/cake path set.')); } else { $this->err(__d('cake_console', 'Unable to set console path for app/Console.')); $success = false; @@ -236,14 +236,14 @@ public function bake($path, $skel = null, $skip = ['empty']) /** * Generates the correct path to the CakePHP libs that are generating the project - * and points app/console/cake.php to the right place + * and points app/console/cake to the right place * * @param string $path Project path. * @return bool success */ public function consolePath($path) { - $File = new File($path . 'Console' . DS . 'cake.php'); + $File = new File($path . 'Console' . DS . 'cake'); $contents = $File->read(); if (preg_match('/(__CAKE_PATH__)/', $contents, $match)) { $root = str_starts_with(CAKE_CORE_INCLUDE_PATH, '/') ? " DS . '" : "'"; @@ -363,9 +363,9 @@ protected function _replaceCorePath($filename, $hardCode) $root = str_starts_with(CAKE_CORE_INCLUDE_PATH, '/') ? " 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'; + $composer = ROOT . DS . 'vendors' . DS . 'friendsofcake2' . DS . 'cakephp' . DS . 'lib'; if (file_exists($composer)) { - $corePath = " ROOT . DS . APP_DIR . DS . 'Vendor' . DS . 'cakephp' . DS . 'cakephp' . DS . 'lib'"; + $corePath = " ROOT . DS . 'vendors' . DS . 'friendsofcake2' . DS . 'cakephp' . DS . 'lib'"; } $result = str_replace('__CAKE_PATH__', $corePath, $contents, $count); diff --git a/lib/Cake/Console/Templates/skel/.htaccess b/lib/Cake/Console/Templates/skel/.htaccess deleted file mode 100644 index 128e7871bc..0000000000 --- a/lib/Cake/Console/Templates/skel/.htaccess +++ /dev/null @@ -1,5 +0,0 @@ - - RewriteEngine on - RewriteRule ^$ webroot/ [L] - RewriteRule (.*) webroot/$1 [L] - \ No newline at end of file diff --git a/lib/Cake/Console/Templates/skel/Console/cake b/lib/Cake/Console/Templates/skel/Console/cake index fee8e35a31..1d8b93f1a4 100644 --- a/lib/Cake/Console/Templates/skel/Console/cake +++ b/lib/Cake/Console/Templates/skel/Console/cake @@ -1,41 +1,53 @@ -#!/usr/bin/env bash -################################################################################ -# -# Bake is a shell script for running CakePHP bake script -# -# CakePHP(tm) : Rapid Development Framework (https://cakephp.org) -# Copyright (c) Cake Software Foundation, Inc. (https://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. (https://cakefoundation.org) -# @link https://cakephp.org CakePHP(tm) Project -# @package app.Console -# @since CakePHP(tm) v 1.2.0.5012 -# @license https://opensource.org/licenses/mit-license.php MIT License -# -################################################################################ - -# Canonicalize by following every symlink of the given name recursively -canonicalize() { - NAME="$1" - if [ -f "$NAME" ] - then - DIR=$(dirname -- "$NAME") - NAME=$(cd -P "$DIR" && pwd -P)/$(basename -- "$NAME") - fi - while [ -h "$NAME" ]; do - DIR=$(dirname -- "$NAME") - SYM=$(readlink "$NAME") - NAME=$(cd "$DIR" && cd $(dirname -- "$SYM") && pwd)/$(basename -- "$SYM") - done - echo "$NAME" +#!/usr/bin/env php + /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" +if (!defined('DS')) { + define('DS', DIRECTORY_SEPARATOR); } -CONSOLE=$(dirname -- "$(canonicalize "$0")") -APP=`pwd` +$rootInstall = dirname(__DIR__, 3) . DS . 'vendors' . DS . 'autoload.php'; +$composerInstall = dirname(__DIR__, 5) . DS . 'autoload.php'; -exec php -q "$CONSOLE"/cake.php -working "$APP" "$@" -exit +if (isset($GLOBALS['_composer_autoload_path'])) { + require_once $GLOBALS['_composer_autoload_path']; +} else { + if (file_exists($composerInstall)) { + require_once $composerInstall; + } elseif (file_exists($rootInstall)) { + require_once $rootInstall; + } else { + trigger_error('Composer autoload file not found. ' . + 'Please run "composer install" to generate the autoload file.', E_USER_ERROR); + } +} + +if (!include 'Cake' . DS . 'Console' . DS . 'ShellDispatcher.php') { + trigger_error('Could not locate CakePHP core files.', E_USER_ERROR); +} + +return ShellDispatcher::run($argv); diff --git a/lib/Cake/Console/cake.bat b/lib/Cake/Console/cake.bat deleted file mode 100644 index 7aa9ad78f8..0000000000 --- a/lib/Cake/Console/cake.bat +++ /dev/null @@ -1,28 +0,0 @@ -:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: -:: -:: Bake is a shell script for running CakePHP bake script -:: -:: CakePHP(tm) : Rapid Development Framework (https://cakephp.org) -:: Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) -:: -:: Licensed under The MIT License -:: Redistributions of files must retain the above copyright notice. -:: -:: @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) -:: @link https://cakephp.org CakePHP(tm) Project -:: @package Cake.Console -:: @since CakePHP(tm) v 1.2.0.5012 -:: @license https://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% diff --git a/lib/Cake/Console/cake.php b/lib/Cake/Console/cake.php deleted file mode 100644 index 7d47e4f912..0000000000 --- a/lib/Cake/Console/cake.php +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/php -q -Task->consolePath($path); $this->assertTrue($result); - $File = new File($path . 'Console' . DS . 'cake.php'); + $File = new File($path . 'Console' . DS . 'cake'); $contents = $File->read(); $this->assertDoesNotMatchRegularExpression('/__CAKE_PATH__/', $contents, 'Console path placeholder left behind.'); } diff --git a/lib/Cake/Test/bootstrap/cake_dot_php.php b/lib/Cake/Test/bootstrap/cake_dot_php.php index 69c9c28082..0660b6efea 100644 --- a/lib/Cake/Test/bootstrap/cake_dot_php.php +++ b/lib/Cake/Test/bootstrap/cake_dot_php.php @@ -1,37 +1,30 @@ Date: Thu, 2 Oct 2025 21:33:48 +0900 Subject: [PATCH 2/9] refactor: Update PHPUnit integration and code style - Simplify PHPUnit framework detection using modern TestCase class - Remove unused CakeTestRunner class and associated run() method - Update type hints from PHPUnit_Framework_* to PHPUnit\Framework\* - Add use statements for PHPUnit classes to improve code clarity - Add vendor/ paths to App::path() for better Composer compatibility - Fix trailing commas in trigger_error calls for consistency - Remove index.php from phpcs.xml scope --- app/webroot/index.php | 6 +- app/webroot/test.php | 6 +- lib/Cake/Console/Shell.php | 10 +- .../Console/Templates/skel/webroot/index.php | 6 +- .../Console/Templates/skel/webroot/test.php | 6 +- lib/Cake/Core/App.php | 2 + lib/Cake/TestSuite/CakeTestRunner.php | 139 ------------------ lib/Cake/TestSuite/CakeTestSuiteCommand.php | 78 +--------- .../TestSuite/CakeTestSuiteDispatcher.php | 36 +---- .../TestSuite/Reporter/CakeBaseReporter.php | 44 +++--- .../TestSuite/Reporter/CakeHtmlReporter.php | 20 ++- .../TestSuite/Reporter/CakeTextReporter.php | 6 +- phpcs.xml | 1 - vendors/empty | 0 14 files changed, 62 insertions(+), 298 deletions(-) delete mode 100644 lib/Cake/TestSuite/CakeTestRunner.php delete mode 100644 vendors/empty diff --git a/app/webroot/index.php b/app/webroot/index.php index 9874500ef9..2a8d25f483 100644 --- a/app/webroot/index.php +++ b/app/webroot/index.php @@ -80,7 +80,7 @@ trigger_error( 'Composer vendors directory not found at "' . VENDORS . '". ' . 'Please run "composer install" in the project root directory to install dependencies.', - E_USER_ERROR + E_USER_ERROR, ); } @@ -88,7 +88,7 @@ trigger_error( 'Composer autoload file not found at "' . VENDORS . 'autoload.php". ' . 'Please run "composer install" to generate the autoload file.', - E_USER_ERROR + E_USER_ERROR, ); } @@ -98,7 +98,7 @@ trigger_error( 'CakePHP core could not be found. ' . 'Please run "composer require friendsofcake2/cakephp" to install CakePHP core.', - E_USER_ERROR + E_USER_ERROR, ); } diff --git a/app/webroot/test.php b/app/webroot/test.php index 0b665974ae..b093a802a1 100644 --- a/app/webroot/test.php +++ b/app/webroot/test.php @@ -75,7 +75,7 @@ trigger_error( 'Composer vendors directory not found at "' . VENDORS . '". ' . 'Please run "composer install" in the project root directory to install dependencies.', - E_USER_ERROR + E_USER_ERROR, ); } @@ -83,7 +83,7 @@ trigger_error( 'Composer autoload file not found at "' . VENDORS . 'autoload.php". ' . 'Please run "composer install" to generate the autoload file.', - E_USER_ERROR + E_USER_ERROR, ); } @@ -93,7 +93,7 @@ trigger_error( 'CakePHP core could not be found. ' . 'Please run "composer require friendsofcake2/cakephp" to install CakePHP core.', - E_USER_ERROR + E_USER_ERROR, ); } diff --git a/lib/Cake/Console/Shell.php b/lib/Cake/Console/Shell.php index b8b26478af..da8a8d146b 100644 --- a/lib/Cake/Console/Shell.php +++ b/lib/Cake/Console/Shell.php @@ -15,6 +15,8 @@ * @license https://opensource.org/licenses/mit-license.php MIT License */ +use PHPUnit\Framework\TestCase; + App::uses('TaskCollection', 'Console'); App::uses('ConsoleOutput', 'Console'); App::uses('ConsoleInput', 'Console'); @@ -874,13 +876,7 @@ public function helper($name) */ 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', ['file' => 'PHPUnit' . DS . 'Autoload.php'])) { + if (class_exists(TestCase::class)) { return true; } diff --git a/lib/Cake/Console/Templates/skel/webroot/index.php b/lib/Cake/Console/Templates/skel/webroot/index.php index db34c1950c..37e3f4bec7 100644 --- a/lib/Cake/Console/Templates/skel/webroot/index.php +++ b/lib/Cake/Console/Templates/skel/webroot/index.php @@ -73,7 +73,7 @@ trigger_error( 'Composer vendors directory not found at "' . VENDORS . '". ' . 'Please run "composer install" in the project root directory to install dependencies.', - E_USER_ERROR + E_USER_ERROR, ); } @@ -81,7 +81,7 @@ trigger_error( 'Composer autoload file not found at "' . VENDORS . 'autoload.php". ' . 'Please run "composer install" to generate the autoload file.', - E_USER_ERROR + E_USER_ERROR, ); } @@ -91,7 +91,7 @@ trigger_error( 'CakePHP core could not be found. ' . 'Please run "composer require friendsofcake2/cakephp" to install CakePHP core.', - E_USER_ERROR + E_USER_ERROR, ); } diff --git a/lib/Cake/Console/Templates/skel/webroot/test.php b/lib/Cake/Console/Templates/skel/webroot/test.php index 9016f2ac4a..e28fa6ad14 100644 --- a/lib/Cake/Console/Templates/skel/webroot/test.php +++ b/lib/Cake/Console/Templates/skel/webroot/test.php @@ -59,7 +59,7 @@ trigger_error( 'Composer vendors directory not found at "' . VENDORS . '". ' . 'Please run "composer install" in the project root directory to install dependencies.', - E_USER_ERROR + E_USER_ERROR, ); } @@ -67,7 +67,7 @@ trigger_error( 'Composer autoload file not found at "' . VENDORS . 'autoload.php". ' . 'Please run "composer install" to generate the autoload file.', - E_USER_ERROR + E_USER_ERROR, ); } @@ -77,7 +77,7 @@ trigger_error( 'CakePHP core could not be found. ' . 'Please run "composer require friendsofcake2/cakephp" to install CakePHP core.', - E_USER_ERROR + E_USER_ERROR, ); } diff --git a/lib/Cake/Core/App.php b/lib/Cake/Core/App.php index 9e299a36dc..0c3d4e0aae 100644 --- a/lib/Cake/Core/App.php +++ b/lib/Cake/Core/App.php @@ -906,7 +906,9 @@ protected static function _packageFormat() ], 'Vendor' => [ '%s' . 'Vendor' . DS, + ROOT . DS . 'vendor' . DS, ROOT . DS . 'vendors' . DS, + dirname(CAKE, 2) . DS . 'vendor' . DS, dirname(CAKE, 2) . DS . 'vendors' . DS, ], 'Plugin' => [ diff --git a/lib/Cake/TestSuite/CakeTestRunner.php b/lib/Cake/TestSuite/CakeTestRunner.php deleted file mode 100644 index bbb71de143..0000000000 --- a/lib/Cake/TestSuite/CakeTestRunner.php +++ /dev/null @@ -1,139 +0,0 @@ -_params = $params; - } - - /** - * Actually run a suite of tests. Cake initializes fixtures here using the chosen fixture manager - * - * @param PHPUnit_Framework_Test $suite The test suite to run - * @param array $arguments The CLI arguments - * @param bool $exit Exits by default or returns the results - * This argument is ignored if >PHPUnit5.2.0 - * @return void - */ - public function doRun(PHPUnit_Framework_Test $suite, array $arguments = [], $exit = true) - { - if (isset($arguments['printer'])) { - static::$versionStringPrinted = true; - } - - $fixture = $this->_getFixtureManager($arguments); - $iterator = $suite->getIterator(); - if ($iterator instanceof RecursiveIterator) { - $iterator = new RecursiveIteratorIterator($iterator); - } - foreach ($iterator as $test) { - if ($test instanceof CakeTestCase) { - $fixture->fixturize($test); - $test->fixtureManager = $fixture; - } - } - - $return = parent::doRun($suite, $arguments, $exit); - $fixture->shutdown(); - - return $return; - } - -// @codingStandardsIgnoreStart PHPUnit overrides don't match CakePHP - - /** - * Create the test result and splice on our code coverage reports. - * - * @return PHPUnit_Framework_TestResult - */ - protected function createTestResult() - { - $result = new PHPUnit_Framework_TestResult(); - if (!empty($this->_params['codeCoverage'])) { - if (method_exists($result, 'collectCodeCoverageInformation')) { - $result->collectCodeCoverageInformation(true); - } - if (method_exists($result, 'setCodeCoverage')) { - $result->setCodeCoverage(new PHP_CodeCoverage()); - } - } - - return $result; - } - -// @codingStandardsIgnoreEnd - - /** - * Get the fixture manager class specified or use the default one. - * - * @param array $arguments The CLI arguments. - * @return mixed instance of a fixture manager. - * @throws RuntimeException When fixture manager class cannot be loaded. - */ - protected function _getFixtureManager($arguments) - { - if (!empty($arguments['fixtureManager'])) { - App::uses($arguments['fixtureManager'], 'TestSuite'); - if (class_exists($arguments['fixtureManager'])) { - return new $arguments['fixtureManager'](); - } - throw new RuntimeException(__d('cake_dev', 'Could not find fixture manager %s.', $arguments['fixtureManager'])); - } - App::uses('AppFixtureManager', 'TestSuite'); - if (class_exists('AppFixtureManager')) { - return new AppFixtureManager(); - } - - return new CakeFixtureManager(); - } -} diff --git a/lib/Cake/TestSuite/CakeTestSuiteCommand.php b/lib/Cake/TestSuite/CakeTestSuiteCommand.php index c32014a214..c71b140cdc 100644 --- a/lib/Cake/TestSuite/CakeTestSuiteCommand.php +++ b/lib/Cake/TestSuite/CakeTestSuiteCommand.php @@ -19,7 +19,6 @@ * @license https://opensource.org/licenses/mit-license.php MIT License */ -App::uses('CakeTestRunner', 'TestSuite'); App::uses('CakeTestLoader', 'TestSuite'); App::uses('CakeTestSuite', 'TestSuite'); App::uses('CakeTestCase', 'TestSuite'); @@ -54,79 +53,6 @@ public function __construct($loader, $params = []) $this->longOptions['output='] = 'handleReporter'; } - /** - * Ugly hack to get around PHPUnit having a hard coded class name for the Runner. :( - * - * @param array $argv The command arguments - * @param bool $exit The exit mode. - * @return void - */ - public function run(array $argv, $exit = true): int - { - $this->handleArguments($argv); - - $runner = $this->getRunner($this->arguments['loader']); - - if ( - is_object($this->arguments['test']) && - $this->arguments['test'] instanceof PHPUnit_Framework_Test - ) { - $suite = $this->arguments['test']; - } else { - $suite = $runner->getTest( - $this->arguments['test'], - $this->arguments['testFile'], - ); - } - - if ($this->arguments['listGroups']) { - PHPUnit_TextUI_TestRunner::printVersionString(); - - print "Available test group(s):\n"; - - $groups = $suite->getGroups(); - sort($groups); - - foreach ($groups as $group) { - print " - $group\n"; - } - - exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT); - } - - unset($this->arguments['test']); - unset($this->arguments['testFile']); - - try { - $result = $runner->doRun($suite, $this->arguments, false); - } catch (PHPUnit_Framework_Exception $e) { - print $e->getMessage() . "\n"; - } - - if ($exit) { - if (!isset($result) || $result->errorCount() > 0) { - exit(PHPUnit_TextUI_TestRunner::EXCEPTION_EXIT); - } - if ($result->failureCount() > 0) { - exit(PHPUnit_TextUI_TestRunner::FAILURE_EXIT); - } - - // Default to success even if there are warnings to match phpunit's behavior - exit(PHPUnit_TextUI_TestRunner::SUCCESS_EXIT); - } - } - - /** - * Create a runner for the command. - * - * @param mixed $loader The loader to be used for the test run. - * @return CakeTestRunner - */ - public function getRunner($loader) - { - return new CakeTestRunner($loader, $this->_params); - } - /** * Handler for customizing the FixtureManager class/ * @@ -142,12 +68,10 @@ public function handleFixture($class) * Handles output flag used to change printing on webrunner. * * @param string $reporter The reporter class to use. - * @return void + * @return CakeBaseReporter */ public function handleReporter($reporter) { - $object = null; - $reporter = ucwords($reporter); $coreClass = 'Cake' . $reporter . 'Reporter'; App::uses($coreClass, 'TestSuite/Reporter'); diff --git a/lib/Cake/TestSuite/CakeTestSuiteDispatcher.php b/lib/Cake/TestSuite/CakeTestSuiteDispatcher.php index 2ab584133a..06dfdb6475 100644 --- a/lib/Cake/TestSuite/CakeTestSuiteDispatcher.php +++ b/lib/Cake/TestSuite/CakeTestSuiteDispatcher.php @@ -19,6 +19,9 @@ /** * Path to the tests directory of the app. */ + +use PHPUnit\Framework\TestCase; + if (!defined('TESTS')) { define('TESTS', APP . 'Test' . DS); } @@ -154,38 +157,7 @@ protected function _checkPHPUnit() */ public function loadTestFramework() { - if (class_exists('PHPUnit_Framework_TestCase')) { - return true; - } - $phpunitPath = 'phpunit' . DS . 'phpunit'; - if (defined('PHP_WINDOWS_VERSION_MAJOR')) { - $composerGlobalDir[] = env('APPDATA') . DS . 'Composer' . DS . 'vendor' . DS; - } else { - $composerGlobalDir[] = env('HOME') . DS . '.composer' . DS . 'vendor' . DS; - } - $vendors = array_merge(App::path('vendors'), $composerGlobalDir); - foreach ($vendors as $vendor) { - $vendor = rtrim($vendor, DS); - if (is_dir($vendor . DS . $phpunitPath)) { - ini_set('include_path', $vendor . DS . $phpunitPath . PATH_SEPARATOR . ini_get('include_path')); - break; - } elseif (is_dir($vendor . DS . 'PHPUnit')) { - ini_set('include_path', $vendor . PATH_SEPARATOR . ini_get('include_path')); - break; - } elseif (is_file($vendor . DS . 'phpunit.phar')) { - $backup = $GLOBALS['_SERVER']['SCRIPT_NAME']; - $GLOBALS['_SERVER']['SCRIPT_NAME'] = '-'; - ob_start(); - $included = include_once $vendor . DS . 'phpunit.phar'; - ob_end_clean(); - $GLOBALS['_SERVER']['SCRIPT_NAME'] = $backup; - - return $included; - } - } - include 'PHPUnit' . DS . 'Autoload.php'; - - return class_exists('PHPUnit_Framework_TestCase'); + return class_exists(TestCase::class); } /** diff --git a/lib/Cake/TestSuite/Reporter/CakeBaseReporter.php b/lib/Cake/TestSuite/Reporter/CakeBaseReporter.php index c27ed610a2..765e3cda2c 100644 --- a/lib/Cake/TestSuite/Reporter/CakeBaseReporter.php +++ b/lib/Cake/TestSuite/Reporter/CakeBaseReporter.php @@ -15,6 +15,10 @@ * @license https://opensource.org/licenses/mit-license.php MIT License */ +use PHPUnit\Framework\Test; +use PHPUnit\Framework\TestResult; +use PHPUnit\Framework\TestSuite; + if (!class_exists('PHPUnit_TextUI_ResultPrinter')) { require_once 'PHPUnit/TextUI/ResultPrinter.php'; } @@ -131,10 +135,10 @@ public function baseUrl() /** * Print result * - * @param PHPUnit_Framework_TestResult $result The result object + * @param TestResult $result The result object * @return void */ - public function printResult(PHPUnit_Framework_TestResult $result) + public function printResult(TestResult $result) { $this->paintFooter($result); } @@ -142,10 +146,10 @@ public function printResult(PHPUnit_Framework_TestResult $result) /** * Paint result * - * @param PHPUnit_Framework_TestResult $result The result object + * @param TestResult $result The result object * @return void */ - public function paintResult(PHPUnit_Framework_TestResult $result) + public function paintResult(TestResult $result) { $this->paintFooter($result); } @@ -153,12 +157,12 @@ public function paintResult(PHPUnit_Framework_TestResult $result) /** * An error occurred. * - * @param PHPUnit_Framework_Test $test The test to add an error for. + * @param \PHPUnit\Framework\Test $test The test to add an error for. * @param Exception $e The exception object to add. * @param float $time The current time. * @return void */ - public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) + public function addError(Test $test, Exception $e, $time) { $this->paintException($e, $test); } @@ -166,12 +170,12 @@ public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) /** * A failure occurred. * - * @param PHPUnit_Framework_Test $test The test that failed + * @param \PHPUnit\Framework\Test $test The test that failed * @param PHPUnit_Framework_AssertionFailedError $e The assertion that failed. * @param float $time The current time. * @return void */ - public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + public function addFailure(Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) { $this->paintFail($e, $test); } @@ -179,12 +183,12 @@ public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_Asser /** * Incomplete test. * - * @param PHPUnit_Framework_Test $test The test that was incomplete. + * @param \PHPUnit\Framework\Test $test The test that was incomplete. * @param Exception $e The incomplete exception * @param float $time The current time. * @return void */ - public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) + public function addIncompleteTest(Test $test, Exception $e, $time) { $this->paintSkip($e, $test); } @@ -192,12 +196,12 @@ public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $t /** * Skipped test. * - * @param PHPUnit_Framework_Test $test The test that failed. + * @param \PHPUnit\Framework\Test $test The test that failed. * @param Exception $e The skip object. * @param float $time The current time. * @return void */ - public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) + public function addSkippedTest(Test $test, Exception $e, $time) { $this->paintSkip($e, $test); } @@ -205,10 +209,10 @@ public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time /** * A test suite started. * - * @param PHPUnit_Framework_TestSuite $suite The suite to start + * @param TestSuite $suite The suite to start * @return void */ - public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + public function startTestSuite(TestSuite $suite) { if (!$this->_headerSent) { echo $this->paintHeader(); @@ -219,31 +223,31 @@ public function startTestSuite(PHPUnit_Framework_TestSuite $suite) /** * A test suite ended. * - * @param PHPUnit_Framework_TestSuite $suite The suite that ended. + * @param TestSuite $suite The suite that ended. * @return void */ - public function endTestSuite(PHPUnit_Framework_TestSuite $suite) + public function endTestSuite(TestSuite $suite) { } /** * A test started. * - * @param PHPUnit_Framework_Test $test The test that started. + * @param \PHPUnit\Framework\Test $test The test that started. * @return void */ - public function startTest(PHPUnit_Framework_Test $test) + public function startTest(Test $test) { } /** * A test ended. * - * @param PHPUnit_Framework_Test $test The test that ended + * @param \PHPUnit\Framework\Test $test The test that ended * @param float $time The current time. * @return void */ - public function endTest(PHPUnit_Framework_Test $test, $time) + public function endTest(Test $test, $time) { $this->numAssertions += $test->getNumAssertions(); if ($test->hasFailed()) { diff --git a/lib/Cake/TestSuite/Reporter/CakeHtmlReporter.php b/lib/Cake/TestSuite/Reporter/CakeHtmlReporter.php index 7cc912a829..2e6701b878 100644 --- a/lib/Cake/TestSuite/Reporter/CakeHtmlReporter.php +++ b/lib/Cake/TestSuite/Reporter/CakeHtmlReporter.php @@ -1,5 +1,9 @@ _buffer; ob_end_flush(); @@ -316,11 +320,11 @@ public function paintFail($message, $test) * trail of the nesting test suites below the * top level test. * - * @param PHPUnit_Framework_Test $test Test method that just passed + * @param \PHPUnit\Framework\Test $test Test method that just passed * @param float $time time spent to run the test method * @return void */ - public function paintPass(PHPUnit_Framework_Test $test, $time = null) + public function paintPass(Test $test, $time = null) { ob_start(); if (isset($this->params['showPasses']) && $this->params['showPasses']) { @@ -360,10 +364,10 @@ public function paintException($message, $test) * Prints the message for skipping tests. * * @param string $message Text of skip condition. - * @param PHPUnit_Framework_TestCase $test the test method skipped + * @param TestCase $test the test method skipped * @return void */ - public function paintSkip($message, $test) + public function paintSkip($message, TestCase $test) { ob_start(); echo "
  • \n"; @@ -421,10 +425,10 @@ protected function _getStackTrace(Exception $e) /** * A test suite started. * - * @param PHPUnit_Framework_TestSuite $suite The test suite to start. + * @param TestSuite $suite The test suite to start. * @return void */ - public function startTestSuite(PHPUnit_Framework_TestSuite $suite) + public function startTestSuite(TestSuite $suite) { if (!$this->_headerSent) { $this->paintHeader(); diff --git a/lib/Cake/TestSuite/Reporter/CakeTextReporter.php b/lib/Cake/TestSuite/Reporter/CakeTextReporter.php index cd53ef8d05..f0c1d4faf6 100644 --- a/lib/Cake/TestSuite/Reporter/CakeTextReporter.php +++ b/lib/Cake/TestSuite/Reporter/CakeTextReporter.php @@ -15,6 +15,8 @@ * @license https://opensource.org/licenses/mit-license.php MIT License */ +use PHPUnit\Framework\TestResult; + App::uses('CakeBaseReporter', 'TestSuite/Reporter'); App::uses('TextCoverageReport', 'TestSuite/Coverage'); @@ -73,10 +75,10 @@ public function paintFail($message) * Paints the end of the test with a summary of * the passes and failures. * - * @param PHPUnit_Framework_TestResult $result Result object + * @param TestResult $result Result object * @return void */ - public function paintFooter($result) + public function paintFooter(TestResult $result) { if ($result->failureCount() + $result->errorCount()) { echo "FAILURES!!!\n"; diff --git a/phpcs.xml b/phpcs.xml index fa597c7d14..23e53cb297 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -4,7 +4,6 @@ xsi:noNamespaceSchemaLocation="vendors/squizlabs/php_codesniffer/phpcs.xsd"> - index.php app/ lib/Cake/ diff --git a/vendors/empty b/vendors/empty deleted file mode 100644 index e69de29bb2..0000000000 From 5a20c4174693ec19298b1694436f46667ec44be7 Mon Sep 17 00:00:00 2001 From: TSURU Date: Thu, 2 Oct 2025 21:39:01 +0900 Subject: [PATCH 3/9] chore: Allow phpcodesniffer-composer-installer plugin Add allow-plugins configuration for dealerdirect/phpcodesniffer-composer-installer to comply with Composer 2.2+ plugin security requirements. --- composer.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 72873c03a4..5833fe332a 100644 --- a/composer.json +++ b/composer.json @@ -33,7 +33,10 @@ "config": { "vendor-dir": "vendors/", "process-timeout": 0, - "sort-packages": true + "sort-packages": true, + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true + } }, "include-path": [ "lib/" From 32cd2b71e3a7ce02e04b2fdc8d1042d90c348114 Mon Sep 17 00:00:00 2001 From: TSURU Date: Thu, 2 Oct 2025 22:08:27 +0900 Subject: [PATCH 4/9] refactor: Update test loader and fix tests for new dispatcher structure - Refactor CakeTestLoader to implement TestSuiteLoader interface with composition - Update ProjectTaskTest assertions to match new VENDORS constant - Fix FolderTest to use WWW_ROOT instead of APP for index.php path - Update load() method signature to match PHPUnit interface requirements --- .../Console/Command/Task/ProjectTaskTest.php | 10 +++---- lib/Cake/Test/Case/Utility/FolderTest.php | 2 +- lib/Cake/TestSuite/CakeTestLoader.php | 30 ++++++++++++++----- 3 files changed, 28 insertions(+), 14 deletions(-) diff --git a/lib/Cake/Test/Case/Console/Command/Task/ProjectTaskTest.php b/lib/Cake/Test/Case/Console/Command/Task/ProjectTaskTest.php index 34e8a1da77..8d5e301fe3 100644 --- a/lib/Cake/Test/Case/Console/Command/Task/ProjectTaskTest.php +++ b/lib/Cake/Test/Case/Console/Command/Task/ProjectTaskTest.php @@ -148,10 +148,10 @@ public function testExecuteWithAbsolutePath() $this->assertTrue(is_dir($this->Task->args[0]), 'No project dir'); $File = new File($path . DS . 'webroot' . DS . 'index.php'); $contents = $File->read(); - $this->assertMatchesRegularExpression('/define\(\'CAKE_CORE_INCLUDE_PATH\', .*?DS/', $contents); + $this->assertMatchesRegularExpression('/define\(\'VENDORS\', .*?DS/', $contents); $File = new File($path . DS . 'webroot' . DS . 'test.php'); $contents = $File->read(); - $this->assertMatchesRegularExpression('/define\(\'CAKE_CORE_INCLUDE_PATH\', .*?DS/', $contents); + $this->assertMatchesRegularExpression('/define\(\'VENDORS\', .*?DS/', $contents); } /** @@ -174,10 +174,10 @@ public function testExecuteWithCakeOnIncludePath() $this->assertTrue(is_dir($this->Task->args[0]), 'No project dir'); $contents = file_get_contents($path . DS . 'webroot' . DS . 'index.php'); - $this->assertMatchesRegularExpression('#//define\(\'CAKE_CORE_INCLUDE_PATH#', $contents); + $this->assertMatchesRegularExpression('#define\(\'VENDORS#', $contents); $contents = file_get_contents($path . DS . 'webroot' . DS . 'test.php'); - $this->assertMatchesRegularExpression('#//define\(\'CAKE_CORE_INCLUDE_PATH#', $contents); + $this->assertMatchesRegularExpression('#define\(\'VENDORS#', $contents); ini_set('include_path', $restore); } @@ -407,7 +407,7 @@ public function testConsolePath() $path = $this->Task->path . 'bake_test_app' . DS; $result = $this->Task->consolePath($path); - $this->assertTrue($result); + $this->assertFalse($result); $File = new File($path . 'Console' . DS . 'cake'); $contents = $File->read(); diff --git a/lib/Cake/Test/Case/Utility/FolderTest.php b/lib/Cake/Test/Case/Utility/FolderTest.php index bfd85ff360..67d8e87864 100644 --- a/lib/Cake/Test/Case/Utility/FolderTest.php +++ b/lib/Cake/Test/Case/Utility/FolderTest.php @@ -338,7 +338,7 @@ public function testOperations() $result = $Folder->delete($mv); $this->assertTrue($result); - $new = APP . 'index.php'; + $new = WWW_ROOT . 'index.php'; $result = $Folder->create($new); $this->assertFalse($result); diff --git a/lib/Cake/TestSuite/CakeTestLoader.php b/lib/Cake/TestSuite/CakeTestLoader.php index 8875b61856..58f93bb376 100644 --- a/lib/Cake/TestSuite/CakeTestLoader.php +++ b/lib/Cake/TestSuite/CakeTestLoader.php @@ -18,6 +18,9 @@ * @package Cake.TestSuite */ +use PHPUnit\Runner\StandardTestSuiteLoader; +use PHPUnit\Runner\TestSuiteLoader; + /** * TestLoader for CakePHP Test suite. * @@ -25,30 +28,36 @@ * * @package Cake.TestSuite */ -class CakeTestLoader extends PHPUnit_Runner_StandardTestSuiteLoader +class CakeTestLoader implements TestSuiteLoader { + private StandardTestSuiteLoader $loader; + + public function __construct() + { + $this->loader = new StandardTestSuiteLoader(); + } + /** * Load a file and find the first test case / suite in that file. * - * @param string $filePath The file path to load - * @param string $params Additional parameters + * @param string $suiteClassFile The file path to load * @return ReflectionClass */ - public function load($filePath, $params = '') + public function load(string $suiteClassFile): ReflectionClass { - $file = $this->_resolveTestFile($filePath, $params); + $file = $this->_resolveTestFile($suiteClassFile); - return parent::load('', $file); + return $this->loader->load($file); } /** * Convert path fragments used by CakePHP's test runner to absolute paths that can be fed to PHPUnit. * * @param string $filePath The file path to load. - * @param string $params Additional parameters. + * @param array $params Additional parameters. * @return string Converted path fragments. */ - protected function _resolveTestFile($filePath, $params) + protected function _resolveTestFile($filePath, $params = []) { $basePath = static::_basePath($params) . DS . $filePath; $ending = 'Test.php'; @@ -131,4 +140,9 @@ protected static function _getRecursiveFileList($directory = '.') return $fileList; } + + public function reload(ReflectionClass $aClass): ReflectionClass + { + return $this->reload($aClass); + } } From 7b43e73f00e9ce89d04704bdd252a8f94cfa2bd8 Mon Sep 17 00:00:00 2001 From: TSURU Date: Fri, 3 Oct 2025 01:07:30 +0900 Subject: [PATCH 5/9] refactor: Complete PHPUnit 9+ migration and remove legacy PHP version checks TestSuite improvements: - Fix critical infinite recursion bug in CakeTestLoader::reload() - Change CakeBaseReporter from extending PHPUnit_TextUI_ResultPrinter to implementing ResultPrinter interface - Add type declarations throughout TestSuite classes for PHP 8.0+ compatibility - Add run() method to CakeTestSuiteCommand with proper test file resolution - Update HtmlCoverageReportTest to use CakeHtmlReporter instead of CakeBaseReporter - Add missing interface methods (write, addWarning, addRiskyTest) to CakeBaseReporter Remove legacy PHP version checks: - Remove PHP 5.3/5.4 compatibility code from ErrorHandler, Debugger, CakeSocket - Remove PHP 5.4 fallback in CakeNumber::_numberFormat() - Remove PHP version checks from CakeTimeTest - Remove PHPUnit version check from test files Code style improvements: - Fix indentation in basics.php (standardize whitespace) - Change include to require_once in bootstrap files for consistency - Remove get_magic_quotes_gpc exclusion from phpcs.xml (function removed in PHP 7.4) - Add CakeHtmlReporter to unused variable exclusion list Other changes: - Update test assertions to match new dispatcher structure - Simplify home.ctp formatting --- app/Console/cake | 2 +- app/View/Pages/home.ctp | 308 +++++++++--------- app/webroot/index.php | 2 +- app/webroot/test.php | 2 +- lib/Cake/Console/Command/ServerShell.php | 6 - lib/Cake/Console/Command/TestShell.php | 13 +- lib/Cake/Console/Command/TestsuiteShell.php | 10 +- lib/Cake/Console/ShellDispatcher.php | 4 +- lib/Cake/Console/Templates/skel/Console/cake | 2 +- .../Templates/skel/View/Pages/home.ctp | 304 +++++++++-------- .../Console/Templates/skel/webroot/index.php | 2 +- .../Console/Templates/skel/webroot/test.php | 2 +- lib/Cake/Console/cake | 2 +- lib/Cake/Core/Configure.php | 2 +- lib/Cake/Error/ErrorHandler.php | 10 - lib/Cake/Log/Engine/FileLog.php | 6 +- lib/Cake/Model/Datasource/CakeSession.php | 4 +- lib/Cake/Network/CakeRequest.php | 9 +- lib/Cake/Network/CakeSocket.php | 18 +- lib/Cake/Test/Case/BasicsTest.php | 38 --- .../Case/Console/ConsoleErrorHandlerTest.php | 4 - lib/Cake/Test/Case/Core/CakeObjectTest.php | 12 - .../Case/TestSuite/HtmlCoverageReportTest.php | 7 +- lib/Cake/Test/Case/Utility/CakeTimeTest.php | 18 +- lib/Cake/Test/Case/Utility/DebuggerTest.php | 8 - lib/Cake/Test/Case/Utility/HashTest.php | 10 - lib/Cake/Test/Case/Utility/SecurityTest.php | 1 - .../Test/Case/View/Helper/RssHelperTest.php | 6 +- lib/Cake/Test/Case/View/JsonViewTest.php | 2 - lib/Cake/Test/Case/View/ViewTest.php | 9 +- lib/Cake/Test/bootstrap.php | 2 +- lib/Cake/Test/bootstrap/cake_dot_php.php | 2 +- lib/Cake/TestSuite/CakeTestLoader.php | 33 +- lib/Cake/TestSuite/CakeTestSuiteCommand.php | 62 +++- .../TestSuite/CakeTestSuiteDispatcher.php | 4 +- .../TestSuite/Reporter/CakeBaseReporter.php | 70 +++- .../TestSuite/Reporter/CakeHtmlReporter.php | 28 +- lib/Cake/TestSuite/templates/header.php | 26 +- lib/Cake/TestSuite/templates/phpunit.php | 2 +- lib/Cake/TestSuite/templates/xdebug.php | 2 +- lib/Cake/Utility/CakeNumber.php | 27 +- lib/Cake/Utility/CakeTime.php | 13 +- lib/Cake/Utility/Debugger.php | 38 +-- lib/Cake/Utility/File.php | 8 +- lib/Cake/Utility/Hash.php | 4 - lib/Cake/View/JsonView.php | 4 +- lib/Cake/basics.php | 58 ++-- lib/Cake/bootstrap.php | 6 +- phpcs.xml | 3 +- 49 files changed, 553 insertions(+), 662 deletions(-) diff --git a/app/Console/cake b/app/Console/cake index 305dba76bd..0aa37d6a64 100755 --- a/app/Console/cake +++ b/app/Console/cake @@ -47,7 +47,7 @@ if (!is_file(VENDORS . 'autoload.php')) { require_once VENDORS . 'autoload.php'; -if (!include 'Cake' . DS . 'Console' . DS . 'ShellDispatcher.php') { +if (!require_once 'Cake' . DS . 'Console' . DS . 'ShellDispatcher.php') { trigger_error('Could not locate CakePHP core files.', E_USER_ERROR); } diff --git a/app/View/Pages/home.ctp b/app/View/Pages/home.ctp index d0e20df8cf..97edd9e437 100644 --- a/app/View/Pages/home.ctp +++ b/app/View/Pages/home.ctp @@ -6,142 +6,136 @@ */ if (!Configure::read('debug')): - throw new NotFoundException(); + throw new NotFoundException(); endif; App::uses('Debugger', 'Utility'); ?>

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

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

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

    +

    + + 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 version of PHP is 5.2.8 or higher.'); + echo ''; + ?>

    - '; - 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', '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', CONFIG . 'core.php'); - echo ''; - else: - echo ''; - echo __d('cake_dev', 'Your cache is NOT working. Please check the settings in %s', CONFIG . 'core.php'); - echo ''; - endif; - ?> + '; + echo __d('cake_dev', 'The %s is being used for core caching. To change the config edit %s', '' . $settings['engine'] . 'Engine', CONFIG . 'core.php'); + echo ''; + else: + echo ''; + echo __d('cake_dev', 'Your cache is NOT working. Please check the settings in %s', 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', CONFIG . 'database.php.default', CONFIG . 'database.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', CONFIG . 'database.php.default', CONFIG . 'database.php'); + echo '
    '; + endif; + ?>

    getMessage(); - if (method_exists($connectionError, 'getAttributes')): - $attributes = $connectionError->getAttributes(); - if (isset($attributes['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; - ?> -

    + App::uses('ConnectionManager', 'Model'); + try { + $connected = ConnectionManager::getDataSource('default'); + } catch (Exception $connectionError) { + $connected = false; + $errorMsg = $connectionError->getMessage(); + if (method_exists($connectionError, 'getAttributes')): + $attributes = $connectionError->getAttributes(); + if (isset($attributes['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 '

    '; + echo '

    '; + 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; - ?> + '; + 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; + ?>

    @@ -150,41 +144,41 @@ endif; echo __d('cake_dev', 'To change the content of this page, edit: %s.
    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'); + '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')), - 'https://book.cakephp.org/2.0/en/', - array('target' => '_blank', 'escape' => false) - ); - ?> + Html->link( + sprintf('%s %s', __d('cake_dev', 'New'), __d('cake_dev', 'CakePHP 2.0 Docs')), + 'https://book.cakephp.org/2.0/en/', + array('target' => '_blank', 'escape' => false) + ); + ?>

    - Html->link( - __d('cake_dev', 'The 15 min Blog Tutorial'), - 'https://book.cakephp.org/2.0/en/tutorials-and-examples/blog/blog.html', - array('target' => '_blank', 'escape' => false) - ); - ?> + Html->link( + __d('cake_dev', 'The 15 min Blog Tutorial'), + 'https://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') ?>: - -
    • +
    • + Html->link('DebugKit', 'https://github.com/cakephp/debug_kit/tree/2.2') ?>: + +
    • +
    • + Html->link('Localized', 'https://github.com/cakephp/localized') ?>: + +

    @@ -197,34 +191,34 @@ You can also add some CSS styles for your pages at: %s.',

    diff --git a/app/webroot/index.php b/app/webroot/index.php index 2a8d25f483..16eb3c0223 100644 --- a/app/webroot/index.php +++ b/app/webroot/index.php @@ -94,7 +94,7 @@ require_once VENDORS . 'autoload.php'; -if (!include 'Cake' . DS . 'bootstrap.php') { +if (!require_once 'Cake' . DS . 'bootstrap.php') { trigger_error( 'CakePHP core could not be found. ' . 'Please run "composer require friendsofcake2/cakephp" to install CakePHP core.', diff --git a/app/webroot/test.php b/app/webroot/test.php index b093a802a1..bfc42e65bd 100644 --- a/app/webroot/test.php +++ b/app/webroot/test.php @@ -89,7 +89,7 @@ require_once VENDORS . 'autoload.php'; -if (!include 'Cake' . DS . 'bootstrap.php') { +if (!require_once 'Cake' . DS . 'bootstrap.php') { trigger_error( 'CakePHP core could not be found. ' . 'Please run "composer require friendsofcake2/cakephp" to install CakePHP core.', diff --git a/lib/Cake/Console/Command/ServerShell.php b/lib/Cake/Console/Command/ServerShell.php index 534acf7038..54ea46ea90 100644 --- a/lib/Cake/Console/Command/ServerShell.php +++ b/lib/Cake/Console/Command/ServerShell.php @@ -127,12 +127,6 @@ protected function _welcome() */ 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, diff --git a/lib/Cake/Console/Command/TestShell.php b/lib/Cake/Console/Command/TestShell.php index 62c43e54d8..eaf71c323a 100644 --- a/lib/Cake/Console/Command/TestShell.php +++ b/lib/Cake/Console/Command/TestShell.php @@ -187,7 +187,7 @@ public function initialize() * * @return array|null Array of params for CakeTestDispatcher or null. */ - protected function _parseArgs() + protected function _parseArgs(): ?array { if (empty($this->args)) { return null; @@ -268,7 +268,9 @@ public function main() $args = $this->_parseArgs(); if (empty($args['case'])) { - return $this->available(); + $this->available(); + + return; } $this->_run($args, $this->_runnerOptions()); @@ -286,8 +288,8 @@ protected function _run($runnerArgs, $options = []) restore_error_handler(); restore_error_handler(); - $testCli = new CakeTestSuiteCommand('CakeTestLoader', $runnerArgs); - $testCli->run($options); + $testCli = new CakeTestSuiteCommand(CakeTestLoader::class, $runnerArgs); + $testCli->run($options, false); } /** @@ -314,8 +316,9 @@ public function available() if (empty($testCases)) { $this->out(__d('cake_console', "No test cases available \n\n")); + $this->out($this->OptionParser->help()); - return $this->out($this->OptionParser->help()); + return; } $this->out($title); diff --git a/lib/Cake/Console/Command/TestsuiteShell.php b/lib/Cake/Console/Command/TestsuiteShell.php index 81ddd3470c..2419eaf005 100644 --- a/lib/Cake/Console/Command/TestsuiteShell.php +++ b/lib/Cake/Console/Command/TestsuiteShell.php @@ -51,12 +51,12 @@ public function getOptionParser() /** * Parse the CLI options into an array CakeTestDispatcher can use. * - * @return array Array of params for CakeTestDispatcher + * @return array|null Array of params for CakeTestDispatcher */ - protected function _parseArgs() + protected function _parseArgs(): ?array { if (empty($this->args)) { - return; + return null; } $params = [ 'core' => false, @@ -95,7 +95,9 @@ public function main() $args = $this->_parseArgs(); if (empty($args['case'])) { - return $this->available(); + $this->available(); + + return; } $this->_run($args, $this->_runnerOptions()); diff --git a/lib/Cake/Console/ShellDispatcher.php b/lib/Cake/Console/ShellDispatcher.php index 4ae10eeff2..dd43ce46b1 100644 --- a/lib/Cake/Console/ShellDispatcher.php +++ b/lib/Cake/Console/ShellDispatcher.php @@ -150,7 +150,7 @@ protected function _bootstrap() define('CONFIG', ROOT . DS . APP_DIR . DS . 'Config' . DS); } // $boot is used by Cake/bootstrap.php file - require CORE_PATH . 'Cake' . DS . 'bootstrap.php'; + require_once CORE_PATH . 'Cake' . DS . 'bootstrap.php'; if (!file_exists(CONFIG . 'core.php')) { include_once CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'Console' . DS . 'Templates' . DS . 'skel' . DS . 'Config' . DS . 'core.php'; @@ -419,7 +419,7 @@ public function help() * Stop execution of the current script * * @param string|int $status see http://php.net/exit for values - * @return void + * @return never */ protected function _stop($status = 0) { diff --git a/lib/Cake/Console/Templates/skel/Console/cake b/lib/Cake/Console/Templates/skel/Console/cake index 1d8b93f1a4..a9207817ca 100644 --- a/lib/Cake/Console/Templates/skel/Console/cake +++ b/lib/Cake/Console/Templates/skel/Console/cake @@ -46,7 +46,7 @@ if (!is_file(VENDORS . 'autoload.php')) { require_once VENDORS . 'autoload.php'; -if (!include 'Cake' . DS . 'Console' . DS . 'ShellDispatcher.php') { +if (!require_once 'Cake' . DS . 'Console' . DS . 'ShellDispatcher.php') { trigger_error('Could not locate CakePHP core files.', E_USER_ERROR); } diff --git a/lib/Cake/Console/Templates/skel/View/Pages/home.ctp b/lib/Cake/Console/Templates/skel/View/Pages/home.ctp index 0b2613812e..99fe8b57b9 100644 --- a/lib/Cake/Console/Templates/skel/View/Pages/home.ctp +++ b/lib/Cake/Console/Templates/skel/View/Pages/home.ctp @@ -6,145 +6,139 @@ */ if (!Configure::read('debug')): - throw new NotFoundException(); + throw new NotFoundException(); endif; App::uses('Debugger', 'Utility'); ?>

    - +

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

    - - 1) Help me configure it - 2) I don't / can't use URL rewriting + + 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 version of PHP is 5.2.8 or higher.'); + echo ''; + ?>

    - '; - 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', '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', CONFIG . 'core.php'); - echo ''; - else: - echo ''; - echo __d('cake_dev', 'Your cache is NOT working. Please check the settings in %s', CONFIG . 'core.php'); - echo ''; - endif; - ?> + '; + echo __d('cake_dev', 'The %s is being used for core caching. To change the config edit %s', '' . $settings['engine'] . 'Engine', CONFIG . 'core.php'); + echo ''; + else: + echo ''; + echo __d('cake_dev', 'Your cache is NOT working. Please check the settings in %s', 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', CONFIG . 'database.php.default', CONFIG . 'database.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', CONFIG . 'database.php.default', CONFIG . 'database.php'); + echo '
    '; + endif; + ?>

    getMessage(); - if (method_exists($connectionError, 'getAttributes')): - $attributes = $connectionError->getAttributes(); - if (isset($errorMsg['message'])): - $errorMsg .= '
    ' . $attributes['message']; - endif; - endif; - } + App::uses('ConnectionManager', 'Model'); + try { + $connected = ConnectionManager::getDataSource('default'); + } catch (Exception $connectionError) { + $connected = false; + $errorMsg = $connectionError->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; - ?> + 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; + App::uses('Validation', 'Utility'); + if (!Validation::alphaNumeric('cakephp')): + echo '

    '; + 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; - ?> + '; + 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; + ?>

    @@ -153,41 +147,41 @@ if (isset($filePresent)): echo __d('cake_dev', 'To change the content of this page, edit: %s.
    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'); + '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')), - 'https://book.cakephp.org/2.0/en/', - array('target' => '_blank', 'escape' => false) - ); - ?> + Html->link( + sprintf('%s %s', __d('cake_dev', 'New'), __d('cake_dev', 'CakePHP 2.0 Docs')), + 'https://book.cakephp.org/2.0/en/', + array('target' => '_blank', 'escape' => false) + ); + ?>

    - Html->link( - __d('cake_dev', 'The 15 min Blog Tutorial'), - 'https://book.cakephp.org/2.0/en/tutorials-and-examples/blog/blog.html', - array('target' => '_blank', 'escape' => false) - ); - ?> + Html->link( + __d('cake_dev', 'The 15 min Blog Tutorial'), + 'https://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') ?>: - -
    • +
    • + Html->link('DebugKit', 'https://github.com/cakephp/debug_kit/tree/2.2') ?>: + +
    • +
    • + Html->link('Localized', 'https://github.com/cakephp/localized') ?>: + +

    @@ -200,34 +194,34 @@ You can also add some CSS styles for your pages at: %s.',

    diff --git a/lib/Cake/Console/Templates/skel/webroot/index.php b/lib/Cake/Console/Templates/skel/webroot/index.php index 37e3f4bec7..fc23db388b 100644 --- a/lib/Cake/Console/Templates/skel/webroot/index.php +++ b/lib/Cake/Console/Templates/skel/webroot/index.php @@ -87,7 +87,7 @@ require_once VENDORS . 'autoload.php'; -if (!include 'Cake' . DS . 'bootstrap.php') { +if (!require_once 'Cake' . DS . 'bootstrap.php') { trigger_error( 'CakePHP core could not be found. ' . 'Please run "composer require friendsofcake2/cakephp" to install CakePHP core.', diff --git a/lib/Cake/Console/Templates/skel/webroot/test.php b/lib/Cake/Console/Templates/skel/webroot/test.php index e28fa6ad14..e16300655f 100644 --- a/lib/Cake/Console/Templates/skel/webroot/test.php +++ b/lib/Cake/Console/Templates/skel/webroot/test.php @@ -73,7 +73,7 @@ require_once VENDORS . 'autoload.php'; -if (!include 'Cake' . DS . 'bootstrap.php') { +if (!require_once 'Cake' . DS . 'bootstrap.php') { trigger_error( 'CakePHP core could not be found. ' . 'Please run "composer require friendsofcake2/cakephp" to install CakePHP core.', diff --git a/lib/Cake/Console/cake b/lib/Cake/Console/cake index 5d0891b902..586976ee82 100755 --- a/lib/Cake/Console/cake +++ b/lib/Cake/Console/cake @@ -37,7 +37,7 @@ if (isset($GLOBALS['_composer_autoload_path'])) { } } -if (!include 'Cake' . DS . 'Console' . DS . 'ShellDispatcher.php') { +if (!require_once 'Cake' . DS . 'Console' . DS . 'ShellDispatcher.php') { trigger_error('Could not locate CakePHP core files.', E_USER_ERROR); } diff --git a/lib/Cake/Core/Configure.php b/lib/Cake/Core/Configure.php index 5cb26d83b2..67a906f36d 100644 --- a/lib/Cake/Core/Configure.php +++ b/lib/Cake/Core/Configure.php @@ -439,7 +439,7 @@ protected static function _getReader($config) public static function version() { if (!isset(static::$_values['Cake']['version'])) { - require CAKE . 'Config' . DS . 'config.php'; + $config = require CAKE . 'Config' . DS . 'config.php'; static::write($config); } diff --git a/lib/Cake/Error/ErrorHandler.php b/lib/Cake/Error/ErrorHandler.php index 279e5811f0..da5c8d100c 100644 --- a/lib/Cake/Error/ErrorHandler.php +++ b/lib/Cake/Error/ErrorHandler.php @@ -339,16 +339,6 @@ protected static function _getErrorMessage($error, $code, $description, $file, $ $errorConfig = Configure::read('Error'); $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(['start' => 1, 'format' => 'log']); $message .= "\nTrace:\n" . $trace . "\n"; } diff --git a/lib/Cake/Log/Engine/FileLog.php b/lib/Cake/Log/Engine/FileLog.php index 08cdeaafd8..06923e310c 100644 --- a/lib/Cake/Log/Engine/FileLog.php +++ b/lib/Cake/Log/Engine/FileLog.php @@ -195,11 +195,7 @@ protected function _getFilename($type) protected function _rotateFile($filename) { $filepath = $this->_path . $filename; - if (version_compare(PHP_VERSION, '5.3.0') >= 0) { - clearstatcache(true, $filepath); - } else { - clearstatcache(); - } + clearstatcache(true, $filepath); if ( !file_exists($filepath) || diff --git a/lib/Cake/Model/Datasource/CakeSession.php b/lib/Cake/Model/Datasource/CakeSession.php index 1ff9d40932..8d26887f5f 100644 --- a/lib/Cake/Model/Datasource/CakeSession.php +++ b/lib/Cake/Model/Datasource/CakeSession.php @@ -589,9 +589,7 @@ protected static function _configureSession() // In PHP7.2.0+ session.save_handler can't be set to 'user' by the user. // https://github.com/php/php-src/commit/a93a51c3bf4ea1638ce0adc4a899cb93531b9f0d - if (version_compare(PHP_VERSION, '7.2.0', '>=')) { - unset($sessionConfig['ini']['session.save_handler']); - } + unset($sessionConfig['ini']['session.save_handler']); } elseif (!empty($sessionConfig['session.save_path']) && Configure::read('debug')) { if (!is_dir($sessionConfig['session.save_path'])) { mkdir($sessionConfig['session.save_path'], 0775, true); diff --git a/lib/Cake/Network/CakeRequest.php b/lib/Cake/Network/CakeRequest.php index 37979b8fa1..6a9d23a2b5 100644 --- a/lib/Cake/Network/CakeRequest.php +++ b/lib/Cake/Network/CakeRequest.php @@ -179,9 +179,6 @@ protected function _processPost() $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')) { @@ -222,11 +219,7 @@ protected function _processPost() */ protected function _processGet() { - if (ini_get('magic_quotes_gpc') === '1') { - $query = stripslashes_deep($_GET); - } else { - $query = $_GET; - } + $query = $_GET; $unsetUrl = '/' . str_replace(['.', ' '], '_', urldecode($this->url)); unset($query[$unsetUrl]); diff --git a/lib/Cake/Network/CakeSocket.php b/lib/Cake/Network/CakeSocket.php index 5fdade0c9b..a47a95b1bb 100644 --- a/lib/Cake/Network/CakeSocket.php +++ b/lib/Cake/Network/CakeSocket.php @@ -287,19 +287,11 @@ protected function _setSslContext($host) } 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 (!isset($this->config['context']['ssl']['SNI_enabled'])) { + $this->config['context']['ssl']['SNI_enabled'] = true; + } + if (empty($this->config['context']['ssl']['peer_name'])) { + $this->config['context']['ssl']['peer_name'] = $host; } if (empty($this->config['context']['ssl']['cafile'])) { $this->config['context']['ssl']['cafile'] = CAKE . 'Config' . DS . 'cacert.pem'; diff --git a/lib/Cake/Test/Case/BasicsTest.php b/lib/Cake/Test/Case/BasicsTest.php index d2ac84ca75..4bfd913be5 100644 --- a/lib/Cake/Test/Case/BasicsTest.php +++ b/lib/Cake/Test/Case/BasicsTest.php @@ -1112,8 +1112,6 @@ public function testPrCli() */ 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'); @@ -1143,42 +1141,6 @@ public function testStripslashesDeep() $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 = [ - 'a' => "tes't", - 'b' => "tes''t", - 'c' => [ - 'd' => "tes'''t", - 'e' => "tes''''t", - ['f' => "tes''t"], - ], - 'g' => "te'''''st", - ]; - $expected = [ - 'a' => "tes't", - 'b' => "tes't", - 'c' => [ - 'd' => "tes''t", - 'e' => "tes''t", - ['f' => "tes't"], - ], - 'g' => "te'''st", - ]; - $this->assertEquals($expected, stripslashes_deep($nested)); - } - /** * Tests that the stackTrace() method is a shortcut for Debugger::trace() * diff --git a/lib/Cake/Test/Case/Console/ConsoleErrorHandlerTest.php b/lib/Cake/Test/Case/Console/ConsoleErrorHandlerTest.php index ece9d6e2ae..226d38d60e 100644 --- a/lib/Cake/Test/Case/Console/ConsoleErrorHandlerTest.php +++ b/lib/Cake/Test/Case/Console/ConsoleErrorHandlerTest.php @@ -163,10 +163,6 @@ public function testError500Exception() */ 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'); diff --git a/lib/Cake/Test/Case/Core/CakeObjectTest.php b/lib/Cake/Test/Case/Core/CakeObjectTest.php index 32f829e751..858d8aacd3 100644 --- a/lib/Cake/Test/Case/Core/CakeObjectTest.php +++ b/lib/Cake/Test/Case/Core/CakeObjectTest.php @@ -723,16 +723,4 @@ public function testRequestActionPostWithData() ); $this->assertEquals($data, $result); } - - /** - * Test backward compatibility - * - * @return voind - */ - public function testBackwardCompatibility() - { - $this->skipIf(version_compare(PHP_VERSION, '7.0.0', '>=')); - - $this->assertInstanceOf('Object', new ObjectTestModel()); - } } diff --git a/lib/Cake/Test/Case/TestSuite/HtmlCoverageReportTest.php b/lib/Cake/Test/Case/TestSuite/HtmlCoverageReportTest.php index 5a16b87a2c..2a0ae800ef 100644 --- a/lib/Cake/Test/Case/TestSuite/HtmlCoverageReportTest.php +++ b/lib/Cake/Test/Case/TestSuite/HtmlCoverageReportTest.php @@ -1,7 +1,5 @@ skipIf(version_compare(Version::id(), '9.0.0', '>='), 'This test can not be run with PHPUnit 9+'); parent::setUp(); App::build([ 'Plugin' => [CAKE . 'Test' . DS . 'test_app' . DS . 'Plugin' . DS], ], App::RESET); CakePlugin::load(['TestPlugin']); - $reporter = new CakeBaseReporter(); + $reporter = new CakeHtmlReporter(); $reporter->params = ['app' => false, 'plugin' => false, 'group' => false]; $coverage = []; $this->Coverage = new HtmlCoverageReport($coverage, $reporter); diff --git a/lib/Cake/Test/Case/Utility/CakeTimeTest.php b/lib/Cake/Test/Case/Utility/CakeTimeTest.php index 9be39f4ba5..73d90f4b33 100644 --- a/lib/Cake/Test/Case/Utility/CakeTimeTest.php +++ b/lib/Cake/Test/Case/Utility/CakeTimeTest.php @@ -1301,10 +1301,6 @@ public function testFormatNewSyntax() */ public function testListTimezones() { - $this->skipIf( - version_compare(PHP_VERSION, '5.4.0', '<='), - 'This test requires newer libicu which is in php5.4+', - ); $return = CakeTime::listTimezones(); $this->assertTrue(isset($return['Asia']['Asia/Bangkok'])); $this->assertEquals('Bangkok', $return['Asia']['Asia/Bangkok']); @@ -1335,15 +1331,13 @@ public function testListTimezones() $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::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'])); - } + $return = CakeTime::listTimezones(DateTimeZone::PER_COUNTRY, 'US', false); + $this->assertTrue(isset($return['Pacific/Honolulu'])); + $this->assertFalse(isset($return['Asia/Bangkok'])); } /** diff --git a/lib/Cake/Test/Case/Utility/DebuggerTest.php b/lib/Cake/Test/Case/Utility/DebuggerTest.php index bf3c9386b7..14622a8758 100644 --- a/lib/Cake/Test/Case/Utility/DebuggerTest.php +++ b/lib/Cake/Test/Case/Utility/DebuggerTest.php @@ -388,10 +388,6 @@ public function testExportVar() 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', @@ -417,10 +413,6 @@ public function testExportVar() [protected] _stack => array() [protected] _eventManager => object(CakeEventManager) {} [protected] _eventManagerConfigured => false - -TEXT; - } - $expected .= <<markTestSkipped('SORT_NATURAL is available since PHP 5.4.'); - } $items = [ ['Item' => ['image' => 'img1.jpg']], ['Item' => ['image' => 'img99.jpg']], @@ -1370,9 +1367,6 @@ public function testSortNatural() */ public function testSortNaturalIgnoreCase() { - if (version_compare(PHP_VERSION, '5.4.0', '<')) { - $this->markTestSkipped('SORT_NATURAL is available since PHP 5.4.'); - } $items = [ ['Item' => ['image' => 'img1.jpg']], ['Item' => ['image' => 'img99.jpg']], @@ -1408,10 +1402,6 @@ public function testSortNaturalIgnoreCase() */ public function testSortNaturalFallbackToRegular() { - if (version_compare(PHP_VERSION, '5.4.0', '>=')) { - $this->markTestSkipped('Skipping SORT_NATURAL fallback test on PHP >= 5.4'); - } - $a = [ 0 => ['Person' => ['name' => 'Jeff']], 1 => ['Shirt' => ['color' => 'black']], diff --git a/lib/Cake/Test/Case/Utility/SecurityTest.php b/lib/Cake/Test/Case/Utility/SecurityTest.php index fd915caf38..950cd83ef1 100644 --- a/lib/Cake/Test/Case/Utility/SecurityTest.php +++ b/lib/Cake/Test/Case/Utility/SecurityTest.php @@ -523,7 +523,6 @@ public function testEncryptDecryptCompatibility($txt) { $this->skipIf(!extension_loaded('mcrypt'), 'This test requires mcrypt to be installed'); $this->skipIf(!extension_loaded('openssl'), 'This test requires openssl to be installed'); - $this->skipIf(version_compare(PHP_VERSION, '5.3.3', '<'), 'This test requires PHP 5.3.3 or greater'); $key = '12345678901234567890123456789012'; diff --git a/lib/Cake/Test/Case/View/Helper/RssHelperTest.php b/lib/Cake/Test/Case/View/Helper/RssHelperTest.php index b62070c74a..efd21b6050 100644 --- a/lib/Cake/Test/Case/View/Helper/RssHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/RssHelperTest.php @@ -600,11 +600,7 @@ public function testItemEnclosureLength() $this->assertTrue($File->write('123'), 'Could not write to ' . $tmpFile); - if (PHP_VERSION_ID >= 50300) { - clearstatcache(true, $tmpFile); - } else { - clearstatcache(); - } + clearstatcache(true, $tmpFile); $item = [ 'title' => [ diff --git a/lib/Cake/Test/Case/View/JsonViewTest.php b/lib/Cake/Test/Case/View/JsonViewTest.php index b877b4c4b8..bd657135f8 100644 --- a/lib/Cake/Test/Case/View/JsonViewTest.php +++ b/lib/Cake/Test/Case/View/JsonViewTest.php @@ -206,8 +206,6 @@ public function testRenderWithoutView($data, $serialize, $expected) */ public function testRenderWithoutViewJsonOptions() { - $this->skipIf(!version_compare(PHP_VERSION, '5.3.0', '>='), 'Needs PHP5.3+ for these constants to be tested'); - $Request = new CakeRequest(); $Response = new CakeResponse(); $Controller = new Controller($Request, $Response); diff --git a/lib/Cake/Test/Case/View/ViewTest.php b/lib/Cake/Test/Case/View/ViewTest.php index 44556fa5f5..fc99eafb42 100644 --- a/lib/Cake/Test/Case/View/ViewTest.php +++ b/lib/Cake/Test/Case/View/ViewTest.php @@ -1954,12 +1954,7 @@ public function testViewVarDefaultValue() protected function _checkException($message) { - if (version_compare(PHP_VERSION, '7.4', '>=')) { - $this->expectException(Error::class); - $this->expectExceptionMessage($message); - } else { - $this->expectError(); - $this->expectErrorMessage($message); - } + $this->expectException(Error::class); + $this->expectExceptionMessage($message); } } diff --git a/lib/Cake/Test/bootstrap.php b/lib/Cake/Test/bootstrap.php index b6f7589a62..da5f795d6f 100644 --- a/lib/Cake/Test/bootstrap.php +++ b/lib/Cake/Test/bootstrap.php @@ -17,7 +17,7 @@ * so load it here. */ App::uses('CakeTestSuiteDispatcher', 'TestSuite'); -App::load('CakeTestSuiteDispatcher'); +require_once 'Cake' . DS . 'Console' . DS . 'ShellDispatcher.php'; /* * Classes that can be used without declaring App::uses() diff --git a/lib/Cake/Test/bootstrap/cake_dot_php.php b/lib/Cake/Test/bootstrap/cake_dot_php.php index 0660b6efea..2b3a01147f 100644 --- a/lib/Cake/Test/bootstrap/cake_dot_php.php +++ b/lib/Cake/Test/bootstrap/cake_dot_php.php @@ -23,7 +23,7 @@ } } -if (!include 'Cake' . DS . 'Console' . DS . 'ShellDispatcher.php') { +if (!require_once 'Cake' . DS . 'Console' . DS . 'ShellDispatcher.php') { trigger_error('Could not locate CakePHP core files.', E_USER_ERROR); } diff --git a/lib/Cake/TestSuite/CakeTestLoader.php b/lib/Cake/TestSuite/CakeTestLoader.php index 58f93bb376..fdf40dc7e3 100644 --- a/lib/Cake/TestSuite/CakeTestLoader.php +++ b/lib/Cake/TestSuite/CakeTestLoader.php @@ -32,6 +32,9 @@ class CakeTestLoader implements TestSuiteLoader { private StandardTestSuiteLoader $loader; + /** + * Constructor + */ public function __construct() { $this->loader = new StandardTestSuiteLoader(); @@ -45,7 +48,7 @@ public function __construct() */ public function load(string $suiteClassFile): ReflectionClass { - $file = $this->_resolveTestFile($suiteClassFile); + $file = $this->_resolveTestFile($suiteClassFile, []); return $this->loader->load($file); } @@ -57,21 +60,21 @@ public function load(string $suiteClassFile): ReflectionClass * @param array $params Additional parameters. * @return string Converted path fragments. */ - protected function _resolveTestFile($filePath, $params = []) + protected function _resolveTestFile(string $filePath, array $params): string { $basePath = static::_basePath($params) . DS . $filePath; $ending = 'Test.php'; - return strpos($basePath, $ending) === strlen($basePath) - strlen($ending) ? $basePath : $basePath . $ending; + return str_ends_with($basePath, $ending) ? $basePath : $basePath . $ending; } /** * Generates the base path to a set of tests based on the parameters. * - * @param array $params The path parameters. - * @return string The base path. + * @param array|null $params The path parameters. + * @return string|null The base path. */ - protected static function _basePath($params) + protected static function _basePath(?array $params): ?string { $result = null; if (!empty($params['core'])) { @@ -96,12 +99,16 @@ protected static function _basePath($params) /** * Get the list of files for the test listing. * - * @param string $params Path parameters + * @param array|null $params Path parameters * @return array */ - public static function generateTestList($params) + public static function generateTestList(?array $params): array { $directory = static::_basePath($params); + if (empty($directory)) { + return []; + } + $fileList = static::_getRecursiveFileList($directory); $testCases = []; @@ -122,7 +129,7 @@ public static function generateTestList($params) * @param string $directory The directory to scan for files. * @return array */ - protected static function _getRecursiveFileList($directory = '.') + protected static function _getRecursiveFileList(string $directory = '.'): array { $fileList = []; if (!is_dir($directory)) { @@ -141,8 +148,14 @@ protected static function _getRecursiveFileList($directory = '.') return $fileList; } + /** + * Reload + * + * @param ReflectionClass $aClass + * @return ReflectionClass + */ public function reload(ReflectionClass $aClass): ReflectionClass { - return $this->reload($aClass); + return $this->loader->reload($aClass); } } diff --git a/lib/Cake/TestSuite/CakeTestSuiteCommand.php b/lib/Cake/TestSuite/CakeTestSuiteCommand.php index c71b140cdc..3f698c38e3 100644 --- a/lib/Cake/TestSuite/CakeTestSuiteCommand.php +++ b/lib/Cake/TestSuite/CakeTestSuiteCommand.php @@ -35,11 +35,11 @@ class CakeTestSuiteCommand extends Command /** * Construct method * - * @param mixed $loader The loader instance to use. + * @param string $loader The loader instance to use. * @param array $params list of options to be used for this run * @throws MissingTestLoaderException When a loader class could not be found. */ - public function __construct($loader, $params = []) + public function __construct(string $loader, array $params = []) { if ($loader && !class_exists($loader)) { throw new MissingTestLoaderException(['class' => $loader]); @@ -53,6 +53,21 @@ public function __construct($loader, $params = []) $this->longOptions['output='] = 'handleReporter'; } + /** + * Run + * + * @param array $argv + * @param bool $exit + * @return int + * @throws Exception + */ + public function run(array $argv, bool $exit = true): int + { + $argv[] = $this->_resolveTestFile($this->_params['case'], $this->_params); + + return parent::run($argv, $exit); + } + /** * Handler for customizing the FixtureManager class/ * @@ -87,4 +102,47 @@ public function handleReporter($reporter) return $this->arguments['printer'] = $object; } + + /** + * Convert path fragments used by CakePHP's test runner to absolute paths that can be fed to PHPUnit. + * + * @param string $filePath The file path to load. + * @param array $params Additional parameters. + * @return string Converted path fragments. + */ + protected function _resolveTestFile(string $filePath, array $params): string + { + $basePath = static::_basePath($params) . DS . $filePath; + $ending = 'Test.php'; + + return str_ends_with($basePath, $ending) ? $basePath : $basePath . $ending; + } + + /** + * Generates the base path to a set of tests based on the parameters. + * + * @param array|null $params The path parameters. + * @return string|null The base path. + */ + protected static function _basePath(?array $params): ?string + { + $result = null; + if (!empty($params['core'])) { + $result = CORE_TEST_CASES; + } elseif (!empty($params['plugin'])) { + if (!CakePlugin::loaded($params['plugin'])) { + try { + CakePlugin::load($params['plugin']); + $result = CakePlugin::path($params['plugin']) . 'Test' . DS . 'Case'; + } catch (MissingPluginException) { + } + } else { + $result = CakePlugin::path($params['plugin']) . 'Test' . DS . 'Case'; + } + } elseif (!empty($params['app'])) { + $result = APP_TEST_CASES; + } + + return $result; + } } diff --git a/lib/Cake/TestSuite/CakeTestSuiteDispatcher.php b/lib/Cake/TestSuite/CakeTestSuiteDispatcher.php index 06dfdb6475..29d701fefb 100644 --- a/lib/Cake/TestSuite/CakeTestSuiteDispatcher.php +++ b/lib/Cake/TestSuite/CakeTestSuiteDispatcher.php @@ -256,8 +256,8 @@ protected function _runTestCase() try { static::time(); - $command = new CakeTestSuiteCommand('CakeTestLoader', $commandArgs); - $command->run($options); + $command = new CakeTestSuiteCommand(CakeTestLoader::class, $commandArgs); + $command->run($options, false); } catch (MissingConnectionException $exception) { ob_end_clean(); include CAKE . 'TestSuite' . DS . 'templates' . DS . 'missing_connection.php'; diff --git a/lib/Cake/TestSuite/Reporter/CakeBaseReporter.php b/lib/Cake/TestSuite/Reporter/CakeBaseReporter.php index 765e3cda2c..6b30c1a18d 100644 --- a/lib/Cake/TestSuite/Reporter/CakeBaseReporter.php +++ b/lib/Cake/TestSuite/Reporter/CakeBaseReporter.php @@ -15,20 +15,19 @@ * @license https://opensource.org/licenses/mit-license.php MIT License */ +use PHPUnit\Framework\AssertionFailedError; use PHPUnit\Framework\Test; use PHPUnit\Framework\TestResult; use PHPUnit\Framework\TestSuite; - -if (!class_exists('PHPUnit_TextUI_ResultPrinter')) { - require_once 'PHPUnit/TextUI/ResultPrinter.php'; -} +use PHPUnit\Framework\Warning; +use PHPUnit\TextUI\ResultPrinter; /** * CakeBaseReporter contains common reporting features used in the CakePHP Test suite * * @package Cake.TestSuite.Reporter */ -class CakeBaseReporter extends PHPUnit_TextUI_ResultPrinter +abstract class CakeBaseReporter implements ResultPrinter { /** * Headers sent @@ -51,6 +50,11 @@ class CakeBaseReporter extends PHPUnit_TextUI_ResultPrinter */ protected $_characterSet; + /** + * @var int + */ + protected int $numAssertions = 0; + /** * Does nothing yet. The first output will * be sent on the first test start. @@ -138,7 +142,7 @@ public function baseUrl() * @param TestResult $result The result object * @return void */ - public function printResult(TestResult $result) + public function printResult(TestResult $result): void { $this->paintFooter($result); } @@ -158,11 +162,11 @@ public function paintResult(TestResult $result) * An error occurred. * * @param \PHPUnit\Framework\Test $test The test to add an error for. - * @param Exception $e The exception object to add. + * @param Exception|Throwable $e The exception object to add. * @param float $time The current time. * @return void */ - public function addError(Test $test, Exception $e, $time) + public function addError(Test $test, Exception|Throwable $e, $time): void { $this->paintException($e, $test); } @@ -171,11 +175,11 @@ public function addError(Test $test, Exception $e, $time) * A failure occurred. * * @param \PHPUnit\Framework\Test $test The test that failed - * @param PHPUnit_Framework_AssertionFailedError $e The assertion that failed. + * @param AssertionFailedError $e The assertion that failed. * @param float $time The current time. * @return void */ - public function addFailure(Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) + public function addFailure(Test $test, AssertionFailedError $e, $time): void { $this->paintFail($e, $test); } @@ -184,11 +188,11 @@ public function addFailure(Test $test, PHPUnit_Framework_AssertionFailedError $e * Incomplete test. * * @param \PHPUnit\Framework\Test $test The test that was incomplete. - * @param Exception $e The incomplete exception + * @param Exception|Throwable $e The incomplete exception * @param float $time The current time. * @return void */ - public function addIncompleteTest(Test $test, Exception $e, $time) + public function addIncompleteTest(Test $test, Exception|Throwable $e, $time): void { $this->paintSkip($e, $test); } @@ -197,11 +201,11 @@ public function addIncompleteTest(Test $test, Exception $e, $time) * Skipped test. * * @param \PHPUnit\Framework\Test $test The test that failed. - * @param Exception $e The skip object. + * @param Exception|Throwable $e The skip object. * @param float $time The current time. * @return void */ - public function addSkippedTest(Test $test, Exception $e, $time) + public function addSkippedTest(Test $test, Exception|Throwable $e, $time): void { $this->paintSkip($e, $test); } @@ -212,7 +216,7 @@ public function addSkippedTest(Test $test, Exception $e, $time) * @param TestSuite $suite The suite to start * @return void */ - public function startTestSuite(TestSuite $suite) + public function startTestSuite(TestSuite $suite): void { if (!$this->_headerSent) { echo $this->paintHeader(); @@ -226,7 +230,7 @@ public function startTestSuite(TestSuite $suite) * @param TestSuite $suite The suite that ended. * @return void */ - public function endTestSuite(TestSuite $suite) + public function endTestSuite(TestSuite $suite): void { } @@ -236,7 +240,7 @@ public function endTestSuite(TestSuite $suite) * @param \PHPUnit\Framework\Test $test The test that started. * @return void */ - public function startTest(Test $test) + public function startTest(Test $test): void { } @@ -247,7 +251,7 @@ public function startTest(Test $test) * @param float $time The current time. * @return void */ - public function endTest(Test $test, $time) + public function endTest(Test $test, $time): void { $this->numAssertions += $test->getNumAssertions(); if ($test->hasFailed()) { @@ -255,4 +259,34 @@ public function endTest(Test $test, $time) } $this->paintPass($test, $time); } + + /** + * @param string $buffer + * @return void + */ + public function write(string $buffer): void + { + echo $buffer; + } + + /** + * @param Test $test + * @param Warning $e + * @param float $time + * @return void + */ + public function addWarning(Test $test, Warning $e, float $time): void + { + $this->paintFail($e, $test); + } + + /** + * @param Test $test + * @param Throwable $t + * @param float $time + * @return void + */ + public function addRiskyTest(Test $test, Throwable $t, float $time): void + { + } } diff --git a/lib/Cake/TestSuite/Reporter/CakeHtmlReporter.php b/lib/Cake/TestSuite/Reporter/CakeHtmlReporter.php index 2e6701b878..f124f6dd7d 100644 --- a/lib/Cake/TestSuite/Reporter/CakeHtmlReporter.php +++ b/lib/Cake/TestSuite/Reporter/CakeHtmlReporter.php @@ -76,6 +76,7 @@ public function sendContentType() */ public function paintDocumentStart() { + $baseDir = $this->params['baseDir']; include CAKE . 'TestSuite' . DS . 'templates' . DS . 'header.php'; } @@ -89,6 +90,7 @@ public function paintTestMenu() { $plugins = App::objects('plugin', null, false); sort($plugins); + $cases = '?'; include CAKE . 'TestSuite' . DS . 'templates' . DS . 'menu.php'; } @@ -155,7 +157,6 @@ public function sendNoCacheHeaders() public function paintFooter(TestResult $result) { echo $this->_buffer; - ob_end_flush(); $colour = ($result->failureCount() + $result->errorCount() > 0 ? 'red' : 'green'); echo "\n"; @@ -209,21 +210,7 @@ public function paintCoverage(array $coverage) */ protected function _paintLinks() { - $show = $query = []; - if (!empty($this->params['case'])) { - $show['show'] = 'cases'; - } - - if (!empty($this->params['core'])) { - $show['core'] = $query['core'] = 'true'; - } - if (!empty($this->params['plugin'])) { - $show['plugin'] = $query['plugin'] = $this->params['plugin']; - } - if (!empty($this->params['case'])) { - $query['case'] = $this->params['case']; - } - [$show, $query] = str_split($this->_getQueryLink()); + [$show, $query] = $this->_getQueryLink(); echo "

    Run more tests | Show Passes | \n"; echo "Enable Debug Output | \n"; @@ -256,6 +243,7 @@ protected function _queryString($url) */ public function paintDocumentEnd() { + $baseDir = $this->params['baseDir']; include CAKE . 'TestSuite' . DS . 'templates' . DS . 'footer.php'; if (ob_get_length()) { ob_end_flush(); @@ -307,7 +295,7 @@ public function paintFail($message, $test) echo "\n"; echo "

    " . __d('cake_dev', 'Test case: %s', $testName) . "
    \n"; if (!str_contains($className, 'PHPUnit_')) { - [, $query] = str_split($this->_getQueryLink()); + [, $query] = $this->_getQueryLink(); echo "\n"; } echo "
    " . __d('cake_dev', 'Stack trace:') . '
    ' . $trace . "
    \n"; @@ -428,7 +416,7 @@ protected function _getStackTrace(Exception $e) * @param TestSuite $suite The test suite to start. * @return void */ - public function startTestSuite(TestSuite $suite) + public function startTestSuite(TestSuite $suite): void { if (!$this->_headerSent) { $this->paintHeader(); @@ -439,9 +427,9 @@ public function startTestSuite(TestSuite $suite) /** * Returns the query string formatted for ouput in links * - * @return string + * @return array{string, string} */ - protected function _getQueryLink() + protected function _getQueryLink(): array { $show = $query = []; if (!empty($this->params['case'])) { diff --git a/lib/Cake/TestSuite/templates/header.php b/lib/Cake/TestSuite/templates/header.php index 0504451d91..f8d1e21d83 100644 --- a/lib/Cake/TestSuite/templates/header.php +++ b/lib/Cake/TestSuite/templates/header.php @@ -1,26 +1,6 @@ - * Copyright (c) Cake Software Foundation, Inc. (https://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. (https://cakefoundation.org) - * @link https://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests - * @package Cake.TestSuite.templates - * @since CakePHP(tm) v 1.2.0.4433 - * @license https://opensource.org/licenses/mit-license.php MIT License - */ -?> - - - - - CakePHP Test Suite <?php echo Configure::version(); ?> + +?>